Export linked grader hint feedback#780
Conversation
Co-authored-by: Jonathan Bell <jon@jonbell.net>
|
Warning Review limit reached
More reviews will be available in 14 minutes and 4 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (12)
WalkthroughAdds server-side pepper-backed tokenization (salt+pepper), new CLI export options and validation, streaming export utilities and helpers, rewrites assignment/submissions export to sectioned/paginated streams, emits hints/LLM-derived hints with deduplication, exports error-pin engagement rows, and extends transient-stream error detection and tests. ChangesAssessment Export with Server-Side Pepper Tokenization
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-authored-by: Jonathan Bell <jon@jonbell.net>
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
supabase/functions/cli/commands/assessment.ts (1)
1373-1384:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix
test_output_max_bytestruncation to use UTF-8 byte length (notstring.length) inassessment.ts(supabase/functions/cli/commands/assessment.ts:1373-1384)
row.outputis astring | null, but the code usesoutput.lengthandoutput.slice(0, outputMaxBytes), which count UTF-16 code units—not UTF-8 bytes. This makes both:
record.output_truncateddecision incorrect for non-ASCII outputrecord.output_full_bytes = output.lengthincorrectTruncate by UTF-8 byte length (e.g., iterate with
TextEncoder/TextDecoderor equivalent) and setoutput_full_bytesto the UTF-8 byte length.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@supabase/functions/cli/commands/assessment.ts` around lines 1373 - 1384, The truncation logic in assessment.ts currently uses string.length and slice which count UTF-16 code units; change it to compute the UTF-8 byte length of row.output (use TextEncoder to get a Uint8Array), set record.output_full_bytes to that byte length, and when output exceeds outputMaxBytes truncate by UTF-8 bytes (slice the encoded bytes to outputMaxBytes and decode back to a string with TextDecoder) so record.output contains a properly truncated UTF-8-safe string and record.output_truncated is set accordingly; update the branches that reference output, outputMaxBytes, record.output, record.output_truncated, and record.output_full_bytes to use this byte-based approach.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cli/commands/assessment/export.ts`:
- Around line 520-530: The pagination loop using batchIndex and the returned
next cursor (from streamAssignmentSection ->
page.endRecord.next_score_review_batch_index) must guard against non-advancing
cursors; update the loop to break (or throw) when next is not a number OR when
next <= batchIndex to prevent infinite loops and repeated edge calls. Do the
same change for the sibling loops that read next_answer_review_batch_index /
other next_*_batch_index cursors (the loops that call mergeBuckets,
addPageCounts, assertExpectedCount), i.e. only assign batchIndex = next when
typeof next === "number" && next > batchIndex, otherwise exit the loop
(optionally log a warning).
In `@supabase/functions/cli/commands/assessment.ts`:
- Around line 758-773: The switch over section (derived from params.section in
assessment.ts) currently treats unknown values as "all" via the default case,
which causes typos like "score" to run exportAssignmentAll; change this to
explicitly reject invalid section values by validating params.section (or the
computed const section) against the allowed AssignmentExportSection values and
replacing the switch default with logic that throws/returns a 400 Bad Request
(or calls the existing request-error helper) when the value is not one of
"meta","submissions","scores","tests","engagement","all"; update the switch in
the same function to only handle the known cases (exportAssignmentMeta,
exportAssignmentSubmissions, exportAssignmentScores, exportAssignmentTests,
exportAssignmentEngagement, exportAssignmentAll) and ensure unknown inputs
produce an immediate error response instead of falling back to
exportAssignmentAll.
- Around line 454-468: slimExtraDataForExport currently destructures prompt and
result into _prompt/_result but leaves them unused which trips
`@typescript-eslint/no-unused-vars`; after the destructuring in
slimExtraDataForExport (where llmObj and { prompt: _prompt, result: _result,
...llmRest } are declared) explicitly mark those vars as used by adding short
no-op references (for example: void _prompt; void _result;) before the return so
ESLint stops complaining while preserving the existing shape logic for llmObj
and llmRest.
In `@tests/unit/assessment-export-tokenization.test.ts`:
- Line 13: Update the import statement in the test to use the project-root alias
instead of the relative path: replace the relative import that currently pulls
createTokenizer, generateRandomSalt, and base32 from
"../../supabase/functions/cli/utils/tokenization" with the alias import from
"`@/supabase/functions/cli/utils/tokenization`" so the test imports
createTokenizer, generateRandomSalt, and base32 via the "`@/`..." alias.
---
Outside diff comments:
In `@supabase/functions/cli/commands/assessment.ts`:
- Around line 1373-1384: The truncation logic in assessment.ts currently uses
string.length and slice which count UTF-16 code units; change it to compute the
UTF-8 byte length of row.output (use TextEncoder to get a Uint8Array), set
record.output_full_bytes to that byte length, and when output exceeds
outputMaxBytes truncate by UTF-8 bytes (slice the encoded bytes to
outputMaxBytes and decode back to a string with TextDecoder) so record.output
contains a properly truncated UTF-8-safe string and record.output_truncated is
set accordingly; update the branches that reference output, outputMaxBytes,
record.output, record.output_truncated, and record.output_full_bytes to use this
byte-based approach.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 87d5ec32-d86b-420a-987e-d84f6df2646f
📒 Files selected for processing (8)
cli/commands/assessment/deanonymize.tscli/commands/assessment/export.tscli/utils/transientRetry.tssupabase/functions/cli/commands/assessment.tssupabase/functions/cli/utils/tokenization.tssupabase/migrations/20260522143000_assessment_export_pepper.sqltests/unit/assessment-export-tokenization.test.tstests/unit/cli-transient-retry.test.ts
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (7)
cli/utils/exportFiles.ts (1)
54-80: ⚖️ Poor tradeoffShared utilities are duplicated in
cli/commands/assessment/export.ts.The
writeJsonArray,sanitizeForFilename,timestamp,generateRandomSalt, andbase32Encodefunctions in this shared module are also defined locally incli/commands/assessment/export.ts. Consider updating that file to import from this shared module to maintain a single source of truth.Also applies to: 94-127
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cli/utils/exportFiles.ts` around lines 54 - 80, The functions writeJsonArray, sanitizeForFilename, timestamp, generateRandomSalt, and base32Encode are duplicated in cli/commands/assessment/export.ts; remove the local copies there and import these utilities from cli/utils/exportFiles (export them from this module if not already exported). Update the assessment export code to reference the shared symbols (writeJsonArray, sanitizeForFilename, timestamp, generateRandomSalt, base32Encode) via imports, ensure any TypeScript types/exports are adjusted in cli/utils/exportFiles to be public, and run a quick compile to fix any leftover import/type errors.supabase/functions/cli/commands/submissions.ts (1)
606-725: 💤 Low valueConsider using a
Setfor section validation likeassessment.tsdoes.The assessment export command uses
ASSIGNMENT_EXPORT_SECTIONSset with explicit validation before the switch. This submissions export relies on the finalthrowat line 724 after the if-else chain. While functionally correct, the explicit set validation pattern is clearer and easier to maintain.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@supabase/functions/cli/commands/submissions.ts` around lines 606 - 725, The handler handleSubmissionsExport currently falls through to a final throw for invalid section values; add an explicit Set of allowed sections (like ASSIGNMENT_EXPORT_SECTIONS used in assessment.ts) and validate params.section (or computed section variable) at the top of the function—if the section is not in the Set throw a CLICommandError immediately—so the allowed values are declared in one place and the rest of the if/branch logic can assume a valid section.cli/commands/submissions/export.ts (1)
351-363: 💤 Low value
runWithConcurrencyis duplicated fromcli/commands/assessment/export.ts.Consider extracting this utility to a shared module (e.g.,
cli/utils/concurrency.ts) to avoid code duplication and ensure consistent behavior across export commands.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cli/commands/submissions/export.ts` around lines 351 - 363, The runWithConcurrency function is duplicated; extract it into a shared utility module (e.g., utils/concurrency.ts) and replace the duplicate implementations by importing that exported function. Specifically, move the implementation of runWithConcurrency (the async function that takes tasks and concurrency, manages nextIdx, workers array and fills results) into the new module, export it, update this file to import runWithConcurrency instead of declaring it, and update the other file (assessment export) to import the same exported function so both use the single shared implementation.tests/unit/submissions-export-files.test.ts (1)
5-6: ⚡ Quick winUse
@/*aliases for these test imports.These should use root aliases instead of relative traversal.
Proposed change
-import { createTokenizer } from "../../supabase/functions/cli/utils/tokenization"; -import { buildFileExportRecord } from "../../supabase/functions/cli/utils/submissionFilesExportStream"; +import { createTokenizer } from "`@/supabase/functions/cli/utils/tokenization`"; +import { buildFileExportRecord } from "`@/supabase/functions/cli/utils/submissionFilesExportStream`";As per coding guidelines,
**/*.{ts,tsx,js,jsx}: Use@/*path alias to reference files from project root.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/submissions-export-files.test.ts` around lines 5 - 6, Replace the relative traversal imports in the test with root path aliases: change the import of createTokenizer from "../../supabase/functions/cli/utils/tokenization" to "`@/supabase/functions/cli/utils/tokenization`" and change the import of buildFileExportRecord from "../../supabase/functions/cli/utils/submissionFilesExportStream" to "`@/supabase/functions/cli/utils/submissionFilesExportStream`" so the test imports use the `@/` alias and reference the same exported symbols createTokenizer and buildFileExportRecord.supabase/functions/cli/utils/filePathMatchers.ts (1)
36-44: ⚡ Quick winCache compiled glob regexes in matcher hot path.
Line 37 recompiles the same pattern repeatedly for each file row. A tiny cache avoids repeated compile overhead during large exports.
Proposed refactor
+const globRegExpCache = new Map<string, RegExp>(); + function matchesGlob(pattern: string, path: string): boolean { - const re = globPatternToRegExp(pattern); + let re = globRegExpCache.get(pattern); + if (!re) { + re = globPatternToRegExp(pattern); + globRegExpCache.set(pattern, re); + } if (re.test(path)) return true; // Patterns without / also match the basename (e.g. *.java matches src/Main.java).Also applies to: 54-58
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@supabase/functions/cli/utils/filePathMatchers.ts` around lines 36 - 44, The matchesGlob function recompiles the same glob pattern for every path; add a module-level cache Map<string, RegExp> (e.g., compiledGlobCache) and use it inside matchesGlob: look up pattern, call globPatternToRegExp only if not cached, store the RegExp, then reuse it for both the full-path test and the basename test; apply the same caching change to the similar matcher function around lines 54-58 that also calls globPatternToRegExp so both hot paths reuse compiled regexes.tests/unit/submissions-export-file-filters.test.ts (1)
5-5: ⚡ Quick winUse the
@/*alias for this test import.Replace the relative path with the project-root alias.
Proposed change
-import { matchesSubmissionFilePath } from "../../supabase/functions/cli/utils/filePathMatchers"; +import { matchesSubmissionFilePath } from "`@/supabase/functions/cli/utils/filePathMatchers`";As per coding guidelines,
**/*.{ts,tsx,js,jsx}: Use@/*path alias to reference files from project root.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/submissions-export-file-filters.test.ts` at line 5, The import in tests/unit/submissions-export-file-filters.test.ts should use the project-root alias instead of a relative path; update the import that references matchesSubmissionFilePath to use the "`@/`..." alias (e.g., import from "`@/supabase/functions/cli/utils/filePathMatchers`") so the test follows the `@/*` path alias convention and resolves consistently across the project.tests/unit/sanitize-grading-paths.test.ts (1)
5-9: ⚡ Quick winSwitch test import to the
@/*root alias.Use the project-root alias here instead of a deep relative path.
Proposed change
import { prepareInstructorBuildOutput, sanitizeGradingPaths, sliceOutputFromSentinel -} from "../../supabase/functions/cli/utils/sanitizeGradingPaths"; +} from "`@/supabase/functions/cli/utils/sanitizeGradingPaths`";As per coding guidelines,
**/*.{ts,tsx,js,jsx}: Use@/*path alias to reference files from project root.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/sanitize-grading-paths.test.ts` around lines 5 - 9, Replace the deep relative import in the test with the project-root alias: update the import that currently brings in prepareInstructorBuildOutput, sanitizeGradingPaths, and sliceOutputFromSentinel from "../../supabase/functions/cli/utils/sanitizeGradingPaths" to use the "`@/`…" root alias (e.g. import { prepareInstructorBuildOutput, sanitizeGradingPaths, sliceOutputFromSentinel } from "`@/supabase/functions/cli/utils/sanitizeGradingPaths`"); ensure the symbols remain the same and the path resolves via the project's path alias configuration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cli/commands/submissions/export.ts`:
- Around line 281-284: The loop that paginates file batches only checks typeof
next_files_batch_index and can infinite-loop if the server returns the same or
lower index; update the loop that uses filesBatchIndex and
next_files_batch_index to detect non-advancing cursors (e.g., require next >
filesBatchIndex) and break or throw when the cursor does not advance; preferably
reuse the existing advanceBatchCursor helper (or implement equivalent logic) to
compare next and filesBatchIndex, log an error message referencing
next_files_batch_index and filesBatchIndex, and stop pagination to avoid
infinite loops.
In `@supabase/functions/cli/utils/submissionExportStream.ts`:
- Around line 21-30: In streamSubmissions, add an early guard that validates the
mode/tokenizer invariant: if mode is 'hash' or 'opaque' and tokenizer is null,
throw a clear error (e.g., throw new Error(...)) before any writing occurs so we
don't emit raw IDs for submission/subject/group; place this check near the start
of streamSubmissions (after includeOrdinal is set) to fail fast and document the
expectation in the error message.
In `@supabase/functions/cli/utils/submissionFilesExportStream.ts`:
- Around line 79-86: The warning records are currently emitting raw
row.submission_id to writer.write (kind: "warning") which leaks real IDs when
tokenized mode is enabled; update the two places that write these warnings (the
block using row.submission_id at lines shown and the similar block at 94-99) to
check the module's tokenized/identity mode flag and, if tokenized mode is
active, replace submission_id with the tokenized field (e.g., submission_token
or tokenized_submission_id) or omit the raw submission_id, using the existing
tokenization helper in this module (or add one) to generate the token; ensure
you only change the payload for writer.write calls that include submission_id so
identity-mode consistency is preserved.
- Around line 157-160: The truthy check for input.content_base64 in
buildFileExportRecord treats an empty string (valid base64 for zero bytes) as
omitted; change the condition so it checks for explicit null/undefined (e.g.,
input.content_base64 !== undefined && input.content_base64 !== null) instead of
a truthy check, then assign record.content_base64 = input.content_base64 and set
record.binary_omitted = false when input.is_binary && input.withBinary and the
content is present (including ""), otherwise mark binary_omitted true; reference
buildFileExportRecord, input.is_binary, input.withBinary, input.content_base64,
record.content_base64, and record.binary_omitted when making the change.
---
Nitpick comments:
In `@cli/commands/submissions/export.ts`:
- Around line 351-363: The runWithConcurrency function is duplicated; extract it
into a shared utility module (e.g., utils/concurrency.ts) and replace the
duplicate implementations by importing that exported function. Specifically,
move the implementation of runWithConcurrency (the async function that takes
tasks and concurrency, manages nextIdx, workers array and fills results) into
the new module, export it, update this file to import runWithConcurrency instead
of declaring it, and update the other file (assessment export) to import the
same exported function so both use the single shared implementation.
In `@cli/utils/exportFiles.ts`:
- Around line 54-80: The functions writeJsonArray, sanitizeForFilename,
timestamp, generateRandomSalt, and base32Encode are duplicated in
cli/commands/assessment/export.ts; remove the local copies there and import
these utilities from cli/utils/exportFiles (export them from this module if not
already exported). Update the assessment export code to reference the shared
symbols (writeJsonArray, sanitizeForFilename, timestamp, generateRandomSalt,
base32Encode) via imports, ensure any TypeScript types/exports are adjusted in
cli/utils/exportFiles to be public, and run a quick compile to fix any leftover
import/type errors.
In `@supabase/functions/cli/commands/submissions.ts`:
- Around line 606-725: The handler handleSubmissionsExport currently falls
through to a final throw for invalid section values; add an explicit Set of
allowed sections (like ASSIGNMENT_EXPORT_SECTIONS used in assessment.ts) and
validate params.section (or computed section variable) at the top of the
function—if the section is not in the Set throw a CLICommandError immediately—so
the allowed values are declared in one place and the rest of the if/branch logic
can assume a valid section.
In `@supabase/functions/cli/utils/filePathMatchers.ts`:
- Around line 36-44: The matchesGlob function recompiles the same glob pattern
for every path; add a module-level cache Map<string, RegExp> (e.g.,
compiledGlobCache) and use it inside matchesGlob: look up pattern, call
globPatternToRegExp only if not cached, store the RegExp, then reuse it for both
the full-path test and the basename test; apply the same caching change to the
similar matcher function around lines 54-58 that also calls globPatternToRegExp
so both hot paths reuse compiled regexes.
In `@tests/unit/sanitize-grading-paths.test.ts`:
- Around line 5-9: Replace the deep relative import in the test with the
project-root alias: update the import that currently brings in
prepareInstructorBuildOutput, sanitizeGradingPaths, and sliceOutputFromSentinel
from "../../supabase/functions/cli/utils/sanitizeGradingPaths" to use the "`@/`…"
root alias (e.g. import { prepareInstructorBuildOutput, sanitizeGradingPaths,
sliceOutputFromSentinel } from
"`@/supabase/functions/cli/utils/sanitizeGradingPaths`"); ensure the symbols
remain the same and the path resolves via the project's path alias
configuration.
In `@tests/unit/submissions-export-file-filters.test.ts`:
- Line 5: The import in tests/unit/submissions-export-file-filters.test.ts
should use the project-root alias instead of a relative path; update the import
that references matchesSubmissionFilePath to use the "`@/`..." alias (e.g., import
from "`@/supabase/functions/cli/utils/filePathMatchers`") so the test follows the
`@/*` path alias convention and resolves consistently across the project.
In `@tests/unit/submissions-export-files.test.ts`:
- Around line 5-6: Replace the relative traversal imports in the test with root
path aliases: change the import of createTokenizer from
"../../supabase/functions/cli/utils/tokenization" to
"`@/supabase/functions/cli/utils/tokenization`" and change the import of
buildFileExportRecord from
"../../supabase/functions/cli/utils/submissionFilesExportStream" to
"`@/supabase/functions/cli/utils/submissionFilesExportStream`" so the test imports
use the `@/` alias and reference the same exported symbols createTokenizer and
buildFileExportRecord.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 4da1b1ac-8872-4784-9639-79232e03f1e3
📒 Files selected for processing (17)
cli/commands/assessment/export.tscli/commands/submissions/export.tscli/commands/submissions/index.tscli/utils/exportFiles.tssupabase/functions/_shared/pawtograderYmlHelpers.tssupabase/functions/cli/commands/assessment.tssupabase/functions/cli/commands/submissions.tssupabase/functions/cli/utils/assessmentExportPepper.tssupabase/functions/cli/utils/exportIdentity.tssupabase/functions/cli/utils/filePathMatchers.tssupabase/functions/cli/utils/sanitizeGradingPaths.tssupabase/functions/cli/utils/submissionExportStream.tssupabase/functions/cli/utils/submissionFilesExportStream.tstests/unit/sanitize-grading-paths.test.tstests/unit/submissions-export-file-filters.test.tstests/unit/submissions-export-files.test.tstests/unit/viewAsStudentDataMask.test.ts
|
Addressed the remaining CodeRabbit feedback plus a new privacy hardening: Resolved review threads (4 major/minor):
Nitpicks:
New: obfuscate repository name + commit SHA in non-raw submission exports. |
…ion exports
- Guard non-advancing next_files_batch_index cursor (submissions/export.ts)
- Enforce mode/tokenizer invariant in streamSubmissions (fail fast)
- Emit tokenized submission ref (not raw submission_id) in file warning records
- Treat zero-byte binary ("") as present in buildFileExportRecord
- Validate section via SUBMISSIONS_EXPORT_SECTIONS set
- Cache compiled glob regexes in filePathMatchers
- Extract runWithConcurrency to cli/utils/concurrency.ts; dedup assessment export helpers
- Use @/* alias in three unit-test imports
- Obfuscate student repository name and commit SHA (new repository/commit token
kinds) in hash/opaque submission exports; raw mode unchanged
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The submissions-export-files unit test imported buildFileExportRecord from submissionFilesExportStream.ts, which transitively pulls Deno-only modules (supabase client, .ts-extension imports) into the Next.js tsc program and broke the type-check. Move the pure helper into a self-contained submissionFileExportRecord.ts (matching the repo's testable-CLI-module convention), re-export it for the Deno consumer, and point the test there. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
grader_result_testsids sohints.jsononly contains rows linked to exported tests.extra_datafield on emitted grader test records.error-pin-engagement.json.Testing
npm run formatnpm run lintnpm test -- --runTestsByPath tests/unit/assessment-export-tokenization.test.ts tests/unit/assessment-export-selectors.test.tsnode -e "const fs=require('fs'); const edge=fs.readFileSync('supabase/functions/cli/commands/assessment.ts','utf8'); const cli=fs.readFileSync('cli/commands/assessment/export.ts','utf8'); if(!edge.includes('kind: \\\"error_pin_engagement\\\"')) throw new Error('edge stream does not emit error_pin_engagement'); if(!edge.includes('.from(\\\"discussion_thread_read_status\\\")')) throw new Error('read status is not exported'); if(!edge.includes('.from(\\\"discussion_thread_likes\\\")')) throw new Error('likes are not exported'); if(!cli.includes('error-pin-engagement.json')) throw new Error('CLI does not write error-pin-engagement.json'); console.log('assessment export includes error-pin engagement read/like wiring');"Notes
npx -y deno check cli/commands/assessment.tswas attempted; it reaches the function but fails on the generatedsupabase/functions/_shared/SupabaseTypes.d.tsexport const Constantsambient declaration before checking this patch.npx tsc --noEmit --pretty falsewas attempted; it fails on the pre-existingtests/e2e/active-submission-gradebook-db.spec.ts(49,5)nullable string assignment.Summary by CodeRabbit
New Features
Improvements