lazycodex-ai 5.1.43 → 5.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +948 -416
- package/dist/cli/service-auth/keystore.d.ts +4 -2
- package/dist/cli-node/index.js +948 -416
- package/docs/reference/web-terminal-visual-qa.md +8 -0
- package/package.json +1 -1
- package/packages/lsp-daemon/dist/cli.js +4 -4
- package/packages/lsp-daemon/dist/client.js +4 -4
- package/packages/lsp-daemon/dist/index.js +4 -4
- package/packages/lsp-daemon/package.json +3 -3
- package/packages/lsp-tools-mcp/dist/cli.js +4 -4
- package/packages/lsp-tools-mcp/dist/mcp.js +4 -4
- package/packages/lsp-tools-mcp/dist/tools.js +4 -4
- package/packages/lsp-tools-mcp/package.json +3 -3
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +62 -21
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/biome.json +1 -21
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +4 -4
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +1 -21
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +4 -4
- package/packages/omo-codex/plugin/components/lsp/biome.json +1 -21
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +4 -4
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +4 -4
- package/packages/omo-codex/plugin/components/lsp/scripts/build-runtime.mjs +0 -1
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook-not-installed.test.ts +1 -1
- package/packages/omo-codex/plugin/components/rules/biome.json +1 -21
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +4 -4
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/biome.json +1 -21
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +90 -1
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +91 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +4 -4
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/biome.json +1 -21
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/biome.json +1 -21
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/biome.json +1 -21
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +7 -7
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-mutations.mjs +2 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +7 -7
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +2 -0
- package/packages/omo-codex/plugin/skills/browser/SKILL.md +21 -22
- package/packages/omo-codex/plugin/skills/browser/references/commands.md +2 -9
- package/packages/omo-codex/plugin/skills/browser/references/install.md +1 -2
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-doctor.mjs +2 -2
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-engine-guard.mjs +63 -487
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-install.mjs +1 -1
- package/packages/omo-codex/plugin/skills/browser/scripts/omowright.mjs +1 -10
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +79 -118
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +75 -224
- package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +32 -27
- package/packages/omo-codex/plugin/skills/frontend/references/perfection/README.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/check-accent-stripes.ts +8 -24
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/check-draft-guard.ts +40 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/collect-files.ts +53 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/draft-guard/findings.ts +16 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/draft-guard/lint.ts +38 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/draft-guard/rules.ts +69 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/draft-guard/text-nodes.ts +121 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/attr-lookalikes.tsx +10 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/bound-values.tsx +12 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/const-generics.tsx +3 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/generics.tsx +7 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/measured-stats.html +6 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/plain-copy.html +9 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/state-copy.html +11 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/attribute-edges.html +7 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/components.tsx +16 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/decorative-badge.vue +7 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/emoji-icons.tsx +9 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/jsx-edges.tsx +1 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/promo-copy.html +6 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/promo-copy.tsx +8 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/vanity-stats.html +5 -0
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +10 -7
- package/packages/omo-codex/plugin/skills/programming/references/typescript/README.md +10 -7
- package/packages/omo-codex/plugin/skills/programming/references/typescript/bootstrap.md +9 -23
- package/packages/omo-codex/plugin/skills/programming/references/typescript/oxc-lint.md +130 -0
- package/packages/omo-codex/plugin/skills/programming/references/typescript/tsconfig-strict.md +6 -62
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +12 -12
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/new-project.ts +20 -81
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/.oxfmtrc.json +9 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/.oxlintrc.json +46 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/LICENSE +21 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/index.js +10 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/no-em-dash-copy.js +28 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/require-suppression-reason.js +62 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/oxc/tsconfig.json +29 -0
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +14 -14
- package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/AGENTS.md +9 -3
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +7 -6
- package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger-grammar.md +116 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/report-gates.md +51 -3
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/claims-index.mjs +125 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/contracts.mjs +68 -3
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger-kinds.mjs +136 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger-schema.mjs +204 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger.mjs +103 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-brief.mjs +145 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-state.mjs +63 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-static.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-structure.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-text.mjs +1 -27
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/lexicon.mjs +47 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/numerals.mjs +226 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/outcome.mjs +2 -3
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/particles-ko.mjs +108 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/rational.mjs +139 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools-commands.mjs +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/sentence-split.mjs +77 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/text-normalize.mjs +82 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/text-similarity.mjs +28 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/units.mjs +105 -0
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +71 -64
- package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +4 -1
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +6 -6
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +152 -23
- package/packages/shared-skills/skills/browser/SKILL.md +21 -22
- package/packages/shared-skills/skills/browser/references/commands.md +2 -9
- package/packages/shared-skills/skills/browser/references/install.md +1 -2
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/shared-skills/skills/browser/scripts/browser-doctor.mjs +2 -2
- package/packages/shared-skills/skills/browser/scripts/browser-engine-guard.mjs +63 -487
- package/packages/shared-skills/skills/browser/scripts/browser-install.mjs +1 -1
- package/packages/shared-skills/skills/browser/scripts/omowright.mjs +1 -10
- package/packages/shared-skills/skills/frontend/SKILL.md +79 -118
- package/packages/shared-skills/skills/frontend/references/design/README.md +75 -224
- package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +32 -27
- package/packages/shared-skills/skills/frontend/references/perfection/README.md +2 -2
- package/packages/shared-skills/skills/frontend/scripts/perfection/check-accent-stripes.ts +8 -24
- package/packages/shared-skills/skills/frontend/scripts/perfection/check-draft-guard.test.ts +101 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/check-draft-guard.ts +40 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/collect-files.test.ts +50 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/collect-files.ts +53 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/draft-guard/findings.ts +16 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/draft-guard/lint.ts +38 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/draft-guard/rules.ts +69 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/draft-guard/text-nodes.ts +121 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/attr-lookalikes.tsx +10 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/bound-values.tsx +12 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/const-generics.tsx +3 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/generics.tsx +7 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/measured-stats.html +6 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/plain-copy.html +9 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/negative/state-copy.html +11 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/attribute-edges.html +7 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/components.tsx +16 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/decorative-badge.vue +7 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/emoji-icons.tsx +9 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/jsx-edges.tsx +1 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/promo-copy.html +6 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/promo-copy.tsx +8 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/draft-guard/positive/vanity-stats.html +5 -0
- package/packages/shared-skills/skills/programming/SKILL.md +10 -7
- package/packages/shared-skills/skills/programming/references/typescript/README.md +10 -7
- package/packages/shared-skills/skills/programming/references/typescript/bootstrap.md +9 -23
- package/packages/shared-skills/skills/programming/references/typescript/oxc-lint.md +130 -0
- package/packages/shared-skills/skills/programming/references/typescript/tsconfig-strict.md +6 -62
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +12 -12
- package/packages/shared-skills/skills/programming/scripts/typescript/new-project.test.ts +162 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/new-project.ts +20 -81
- package/packages/shared-skills/skills/programming/scripts/typescript/oxc/.oxfmtrc.json +9 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/oxc/.oxlintrc.json +46 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/LICENSE +21 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/index.js +10 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/no-em-dash-copy.js +28 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/oxc/lint/oxlint-plugin/require-suppression-reason.js +62 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/oxc/tsconfig.json +29 -0
- package/packages/shared-skills/skills/refactor/SKILL.md +13 -13
- package/packages/shared-skills/skills/ulw-execute/SKILL.md +1 -1
- package/packages/shared-skills/skills/ulw-research/AGENTS.md +9 -3
- package/packages/shared-skills/skills/ulw-research/SKILL.md +2 -2
- package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +7 -6
- package/packages/shared-skills/skills/ulw-research/references/fact-ledger-grammar.md +116 -0
- package/packages/shared-skills/skills/ulw-research/references/report-gates.md +51 -3
- package/packages/shared-skills/skills/ulw-research/scripts/claims-index.mjs +125 -0
- package/packages/shared-skills/skills/ulw-research/scripts/claims-index.test.ts +149 -0
- package/packages/shared-skills/skills/ulw-research/scripts/contracts.mjs +68 -3
- package/packages/shared-skills/skills/ulw-research/scripts/contracts.test.ts +97 -12
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-grammar.test.ts +190 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.mjs +136 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.test.ts +141 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-schema.mjs +204 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-schema.test.ts +43 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger.mjs +103 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger.test.ts +252 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-brief.mjs +145 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-brief.test.ts +179 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-state.mjs +63 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-state.test.ts +46 -0
- package/packages/shared-skills/skills/ulw-research/scripts/gates-context.test.ts +64 -0
- package/packages/shared-skills/skills/ulw-research/scripts/gates-static.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/scripts/gates-structure.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/scripts/gates-text.mjs +1 -27
- package/packages/shared-skills/skills/ulw-research/scripts/lexicon.mjs +47 -0
- package/packages/shared-skills/skills/ulw-research/scripts/lexicon.test.ts +57 -0
- package/packages/shared-skills/skills/ulw-research/scripts/numerals.mjs +226 -0
- package/packages/shared-skills/skills/ulw-research/scripts/numerals.test.ts +120 -0
- package/packages/shared-skills/skills/ulw-research/scripts/outcome.mjs +2 -3
- package/packages/shared-skills/skills/ulw-research/scripts/outcome.test.ts +29 -0
- package/packages/shared-skills/skills/ulw-research/scripts/particles-ko.mjs +108 -0
- package/packages/shared-skills/skills/ulw-research/scripts/particles-ko.test.ts +86 -0
- package/packages/shared-skills/skills/ulw-research/scripts/rational.mjs +139 -0
- package/packages/shared-skills/skills/ulw-research/scripts/rational.test.ts +46 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-commands.mjs +2 -2
- package/packages/shared-skills/skills/ulw-research/scripts/sentence-split.mjs +77 -0
- package/packages/shared-skills/skills/ulw-research/scripts/sentence-split.test.ts +109 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/claim-graph.md +13 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity-brief-locked.md +17 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity-brief-pending.md +17 -0
- package/packages/shared-skills/skills/ulw-research/scripts/text-normalize.mjs +82 -0
- package/packages/shared-skills/skills/ulw-research/scripts/text-normalize.test.ts +73 -0
- package/packages/shared-skills/skills/ulw-research/scripts/text-similarity.mjs +28 -0
- package/packages/shared-skills/skills/ulw-research/scripts/text-similarity.test.ts +38 -0
- package/packages/shared-skills/skills/ulw-research/scripts/units.mjs +105 -0
- package/packages/shared-skills/skills/ulw-research/scripts/units.test.ts +83 -0
- package/packages/shared-skills/skills/visual-qa/SKILL.md +70 -63
- package/packages/shared-skills/skills/visual-qa/scripts/skill-doc-fields.test.ts +34 -0
- package/script/qa/web-terminal-visual-qa.mjs +6 -2
- package/script/qa/xterm-live-terminal.mjs +26 -3
|
@@ -346,12 +346,12 @@ Assembly worker — `task(category="deep-low", load_skills=["frontend", "visual-
|
|
|
346
346
|
|
|
347
347
|
### The delivery gates — every gate for the QA tier must PASS, in order
|
|
348
348
|
|
|
349
|
-
Nothing reaches the user until the gates pass. Record each result with `node "$SKILL_DIR/scripts/report-tools.mjs" outcome gate <static|layout|visual|proofread> <pass|fail|not_run> --session-dir "$SESSION_DIR"`; a gate this harness does not provide is recorded `not_run`. A chat or post answer (light tier) runs the static gates and one render; every paginated or web deliverable runs them all (the reference's sections 3 and 7).
|
|
349
|
+
Nothing reaches the user until the gates pass. Record each result with `node "$SKILL_DIR/scripts/report-tools.mjs" outcome gate <static|fidelity|layout|visual|proofread> <pass|fail|not_run> --session-dir "$SESSION_DIR"`; `fidelity` is recorded not_run until the fidelity verifier ships in this edition; a gate this harness does not provide is recorded `not_run`. A chat or post answer (light tier) runs the static gates and one render; every paginated or web deliverable runs them all (the reference's sections 3 and 7).
|
|
350
350
|
|
|
351
351
|
1. **Static gates (always, before anyone looks at pixels).** `node "$SKILL_DIR/scripts/report-tools.mjs" check "$SESSION_DIR/report.html" --design-spec "$SESSION_DIR/design-spec.md" > "$SESSION_DIR/defects.json"`: keep-all, palette tokens, emoji, em dashes, heading length, unsourced numbers, figure containers, chart text, a report with no visual, images without alt text, gothic-only fonts, citations, the closing and sources sections, broken assets. Codes and fixes: [references/report-gates.md](references/report-gates.md).
|
|
352
352
|
2. **Layout gates.** Print the probe with `node "$SKILL_DIR/scripts/report-tools.mjs" layout-probe --json`, evaluate its `source` in the rendered page through the `browser` skill's owned headless engine, save the result as `$SESSION_DIR/boxes.json`, and re-run `check` with `--layout "$SESSION_DIR/boxes.json"` (overflow, clipped text, distorted images, overlapping siblings).
|
|
353
353
|
3. **Visual QA.** Render the produced artifact back to images — PDF pages to PNG, the HTML through the browser skill at desktop and phone widths — and look at them: missing or broken figures, images stretched or spilling their containers, diagram or chart text rendered off the spec's font or palette, clipped tables, overflowing CJK text, blank pages, unlabeled chart values, wrong page breaks. Reading the source markup is not visual QA; inspect the pixels.
|
|
354
|
-
4. **Proofread gate
|
|
354
|
+
4. **Proofread gate: `task(category="writing", ...)`.** Hand the final text to a dedicated `writing` worker whose only job is language: grammar, spelling, punctuation, terminology consistency, and whether the prose reads NATIVELY in the report's own language. It proofreads only and never composes. It returns a defect list; fix every item and re-run the gate on the delta. Deliver only on a clean pass. This gate runs BEFORE the first delivery, not after the user finds the typo.
|
|
355
355
|
|
|
356
356
|
**Repair is bounded.** After every gate run that found defects, ask `node "$SKILL_DIR/scripts/report-tools.mjs" repair decide --state "$SESSION_DIR/repair-state.json" --defects "$SESSION_DIR/defects.json" --artifact-bytes <bytes> --renders <pages> --session-dir "$SESSION_DIR"` and obey it: `repair` means fix and re-run; `deliver` means stop and ship with the residual defects the manifest now lists; `block` means a content-integrity defect remains (or there is no usable artifact), so do not deliver: tell the user what blocks it and record the row as `failed` with the reason. Never repair past a stop decision (3 attempts, a 2-attempt plateau, an oscillation, or 15 minutes; the reference's section 8).
|
|
357
357
|
|
|
@@ -50,7 +50,7 @@ The request and its destination usually answer the format question already. Deri
|
|
|
50
50
|
| A prior report of the same kind in this workspace, not pointed at | that report's format, offered as the Q1 default | `template-vibe` | full |
|
|
51
51
|
| A complete existing deliverable for this question (section 2) | its existing format | `edit-existing` | the original's tier |
|
|
52
52
|
|
|
53
|
-
QA tiers: **light** runs the static gates and one render check of the answer. **Full** runs the static gates, the layout gates, visual QA of every page, and the proofread gate (section 7).
|
|
53
|
+
QA tiers: **light** runs the static gates and one render check of the answer, and records the fidelity gate as `not_run` until Markdown deliverable support ships for it. **Full** runs the static gates, the fidelity gate, the layout gates, visual QA of every page, and the proofread gate (section 7).
|
|
54
54
|
|
|
55
55
|
## 4. The empty-info interview
|
|
56
56
|
|
|
@@ -123,14 +123,15 @@ Nothing reaches the requester until the gates for its QA tier pass, in this orde
|
|
|
123
123
|
node "$SKILL_DIR/scripts/report-tools.mjs" check "$SESSION_DIR/report.html" --design-spec "$SESSION_DIR/design-spec.md" > "$SESSION_DIR/defects.json"
|
|
124
124
|
```
|
|
125
125
|
It checks keep-all, palette tokens, emoji, em dashes in prose (en dashes outside numeric ranges are advisory), heading length and generic headings, unsourced numbers (section 6), figure containers and captions, chart SVG text, a report with no visual at all, images without alt text, Korean serif fonts, sections without citations, the closing section, the sources section, broken local assets, and any `--require-section <regex>` the brief requires. Every code, severity, and fix is in [report-gates.md](report-gates.md).
|
|
126
|
-
2. **
|
|
126
|
+
2. **Fidelity gate.** The fidelity verifier checks every number, quote, and claim binding against the fact ledger and the source snapshots; its codes are the Fidelity Gate table in [report-gates.md](report-gates.md). It runs before layout and visual QA because a content failure would otherwise force an expensive re-render. Until the fidelity verifier ships in this edition, record `outcome gate fidelity not_run`.
|
|
127
|
+
3. **Layout gates.** Print the probe, evaluate it in the rendered page through the browser skill's owned headless engine, save the returned object as `$SESSION_DIR/boxes.json`, and re-run `check` with `--layout "$SESSION_DIR/boxes.json"`. It adds overflow past the container, clipped text, scroll containers, distorted images, and overlapping siblings.
|
|
127
128
|
```bash
|
|
128
129
|
node "$SKILL_DIR/scripts/report-tools.mjs" layout-probe --json # .source is one async expression
|
|
129
130
|
```
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
4. **Visual QA.** Render the artifact to images (PDF pages to PNG, the HTML in the browser skill's engine at desktop and phone widths) and look at the pixels for what a machine cannot see: composition, hierarchy, page breaks, figure legibility.
|
|
132
|
+
5. **Proofread.** A dedicated writing lane proofreads the final text only (grammar, spelling, punctuation, terminology, native register); it never composes or rewrites content.
|
|
132
133
|
|
|
133
|
-
The light tier runs gate 1 and one render (recorded as `visual`) and records `layout
|
|
134
|
+
The light tier runs gate 1 and one render (recorded as `visual`) and records `fidelity`, `layout`, and `proofread` as `not_run`; `fidelity` stays `not_run` in the light tier until Markdown deliverable support ships for the fidelity verifier. The full tier runs all five.
|
|
134
135
|
|
|
135
136
|
## 8. Bounded repair loop
|
|
136
137
|
|
|
@@ -142,7 +143,7 @@ node "$SKILL_DIR/scripts/report-tools.mjs" repair decide --state "$SESSION_DIR/r
|
|
|
142
143
|
|
|
143
144
|
- `action: repair`: fix the listed defects, re-render, re-run the gate, and ask again.
|
|
144
145
|
- `action: deliver`: stop repairing and deliver. `reason` is `clean` or the stop condition that fired; the residual defects are written into the manifest and listed in the closing briefing.
|
|
145
|
-
- `action: block` (exit `1`): do not deliver. Either a content-integrity defect remains (`missing_closing_section`, `missing_citation_section`, `broken_asset_reference`, `missing_required_section`, `missing_promised_deliverable`), or a stop fired without proof of a usable artifact (`--artifact-bytes` and `--renders`). Tell the requester what blocks delivery and record the affected rows as `failed` with the reason.
|
|
146
|
+
- `action: block` (exit `1`): do not deliver. Either a content-integrity defect remains (`missing_closing_section`, `missing_citation_section`, `broken_asset_reference`, `missing_required_section`, `missing_promised_deliverable`, or a fidelity integrity code: `unresolved_placeholder`, `value_mismatch`, `unit_mismatch`, `quote_not_verbatim`, `claim_status_invalid`, `incompatible_operands`, `pointer_label_mismatch`, `quote_anchor_unresolved`, `unit_duplicated`, `polish_diff_fail`, `fidelity_interview_incomplete`, `derived_not_allowed`, `source_outside_floor`, `snapshot_hash_mismatch`, `chart_value_untraceable`, `quote_unbound`, `edition_unverified`), or a stop fired without proof of a usable artifact (`--artifact-bytes` and `--renders`). Tell the requester what blocks delivery and record the affected rows as `failed` with the reason.
|
|
146
147
|
|
|
147
148
|
Defaults: 3 repair attempts, a plateau of 2 consecutive attempts that do not improve the (blocker, major, minor) counts compared in that order, and 15 minutes of wall clock from the first decision. A defect set that repeats an earlier attempt exactly stops the loop as an oscillation. When several conditions hold at once the reported reason follows `clean`, `blocking`, `oscillation`, `plateau`, `max_attempts`, `wall_clock`.
|
|
148
149
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Fact ledger grammar
|
|
2
|
+
|
|
3
|
+
`fact-ledger.json` is the single source of numbers and quotes for a research run. This file is
|
|
4
|
+
the one definition of what a valid ledger is. `scripts/fact-ledger-schema.mjs` encodes it as
|
|
5
|
+
data (`TRANSITIONS`, `transitionError`, `provenanceErrors`), and both the validator
|
|
6
|
+
(`validateLedger`) and every writer (`addRow`, `retractRow`, `supersedeRow`, `writeLedger`)
|
|
7
|
+
call that same code. A writer can therefore never produce a ledger the validator rejects, and
|
|
8
|
+
the validator can never accept a ledger no writer could produce.
|
|
9
|
+
|
|
10
|
+
## Ledger
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
ledger := { schemaVersion: 1, rows: row[], events: event[] }
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`rows` is append-only: a row is never deleted or reordered. `events` is append-only and
|
|
17
|
+
ordered; an event's position is its time.
|
|
18
|
+
|
|
19
|
+
## Ids
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
fact_id := "F" digits for kind in measured | derived | assumed | converted
|
|
23
|
+
| "Q" digits for kind = quote
|
|
24
|
+
source_id := "S" digits
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`nextId` returns the prefix plus one more than the largest number already used for that
|
|
28
|
+
prefix. `C<n>` is reserved for claim-graph nodes and never appears in the ledger. Fact ids are
|
|
29
|
+
unique across all rows.
|
|
30
|
+
|
|
31
|
+
## Rows
|
|
32
|
+
|
|
33
|
+
Every row carries every field of `ROW_FIELDS`; unknown fields are rejected.
|
|
34
|
+
|
|
35
|
+
The per-kind table below is rendered from `KIND_RULES` in `scripts/fact-ledger-kinds.mjs`
|
|
36
|
+
(`node scripts/fact-ledger-kinds.mjs --render-grammar`); the validator checks every per-kind
|
|
37
|
+
column through that same table, and a test keeps this copy equal to the rendered output.
|
|
38
|
+
|
|
39
|
+
Always required, never null: `fact_id`, `kind`, `raw` (string), `quote` (string),
|
|
40
|
+
`extracted_by` (non-empty), `observed_at` (ISO timestamp), `label` (`[a-z0-9_-]{1,32}`),
|
|
41
|
+
`status`.
|
|
42
|
+
|
|
43
|
+
<!-- kind-rules:begin (rendered from KIND_RULES; do not edit by hand) -->
|
|
44
|
+
| field | measured | quote | derived | assumed | converted |
|
|
45
|
+
|---|---|---|---|---|---|
|
|
46
|
+
| `fact_id` | `F<n>` | `Q<n>` | `F<n>` | `F<n>` | `F<n>` |
|
|
47
|
+
| `value` | decimal | null | decimal | decimal | decimal |
|
|
48
|
+
| `source_id` | `S<n>` | `S<n>` | `S<n>` or null | `S<n>` or null | `S<n>` or null |
|
|
49
|
+
| `locator` | object | object | object or null | object or null | object or null |
|
|
50
|
+
| `snapshot_sha256` | sha256 | sha256 | sha256 or null | sha256 or null | sha256 or null |
|
|
51
|
+
| `rationale` | string or null | string or null | string or null | non-empty | string or null |
|
|
52
|
+
| `exact` | from `value` | null | written by derive (rational or null) | rational or null | written by derive (rational or null) |
|
|
53
|
+
<!-- kind-rules:end -->
|
|
54
|
+
|
|
55
|
+
- `exact` is `{ num: integer string, den: positive integer string }` or null. A measured row's
|
|
56
|
+
`exact` must equal the reduced rational of its `value` (`exactFromDecimal`); `addRow` fills
|
|
57
|
+
it when the caller leaves it null. Derived and converted rows get it from
|
|
58
|
+
derive (plan todo 9): a converted value's rational comes from the original and the factor,
|
|
59
|
+
not from the rounded `value`, so `addRow` never computes it from `value`.
|
|
60
|
+
- `locator` is `{ artifact, char_start <= char_end, page?, line?, table?, row_label?,
|
|
61
|
+
col_label? }`.
|
|
62
|
+
- All other fields are nullable with the types in `fact-ledger-schema.mjs`.
|
|
63
|
+
|
|
64
|
+
## Labels
|
|
65
|
+
|
|
66
|
+
A label is unique across ALL rows, whatever their status. Retracting or superseding a row does
|
|
67
|
+
not free its label.
|
|
68
|
+
|
|
69
|
+
## Provenance
|
|
70
|
+
|
|
71
|
+
`operands` and `derived_from` are arrays of fact ids. Every id must name an existing row and
|
|
72
|
+
must not be the row's own id. Taken together over all rows, these references form a directed
|
|
73
|
+
graph that must have no cycle.
|
|
74
|
+
|
|
75
|
+
## Status machine
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
TRANSITIONS: active -> retracted
|
|
79
|
+
active -> superseded
|
|
80
|
+
retracted, superseded: terminal (no outgoing edge)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
No edge leads back to `active`; every row starts as `active`.
|
|
84
|
+
|
|
85
|
+
## Events
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
event := { fact_id, from, to, replacement, reason }
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
An event is valid against the statuses S at its position (every row active, then each earlier
|
|
92
|
+
event applied in order) when:
|
|
93
|
+
|
|
94
|
+
1. `fact_id` names a row.
|
|
95
|
+
2. `from` equals S[fact_id], so an event can only start from the state the previous event left.
|
|
96
|
+
3. `from -> to` is an edge of `TRANSITIONS`.
|
|
97
|
+
4. `replacement` is non-null exactly when `to = superseded`. A superseded event's replacement
|
|
98
|
+
is a different row (never `fact_id` itself) and S[replacement] is `active`.
|
|
99
|
+
5. `reason` is a non-empty string.
|
|
100
|
+
6. The event has no other keys.
|
|
101
|
+
|
|
102
|
+
A writer builds the event with `from` set to the row's current status and checks it with the
|
|
103
|
+
same `transitionError` before it appends anything.
|
|
104
|
+
|
|
105
|
+
## History invariants
|
|
106
|
+
|
|
107
|
+
For each row, the events naming it form a chain: the first starts at `active`, and each later
|
|
108
|
+
`from` equals the previous `to`. This holds for every event, not just the last one. Then:
|
|
109
|
+
|
|
110
|
+
- The row's `status` equals the `to` of its last event.
|
|
111
|
+
- An `active` row has no events. Since no edge returns to `active`, any event leaves the row
|
|
112
|
+
non-active.
|
|
113
|
+
- A `retracted` or `superseded` row has at least one event (in fact exactly one, because both
|
|
114
|
+
states are terminal).
|
|
115
|
+
|
|
116
|
+
Every error message names the fact id it concerns.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Report-Gates Defect Glossary
|
|
2
2
|
|
|
3
|
-
This reference catalogs every defect code the report gates (`static`, `layout`, `visual`, `proofread`) can raise, their severity and impact, and how to repair them.
|
|
3
|
+
This reference catalogs every defect code the report gates (`static`, `fidelity`, `layout`, `visual`, `proofread`) can raise, their severity and impact, and how to repair them.
|
|
4
4
|
|
|
5
5
|
## Defect Codes by Category
|
|
6
6
|
|
|
@@ -29,6 +29,54 @@ This reference catalogs every defect code the report gates (`static`, `layout`,
|
|
|
29
29
|
| `missing_required_section` | blocker | true | A section explicitly required by the brief (e.g., via `--require-section`) is absent. | Add the section the brief requires (matched by --require-section). |
|
|
30
30
|
| `missing_promised_deliverable` | blocker | true | A deliverable (e.g., a slide deck, a chart, a data file) is promised in the brief but not delivered, not marked blocked_capability, and not skipped with a reason. | Produce the promised deliverable or record it as blocked_capability or skipped with a reason. |
|
|
31
31
|
|
|
32
|
+
### Fidelity Gate (Facts, Quotes & Meaning)
|
|
33
|
+
|
|
34
|
+
Raised only by the fidelity verifier (the fact ledger, fill, verify, meaning, and polish steps), never by `check`. Until that verifier ships in an edition, the manifest records `fidelity: not_run`.
|
|
35
|
+
|
|
36
|
+
| Code | Severity | Integrity | What It Detects | How to Fix |
|
|
37
|
+
|------|----------|-----------|-----------------|-----------|
|
|
38
|
+
| `unresolved_placeholder` | blocker | true | A fact or quote placeholder is left in the artifact, names an unknown ledger id, is malformed, or uses an unsupported mode. | Register the fact with fact add or remove the sentence; a placeholder is never filled with a guess. |
|
|
39
|
+
| `value_mismatch` | blocker | true | A displayed value differs from its ledger row's rendering, or a stored derived value differs from exact recomputation (a hand edit after fill). | Re-run fact fill; never edit a filled value by hand. |
|
|
40
|
+
| `unit_mismatch` | blocker | true | A displayed, adjacent, or header unit conflicts with the ledger row's unit or scale. | Re-run fact fill, or derive a converted row with fact derive --op convert. |
|
|
41
|
+
| `quote_not_verbatim` | blocker | true | A quotation bound to a quote row does not match the source snapshot contiguously after normalization, or a rendered cut is not the registered cut. | Re-insert the quote through its {{Q<n>}} placeholder; after a second failure the sentence is replaced by the quote. |
|
|
42
|
+
| `claim_status_invalid` | blocker | true | A sentence's claim binding names an unknown claim, a refuted or unresolved claim outside Gaps and Contradictions, or a high-risk claim absent from the verified claims. | The claim id is unknown, refuted, unresolved, or not in verified-claims; move the sentence to Gaps or Contradictions, or remove it. |
|
|
43
|
+
| `incompatible_operands` | blocker | true | A derivation's operands differ in unit, population, period, or accounting basis where the operation requires them to match; derive refuses and writes no row. | The operands differ in unit, population, period, or basis for this operation; fix the rows or declare the operation that fits. |
|
|
44
|
+
| `pointer_label_mismatch` | blocker | true | A placeholder's label differs from the referenced ledger row's label (a typo guard on the id). | The placeholder's label is not the row's label; check the id, then the label. |
|
|
45
|
+
| `quote_anchor_unresolved` | blocker | true | A quote cut's from or to anchor is absent, occurs more than once, or appears in reverse order in the quote. | A from or to anchor is missing or occurs more than once in the quote; pick unique anchor words. |
|
|
46
|
+
| `unit_duplicated` | blocker | true | A unit-bearing placeholder is followed by another copy of its own unit. | The unit after the placeholder repeats the row's unit; use :value or remove the unit. |
|
|
47
|
+
| `polish_diff_fail` | blocker | true | The polish pass changed protected fact values, numerals outside fact spans, tickers, or table row counts. | The polish pass changed numbers, tickers, or table rows; revert to the pre-polish artifact and apply the language fixes only. |
|
|
48
|
+
| `fidelity_interview_incomplete` | blocker | true | A fidelity field in the brief is still pending or missing when a fidelity command runs. | A fidelity field is pending or missing in brief.md; answer the open question or record its default, then rerun. |
|
|
49
|
+
| `derived_not_allowed` | blocker | true | A placeholder resolves to a derived, converted, or assumed row while the brief allows no derived numbers. | The brief allows no derived or assumed numbers; cite a source row directly or change the brief with the requester. |
|
|
50
|
+
| `source_outside_floor` | blocker | true | A ledger row's source lies outside the source floor the brief records (pointed sources only, or the allowed source classes). | The row's source is outside the source floor the brief records; use a source the brief allows or remove the fact. |
|
|
51
|
+
| `snapshot_hash_mismatch` | blocker | true | A pinned source snapshot's text no longer hashes to its recorded hash, or indexed slices no longer equal the snapshot text. | The source snapshot changed after it was pinned; re-snapshot the source and re-register its rows. |
|
|
52
|
+
| `chart_value_untraceable` | blocker | true | A chart data label, axis tick, or chart data file does not match the ledger-backed data the chart declares, or the chart declares no data source. | A chart value, tick, or data file does not match its ledger-backed data source; re-render the chart from the exported data. |
|
|
53
|
+
| `quote_unbound` | blocker | true | A direct quotation in the report has no ledger quote row behind it; a citation marker alone does not bind it. | A direct quotation has no ledger quote row; register it with fact quote and insert it through its placeholder. |
|
|
54
|
+
| `edition_unverified` | blocker | true | A delivered edition has no fact verify record whose artifact hash matches the delivered source. | The delivered file has no matching fact verify record; run fact verify on that edition and record it with --verified-by. |
|
|
55
|
+
| `untraceable_number` | major | false | A number or date in prose or a table cell resolves to no ledger row and is not structural; a citation does not exempt it. | Replace the typed number with a {{F<n>}} placeholder backed by a ledger row, or register it as assumed with a rationale. |
|
|
56
|
+
| `unsupported_verification` | major | false | A sentence asserts a command or tool check that no recorded command-output row backs. | The sentence claims a tool check that no recorded command output backs; link the recorded output row or remove the claim. |
|
|
57
|
+
| `conflicting_readings` | major | false | Two active ledger rows with the same value and unit but different periods or qualifiers are cited as one fact. | Two ledger rows with different periods or qualifiers are cited as one fact; split the sentence or retire one row. |
|
|
58
|
+
| `hedge_dropped` | major | false | A hedge, condition, or negation class present in the source quote is absent from the report sentence. | Restore the qualifier the source uses (estimated, about, not yet). |
|
|
59
|
+
| `direction_flipped` | major | false | The source states an increase and the sentence a decrease, or the reverse. | The source states the opposite direction; rewrite from the quote. |
|
|
60
|
+
| `causality_added` | major | false | The sentence carries a causal connective that no supporting quote or claim statement contains. | The source states no cause; state the correlation or quote the source. |
|
|
61
|
+
| `qualifier_dropped` | major | false | A bounding or approximation qualifier recorded on the ledger row (up to, at least, about) is absent near the value in the sentence. | The source bounds this value (up to, at least, about); restore the qualifier or use :q. |
|
|
62
|
+
| `unbound_sentence` | major | false | A findings sentence carries no fact, quote, citation marker, or claim binding and is not marked as opinion or recommendation. | Bind the sentence to a fact, a quote, a citation, or a claim-graph node with data-claim. |
|
|
63
|
+
| `meaning_drift_confirmed` | major | false | Two independent meaning readers flag the same drift kind on the same sentence and quote pair. | Two independent readers found the same drift; rewrite from the quote or dispute with a reason. |
|
|
64
|
+
| `polish_edit_rejected` | major | false | A proposed polish edit changes a protected number, hedge, qualifier, link, or claim id. | The edit changed a number, a hedge, a qualifier, a link, or a claim id; re-propose the language fix only. |
|
|
65
|
+
| `polish_hedging_decreased` | major | false | The polish pass removed a hedge the source grounds. | The polish pass removed qualifiers; restore them. |
|
|
66
|
+
| `polish_text_churn` | major | false | More than half of the visible prose changed during the polish pass. | More than half the text changed during polish; the pass composed instead of proofreading. |
|
|
67
|
+
| `snapshot_mismatch` | major | false | An operation that needs one collection window uses operands from unequal windows or observations outside the window. | The operands come from different collection windows; use rows from one window or state the windows separately. |
|
|
68
|
+
| `join_integrity_fail` | major | false | A table row combines facts from different source observation rows, or a declared observation id contradicts the row's lineage. | A table row combines facts from different source observations; keep each row to one observation or split it. |
|
|
69
|
+
| `quote_stale_version` | major | false | The quoted source revision differs from the revision the report targets for the same scope. | The quoted source revision differs from the revision the report targets; re-snapshot the target revision or date the quote. |
|
|
70
|
+
| `quote_fuzzy_match` | minor | false | An exact quote match failed but a candidate with similarity of at least 0.95 and identical protected tokens exists (OCR noise); diagnostic only. | The source text is OCR-noisy; confirm the snapshot and prefer the raw document. |
|
|
71
|
+
| `name_outside_quote` | minor | false | An uppercase Latin token of 2 to 6 letters in the sentence is absent from the supporting source text and that source's acronym table. | A name in the sentence is not in the cited quote; add the source or remove the name. |
|
|
72
|
+
| `scope_widened_warn` | minor | false | The sentence uses a broader scope term than the quote's narrow term, and no supporting fact carries the broad scope. | The sentence uses a broader scope word than the quote; confirm the scope or narrow it. |
|
|
73
|
+
| `particle_unverified` | minor | false | A particle after a filled value could not be checked against the value's final reading. | The particle after this value could not be checked; read it aloud and fix it by hand if wrong. |
|
|
74
|
+
| `fallback_without_entity` | minor | false | A quote that replaced a twice-failed sentence has no entity for its attribution line. | The replacement quote has no entity for attribution; set one on the row. |
|
|
75
|
+
| `meaning_drift_warn` | minor | false | One meaning reader flags a change of scope, subject, or certainty without independent agreement. | A separate reader found the sentence changes scope, subject, or certainty; rewrite from the quote. |
|
|
76
|
+
| `polish_edit_unlocated` | minor | false | A polish edit's before-text matches zero or several places in the current text. | The edit's before-text was not found exactly once; re-propose against the current text. |
|
|
77
|
+
| `polish_link_changed` | minor | false | The polish pass altered or removed a link target, or an internal target stopped resolving. | A link was altered or removed during polish; restore it. |
|
|
78
|
+
| `polish_name_changed` | minor | false | A ledger-backed proper noun present before polish is absent afterward. | A proper noun changed during polish; restore it. |
|
|
79
|
+
|
|
32
80
|
### Layout Gate (Rendering & Presentation)
|
|
33
81
|
|
|
34
82
|
| Code | Severity | Integrity | What It Detects | How to Fix |
|
|
@@ -46,7 +94,7 @@ Gates emit a manifest-level outcome with one of three statuses:
|
|
|
46
94
|
| Status | Meaning |
|
|
47
95
|
|--------|---------|
|
|
48
96
|
| `pass` | All checks passed; no defects raised. |
|
|
49
|
-
| `fail` |
|
|
97
|
+
| `fail` | At least one blocker defect was raised. Major and minor defects alone leave the gate at `pass`; they still go to the repair loop. |
|
|
50
98
|
| `not_run` | The gate was not invoked (e.g., no probe file provided for layout, no visual inspection conducted). |
|
|
51
99
|
|
|
52
100
|
### Layout Gate Probe File Requirement
|
|
@@ -62,7 +110,7 @@ Defect codes and their hints are delivered via the outcome manifest under `resid
|
|
|
62
110
|
|
|
63
111
|
Citations within reports follow one of two lineage modes:
|
|
64
112
|
|
|
65
|
-
- **inline**: Source marks appear as `[Sn]` or `[
|
|
113
|
+
- **inline**: Source marks appear as `[Sn]`, `[Source n]`, or `[^n]` hyperlinks inline with the cited text.
|
|
66
114
|
- **section**: Sources are listed in a dedicated section with numbered entries ([S1], [S2], etc.).
|
|
67
115
|
|
|
68
116
|
Both modes are valid; choose based on the report's narrative flow.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// claims-index.mjs - deterministic index of claim-graph.md: the one Markdown table whose header
|
|
2
|
+
// names claim_id, statement, risk tier, and status, plus the ids listed under the
|
|
3
|
+
// `## verified-claims` digest. Pure function of the text; node: builtins only.
|
|
4
|
+
|
|
5
|
+
const CLAIM_ID = /^C\d+$/
|
|
6
|
+
const REQUIRED_COLUMNS = Object.freeze({ claim_id: "claim_id", statement: "statement", risk: "risk tier", status: "status" })
|
|
7
|
+
|
|
8
|
+
/** Split one table line on unescaped pipes; drops the leading and trailing border cells. */
|
|
9
|
+
function splitRow(line) {
|
|
10
|
+
const cells = []
|
|
11
|
+
let current = ""
|
|
12
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
13
|
+
const char = line[index]
|
|
14
|
+
if (char === "\\" && line[index + 1] === "|") {
|
|
15
|
+
current += "|"
|
|
16
|
+
index += 1
|
|
17
|
+
} else if (char === "|") {
|
|
18
|
+
cells.push(current)
|
|
19
|
+
current = ""
|
|
20
|
+
} else current += char
|
|
21
|
+
}
|
|
22
|
+
cells.push(current)
|
|
23
|
+
const trimmed = cells.map((value) => value.trim())
|
|
24
|
+
if (line.trim().startsWith("|")) trimmed.shift()
|
|
25
|
+
if (line.trim().endsWith("|")) trimmed.pop()
|
|
26
|
+
return trimmed
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function normalizeHeader(value) {
|
|
30
|
+
return value.replace(/`/g, "").trim().toLowerCase().replace(/[\s_-]+/g, " ")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function columnIndexes(header) {
|
|
34
|
+
const names = header.map(normalizeHeader)
|
|
35
|
+
const indexes = {}
|
|
36
|
+
for (const [key, name] of Object.entries(REQUIRED_COLUMNS)) indexes[key] = names.indexOf(normalizeHeader(name))
|
|
37
|
+
return Object.values(indexes).every((index) => index >= 0) ? indexes : null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function isSeparator(line) {
|
|
41
|
+
return /^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)*\|?\s*$/.test(line)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const DIGEST_HEADING = normalizeHeader("verified-claims")
|
|
45
|
+
|
|
46
|
+
/** `offset` is the index of `lines[0]` in the document, for line numbers in errors. */
|
|
47
|
+
function verifiedIds(lines, offset, errors) {
|
|
48
|
+
const ids = []
|
|
49
|
+
let inside = false
|
|
50
|
+
for (const [index, line] of lines.entries()) {
|
|
51
|
+
const heading = /^(#{1,6})\s+(.*)$/.exec(line)
|
|
52
|
+
if (heading) {
|
|
53
|
+
const name = normalizeHeader(heading[2])
|
|
54
|
+
inside = name === DIGEST_HEADING
|
|
55
|
+
if (!inside && name.startsWith(DIGEST_HEADING)) {
|
|
56
|
+
errors.push(`line ${offset + index + 1}: heading "${line.trim()}" is not the digest heading "## verified-claims"; drop the suffix so its entries are read`)
|
|
57
|
+
}
|
|
58
|
+
continue
|
|
59
|
+
}
|
|
60
|
+
if (!inside) continue
|
|
61
|
+
// An entry is a list item or a table row; prose lines never verify. Only the id an entry
|
|
62
|
+
// starts with is verified; ids mentioned later in the line are not.
|
|
63
|
+
const leading = /^\s*(?:(?:[-*+]|\d+[.)])\s+|\|\s*)`?(C\d+)\b/.exec(line)
|
|
64
|
+
if (leading && !ids.includes(leading[1])) ids.push(leading[1])
|
|
65
|
+
}
|
|
66
|
+
return ids
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Blank every line of a fenced code block (``` or ~~~, fences included) so nothing in it is read. */
|
|
70
|
+
function unfenced(lines) {
|
|
71
|
+
let fence = null
|
|
72
|
+
return lines.map((line) => {
|
|
73
|
+
const marker = /^\s{0,3}(`{3,}|~{3,})/.exec(line)
|
|
74
|
+
if (fence === null) {
|
|
75
|
+
if (marker) fence = marker[1]
|
|
76
|
+
return marker ? "" : line
|
|
77
|
+
}
|
|
78
|
+
const closes = marker && marker[1][0] === fence[0] && marker[1].length >= fence.length && line.trim() === marker[1]
|
|
79
|
+
if (closes) fence = null
|
|
80
|
+
return ""
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** @returns {{ claims: { claim_id: string, statement: string, risk: string, status: string, in_verified: boolean }[], errors: string[] }} */
|
|
85
|
+
export function indexClaims(markdown) {
|
|
86
|
+
const lines = unfenced(markdown.split(/\r?\n/))
|
|
87
|
+
const errors = []
|
|
88
|
+
const headerAt = lines.findIndex((line) => line.trim().startsWith("|") && columnIndexes(splitRow(line)) !== null)
|
|
89
|
+
if (headerAt < 0) {
|
|
90
|
+
return { claims: [], errors: ["no claim table: a Markdown table with claim_id, statement, risk tier, and status columns is required"] }
|
|
91
|
+
}
|
|
92
|
+
const header = splitRow(lines[headerAt])
|
|
93
|
+
const columns = columnIndexes(header)
|
|
94
|
+
const hasSeparator = isSeparator(lines[headerAt + 1] ?? "")
|
|
95
|
+
if (!hasSeparator) errors.push(`line ${headerAt + 2}: claim table header must be followed by a separator row`)
|
|
96
|
+
const firstRow = headerAt + (hasSeparator ? 2 : 1)
|
|
97
|
+
const rows = []
|
|
98
|
+
let tableEnd = firstRow
|
|
99
|
+
for (let index = firstRow; index < lines.length && lines[index].trim().startsWith("|"); index += 1) {
|
|
100
|
+
tableEnd = index + 1
|
|
101
|
+
const cells = splitRow(lines[index])
|
|
102
|
+
const at = `line ${index + 1}`
|
|
103
|
+
if (cells.length !== header.length) {
|
|
104
|
+
errors.push(`${at}: expected ${header.length} cells, found ${cells.length}`)
|
|
105
|
+
continue
|
|
106
|
+
}
|
|
107
|
+
const claimId = cells[columns.claim_id].replace(/`/g, "")
|
|
108
|
+
if (!CLAIM_ID.test(claimId)) {
|
|
109
|
+
errors.push(`${at}: claim_id "${claimId}" must match C<n>`)
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
if (rows.some((row) => row.claim_id === claimId)) {
|
|
113
|
+
errors.push(`${at}: duplicate claim_id ${claimId}`)
|
|
114
|
+
continue
|
|
115
|
+
}
|
|
116
|
+
rows.push({ claim_id: claimId, statement: cells[columns.statement], risk: cells[columns.risk], status: cells[columns.status] })
|
|
117
|
+
}
|
|
118
|
+
// The digest section ends at the claim table: scan each side on its own so it cannot carry across.
|
|
119
|
+
const verified = [...new Set([...verifiedIds(lines.slice(0, headerAt), 0, errors), ...verifiedIds(lines.slice(tableEnd), tableEnd, errors)])]
|
|
120
|
+
for (const id of verified) {
|
|
121
|
+
if (!rows.some((row) => row.claim_id === id)) errors.push(`verified-claims lists ${id}, which has no claim row`)
|
|
122
|
+
}
|
|
123
|
+
const claims = rows.map((row) => ({ ...row, in_verified: verified.includes(row.claim_id) }))
|
|
124
|
+
return { claims, errors }
|
|
125
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test"
|
|
2
|
+
import { readFileSync } from "node:fs"
|
|
3
|
+
import { join } from "node:path"
|
|
4
|
+
|
|
5
|
+
import { indexClaims } from "./claims-index.mjs"
|
|
6
|
+
|
|
7
|
+
const FIXTURE = join(import.meta.dir, "tests", "fixtures", "fidelity", "claim-graph.md")
|
|
8
|
+
|
|
9
|
+
describe("indexClaims", () => {
|
|
10
|
+
test("indexes the fixture claim graph", () => {
|
|
11
|
+
const { claims, errors } = indexClaims(readFileSync(FIXTURE, "utf8"))
|
|
12
|
+
expect(errors).toEqual([])
|
|
13
|
+
expect(claims.map((claim: { claim_id: string; in_verified: boolean }) => claim.claim_id)).toEqual(["C1", "C2", "C3"])
|
|
14
|
+
expect(claims.filter((claim: { claim_id: string; in_verified: boolean }) => claim.in_verified).map((claim: { claim_id: string; in_verified: boolean }) => claim.claim_id)).toEqual(["C1"])
|
|
15
|
+
expect(claims[0]).toEqual({
|
|
16
|
+
claim_id: "C1",
|
|
17
|
+
statement: "The bridge span is up to 320 m.",
|
|
18
|
+
risk: "high",
|
|
19
|
+
status: "supported",
|
|
20
|
+
in_verified: true,
|
|
21
|
+
})
|
|
22
|
+
expect(claims[2].status).toBe("refuted")
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test("a malformed table returns errors", () => {
|
|
26
|
+
const bad = [
|
|
27
|
+
"| claim_id | statement | risk tier | status |",
|
|
28
|
+
"|---|---|---|---|",
|
|
29
|
+
"| X1 | bad id | high | supported |",
|
|
30
|
+
"| C2 | too few cells |",
|
|
31
|
+
].join("\n")
|
|
32
|
+
const { errors } = indexClaims(bad)
|
|
33
|
+
expect(errors.length).toBeGreaterThanOrEqual(2)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test("fenced code blocks are skipped: a fenced heading does not end the digest and a fenced entry does not verify", () => {
|
|
37
|
+
const text = [
|
|
38
|
+
"| claim_id | statement | risk tier | status |",
|
|
39
|
+
"|---|---|---|---|",
|
|
40
|
+
"| C1 | one | high | supported |",
|
|
41
|
+
"| C2 | two | low | supported |",
|
|
42
|
+
"",
|
|
43
|
+
"## verified-claims",
|
|
44
|
+
"```",
|
|
45
|
+
"# not a heading",
|
|
46
|
+
"- C2",
|
|
47
|
+
"```",
|
|
48
|
+
"- C1",
|
|
49
|
+
].join("\n")
|
|
50
|
+
const { claims, errors } = indexClaims(text)
|
|
51
|
+
expect(errors).toEqual([])
|
|
52
|
+
expect(claims.map((claim: { in_verified: boolean }) => claim.in_verified)).toEqual([true, false])
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test("a document without the claim table returns an error", () => {
|
|
56
|
+
const { claims, errors } = indexClaims("# claim graph\n\nno table here\n")
|
|
57
|
+
expect(claims).toEqual([])
|
|
58
|
+
expect(errors.length).toBe(1)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test("a verified id with no claim row is an error", () => {
|
|
62
|
+
const text = "## verified-claims\n\n- C9\n\n| claim_id | statement | risk tier | status |\n|---|---|---|---|\n| C1 | a | high | supported |\n"
|
|
63
|
+
expect(indexClaims(text).errors.some((e: string) => e.includes("C9"))).toBe(true)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test("only the leading claim id of a verified entry is verified", () => {
|
|
67
|
+
const text = [
|
|
68
|
+
"## verified-claims",
|
|
69
|
+
"",
|
|
70
|
+
"- C1 (merged from C2)",
|
|
71
|
+
"",
|
|
72
|
+
"| claim_id | statement | risk tier | status |",
|
|
73
|
+
"|---|---|---|---|",
|
|
74
|
+
"| C1 | a, see C2 | high | supported |",
|
|
75
|
+
"| C2 | b | high | unresolved |",
|
|
76
|
+
].join("\n")
|
|
77
|
+
const { claims, errors } = indexClaims(text)
|
|
78
|
+
expect(errors).toEqual([])
|
|
79
|
+
expect(claims.map((claim: { claim_id: string; in_verified: boolean }) => [claim.claim_id, claim.in_verified])).toEqual([
|
|
80
|
+
["C1", true],
|
|
81
|
+
["C2", false],
|
|
82
|
+
])
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test("a verified-claims line verifies only as a list item or a table row, never as prose", () => {
|
|
86
|
+
const text = [
|
|
87
|
+
"## verified-claims",
|
|
88
|
+
"",
|
|
89
|
+
"- C1",
|
|
90
|
+
"C2 is pending review",
|
|
91
|
+
"1) C3",
|
|
92
|
+
"| C4 | merged |",
|
|
93
|
+
"",
|
|
94
|
+
"| claim_id | statement | risk tier | status |",
|
|
95
|
+
"|---|---|---|---|",
|
|
96
|
+
"| C1 | a | high | supported |",
|
|
97
|
+
"| C2 | b | high | unresolved |",
|
|
98
|
+
"| C3 | c | high | supported |",
|
|
99
|
+
"| C4 | d | high | supported |",
|
|
100
|
+
].join("\n")
|
|
101
|
+
const { claims, errors } = indexClaims(text)
|
|
102
|
+
expect(errors).toEqual([])
|
|
103
|
+
expect(claims.map((claim: { claim_id: string; in_verified: boolean }) => [claim.claim_id, claim.in_verified])).toEqual([
|
|
104
|
+
["C1", true],
|
|
105
|
+
["C2", false],
|
|
106
|
+
["C3", true],
|
|
107
|
+
["C4", true],
|
|
108
|
+
])
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test("the SKILL.md synthesis heading 'Verified claims' is recognized", () => {
|
|
112
|
+
const text = "## Verified claims\n\n- C1\n\n| claim_id | statement | risk tier | status |\n|---|---|---|---|\n| C1 | a | high | supported |\n"
|
|
113
|
+
expect(indexClaims(text).claims[0].in_verified).toBe(true)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test("a digest heading with a suffix is an error naming the heading, not a silently empty digest", () => {
|
|
117
|
+
const text = "## Verified claims (2)\n\n- C1\n\n| claim_id | statement | risk tier | status |\n|---|---|---|---|\n| C1 | a | high | supported |\n"
|
|
118
|
+
const { claims, errors } = indexClaims(text)
|
|
119
|
+
expect(claims[0].in_verified).toBe(false)
|
|
120
|
+
expect(errors.some((e: string) => e.startsWith("line 1:") && e.includes('"## Verified claims (2)"'))).toBe(true)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test("the verified-claims section ends at the claim table", () => {
|
|
124
|
+
const text = [
|
|
125
|
+
"## verified-claims",
|
|
126
|
+
"- C1",
|
|
127
|
+
"",
|
|
128
|
+
"| claim_id | statement | risk tier | status |",
|
|
129
|
+
"|---|---|---|---|",
|
|
130
|
+
"| C1 | a | high | supported |",
|
|
131
|
+
"| C2 | b | high | unresolved |",
|
|
132
|
+
"",
|
|
133
|
+
"C2 still pending",
|
|
134
|
+
].join("\n")
|
|
135
|
+
const { claims, errors } = indexClaims(text)
|
|
136
|
+
expect(errors).toEqual([])
|
|
137
|
+
expect(claims.map((claim: { claim_id: string; in_verified: boolean }) => [claim.claim_id, claim.in_verified])).toEqual([
|
|
138
|
+
["C1", true],
|
|
139
|
+
["C2", false],
|
|
140
|
+
])
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
test("a GFM two-dash separator row is accepted and the first data row is read", () => {
|
|
144
|
+
const text = "| claim_id | statement | risk tier | status |\n|--|--|--|--|\n| C1 | a | high | supported |\n| C2 | b | normal | unresolved |\n"
|
|
145
|
+
const { claims, errors } = indexClaims(text)
|
|
146
|
+
expect(errors).toEqual([])
|
|
147
|
+
expect(claims.map((claim: { claim_id: string }) => claim.claim_id)).toEqual(["C1", "C2"])
|
|
148
|
+
})
|
|
149
|
+
})
|