lazycodex-ai 5.1.44 → 5.1.46
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/README.de.md +0 -5
- package/README.es.md +0 -5
- package/README.fr.md +0 -5
- package/README.it.md +0 -5
- package/README.ja.md +0 -5
- package/README.ko.md +0 -5
- package/README.md +4 -5
- package/README.pt-br.md +0 -5
- package/README.ru.md +0 -6
- package/README.zh-cn.md +0 -5
- package/dist/cli/index.js +865 -413
- package/dist/cli/service-auth/keystore.d.ts +4 -2
- package/dist/cli-node/index.js +865 -413
- package/docs/reference/web-terminal-visual-qa.md +8 -0
- package/package.json +1 -1
- package/packages/lsp-daemon/dist/cli.js +7 -7
- package/packages/lsp-daemon/dist/client.js +7 -7
- package/packages/lsp-daemon/dist/index.js +7 -7
- package/packages/lsp-daemon/package.json +3 -3
- package/packages/lsp-tools-mcp/dist/cli.js +7 -7
- package/packages/lsp-tools-mcp/dist/mcp.js +7 -7
- 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 +77 -26
- 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 +14 -9
- package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +1 -1
- 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/ATTRIBUTION.md +2 -2
- 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/ultimate-browsing/engine/AGENTS.md +1 -1
- 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 +21 -3
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +37 -12
- package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +77 -16
- package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger-grammar.md +134 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger.md +95 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/fidelity-claim-kinds.md +19 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/report-gates.md +68 -3
- package/packages/omo-codex/plugin/skills/ulw-research/references/report-visualization.md +2 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/unit-rules.md +157 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/claim-kinds.mjs +116 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/claims-index.mjs +125 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/cli-support.mjs +19 -5
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/contracts.mjs +89 -3
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-meaning.mjs +191 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-verify.mjs +164 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands.mjs +239 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-derive.mjs +66 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-expr.mjs +108 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-fill.mjs +194 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger-kinds.mjs +250 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger-schema.mjs +221 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger.mjs +123 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-locate.mjs +231 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-pairs.mjs +187 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-recompute.mjs +89 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-binding.mjs +130 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-brief.mjs +150 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-claims.mjs +89 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-lexicon.mjs +145 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-records.mjs +163 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-state.mjs +64 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-trace.mjs +85 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-values.mjs +229 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-fidelity.mjs +113 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-static.mjs +29 -9
- 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/html-lite.mjs +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-markup.mjs +182 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/lexicon.mjs +47 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/md-lite.mjs +193 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/meaning-check.mjs +196 -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 +8 -8
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/particles-ko.mjs +108 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/placeholder.mjs +184 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-apply.mjs +115 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-diff.mjs +31 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-project.mjs +125 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-rules.mjs +170 -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 +21 -10
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools.mjs +15 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/sentence-split.mjs +77 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-commands.mjs +140 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-snapshot.mjs +176 -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/unit-algebra.mjs +101 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-errors.mjs +23 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-metadata.mjs +31 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-pairs.mjs +72 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-precision.mjs +44 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-rules-shapes.mjs +64 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/unit-rules.mjs +173 -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-codex-compatibility.test.mjs +19 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +12 -8
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +169 -30
- package/packages/shared-skills/skills/ast-grep/AGENTS.md +1 -1
- 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/ATTRIBUTION.md +2 -2
- 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/ultimate-browsing/engine/AGENTS.md +1 -1
- package/packages/shared-skills/skills/ulw-execute/SKILL.md +1 -1
- package/packages/shared-skills/skills/ulw-research/AGENTS.md +21 -3
- package/packages/shared-skills/skills/ulw-research/SKILL.md +37 -12
- package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +77 -16
- package/packages/shared-skills/skills/ulw-research/references/fact-ledger-grammar.md +134 -0
- package/packages/shared-skills/skills/ulw-research/references/fact-ledger.md +95 -0
- package/packages/shared-skills/skills/ulw-research/references/fidelity-claim-kinds.md +19 -0
- package/packages/shared-skills/skills/ulw-research/references/report-gates.md +68 -3
- package/packages/shared-skills/skills/ulw-research/references/report-visualization.md +2 -0
- package/packages/shared-skills/skills/ulw-research/references/unit-rules.md +157 -0
- package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.mjs +116 -0
- package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.test.ts +193 -0
- 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/cli-support.mjs +19 -5
- package/packages/shared-skills/skills/ulw-research/scripts/cli-support.test.ts +13 -2
- package/packages/shared-skills/skills/ulw-research/scripts/contracts.mjs +89 -3
- package/packages/shared-skills/skills/ulw-research/scripts/contracts.test.ts +100 -12
- package/packages/shared-skills/skills/ulw-research/scripts/copy-returns.test.ts +183 -0
- package/packages/shared-skills/skills/ulw-research/scripts/delivery-barrier.test.ts +245 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-meaning.mjs +191 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-verify.mjs +164 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands.mjs +239 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.mjs +66 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.test.ts +375 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-expr.mjs +108 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-fill.mjs +194 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-fill.test.ts +221 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-grammar.test.ts +197 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.mjs +250 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.test.ts +156 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-legacy.test.ts +160 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-schema.mjs +221 -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 +123 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger.test.ts +254 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-locate.mjs +231 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-locate.test.ts +118 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-pairs.mjs +187 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-pairs.test.ts +167 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-recompute.mjs +89 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-dimensions.test.ts +409 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-rules.test.ts +388 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-binding.mjs +130 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-binding.test.ts +81 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-brief.mjs +150 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-brief.test.ts +179 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-claims.mjs +89 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-lexicon.mjs +145 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-lexicon.test.ts +117 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-records.mjs +163 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-state.mjs +64 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-state.test.ts +46 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-trace.mjs +85 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-trace.test.ts +58 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.mjs +229 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.test.ts +270 -0
- package/packages/shared-skills/skills/ulw-research/scripts/gates-context.test.ts +64 -0
- package/packages/shared-skills/skills/ulw-research/scripts/gates-fidelity.mjs +113 -0
- package/packages/shared-skills/skills/ulw-research/scripts/gates-fidelity.test.ts +73 -0
- package/packages/shared-skills/skills/ulw-research/scripts/gates-static.mjs +29 -9
- 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/html-lite.mjs +2 -2
- package/packages/shared-skills/skills/ulw-research/scripts/html-markup.mjs +182 -0
- 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/md-lite.mjs +193 -0
- package/packages/shared-skills/skills/ulw-research/scripts/md-lite.test.ts +271 -0
- package/packages/shared-skills/skills/ulw-research/scripts/meaning-check.mjs +196 -0
- package/packages/shared-skills/skills/ulw-research/scripts/meaning-check.test.ts +228 -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 +8 -8
- 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/placeholder.mjs +184 -0
- package/packages/shared-skills/skills/ulw-research/scripts/placeholder.test.ts +77 -0
- package/packages/shared-skills/skills/ulw-research/scripts/polish-apply.mjs +115 -0
- package/packages/shared-skills/skills/ulw-research/scripts/polish-apply.test.ts +363 -0
- package/packages/shared-skills/skills/ulw-research/scripts/polish-diff.mjs +31 -0
- package/packages/shared-skills/skills/ulw-research/scripts/polish-diff.test.ts +168 -0
- package/packages/shared-skills/skills/ulw-research/scripts/polish-markup.test.ts +187 -0
- package/packages/shared-skills/skills/ulw-research/scripts/polish-project.mjs +125 -0
- package/packages/shared-skills/skills/ulw-research/scripts/polish-rules.mjs +170 -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 +21 -10
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools.mjs +15 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools.test.ts +458 -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/source-commands.mjs +140 -0
- package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.mjs +176 -0
- package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.test.ts +113 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/assets/share.csv +3 -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/gen-legacy-dev.mjs +89 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/ledger-basic.json +223 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/ledger-legacy-dev.json +859 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/ledger-verify.json +420 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/report-bad.html +19 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/report-good.html +39 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4/acronyms.json +3 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4/meta.json +9 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4/sentences.jsonl +7 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4/text.txt +7 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S4.html +19 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S5/acronyms.json +1 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S5/meta.json +9 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S5/sentences.jsonl +1 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S5/text.txt +1 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/sources/S9.txt +1 -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/unit-algebra.mjs +101 -0
- package/packages/shared-skills/skills/ulw-research/scripts/unit-errors.mjs +23 -0
- package/packages/shared-skills/skills/ulw-research/scripts/unit-metadata.mjs +31 -0
- package/packages/shared-skills/skills/ulw-research/scripts/unit-pairs.mjs +72 -0
- package/packages/shared-skills/skills/ulw-research/scripts/unit-precision.mjs +44 -0
- package/packages/shared-skills/skills/ulw-research/scripts/unit-rules-shapes.mjs +64 -0
- package/packages/shared-skills/skills/ulw-research/scripts/unit-rules.mjs +173 -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
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Fact ledger
|
|
2
|
+
|
|
3
|
+
`$SESSION_DIR/fact-ledger.json` holds every number and every direct quotation a research run may put in front of a reader. Rows come only from a source snapshot (through a deterministic locator), from a script-computed derivation, or from an explicit assumption with a rationale. A report source never carries a typed value: it carries a placeholder, and `fact fill` renders the row. The validity rules (ids, per-kind columns, the status machine) are in [fact-ledger-grammar.md](fact-ledger-grammar.md); this file is the working guide.
|
|
4
|
+
|
|
5
|
+
Every command is `node "$SKILL_DIR/scripts/report-tools.mjs" <command> --session-dir "$SESSION_DIR"`; the flags and exit codes are in [deliverable-phase.md](deliverable-phase.md), sections 10 and 11.
|
|
6
|
+
|
|
7
|
+
## Files
|
|
8
|
+
|
|
9
|
+
| Path | Written by | Holds |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `sources/S<n>/text.txt` | `source snapshot` | the extracted text the locators read (one line per block; pages joined by a form feed); `sha256` covers this file |
|
|
12
|
+
| `sources/S<n>/source.html` | `source snapshot` (page sources) | the captured page, read by the table locator |
|
|
13
|
+
| `sources/S<n>/meta.json` | `source snapshot` | `source_id`, `url`, `observed_at`, `sha256`, `extractor`, `revision`, `kind`, `provenance` |
|
|
14
|
+
| `sources/S<n>/sentences.jsonl`, `acronyms.json` | `source snapshot` | the sentence index (`S<n>:s<k>`) and the acronym table the fidelity gate reads |
|
|
15
|
+
| `sources/S<n>/command.json` | `source snapshot --command` | argv, working directory, exit status, stdout and stderr hashes |
|
|
16
|
+
| `fact-ledger.json` | `fact add`, `fact quote`, `fact derive`, `fact retract` | `{ schemaVersion: 1, rows, events }` |
|
|
17
|
+
| `claims.json` | `claims index` | the claim table and the `verified-claims` membership |
|
|
18
|
+
| `fidelity-defects.json` | `fact verify` | the verify record: the fidelity envelope (`record_kind: "fidelity"`, `artifact_sha256`, `report`, `written_at`, `defects`) plus `command`, `status`, `exitCode`, `format`, `counts`, `gatesRun` |
|
|
19
|
+
| `fidelity-meaning-defects.json` | `fact meaning-check` | the meaning record: the fidelity envelope (`record_kind: "meaning"`) plus the run fields under Meaning verdicts |
|
|
20
|
+
|
|
21
|
+
A source directory is immutable. Snapshotting the same id again with the same text is a no-op; different text fails with `snapshot_exists`, because rows pin the snapshot hash.
|
|
22
|
+
|
|
23
|
+
## Row fields
|
|
24
|
+
|
|
25
|
+
| Field | Meaning |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `fact_id` | `F<n>` for a value, `Q<n>` for a quotation; assigned by the writer |
|
|
28
|
+
| `kind` | `measured` (located in a snapshot), `quote`, `derived`, `converted`, or `assumed` |
|
|
29
|
+
| `label` | the name a placeholder must repeat exactly (`[a-z0-9_-]`, up to 32 characters) |
|
|
30
|
+
| `value`, `unit`, `exact` | the decimal value as written, its normalized unit, and the exact rational the arithmetic uses |
|
|
31
|
+
| `raw`, `quote`, `value_span` | the source's own characters for the value, the whole containing sentence or cell, and where `raw` sits inside `quote` |
|
|
32
|
+
| `qualifier` | a bounding word the source puts on the value: `upper_inclusive` (up to, at most), `lower_inclusive` (at least), `approximate` (about), `near` (nearly), `lower_exclusive` (over, more than), `upper_exclusive` (under, less than) |
|
|
33
|
+
| `source_id`, `snapshot_sha256`, `sentence_id` | the snapshot the row was read from, its hash at that moment, and the sentence id |
|
|
34
|
+
| `locator` | where `quote` sits in `text.txt` (`artifact`, `line`, `page`, `char_start`, `char_end`, and `table`, `row_label`, `col_label` for a table cell), plus the source's `source_kind`, `url`, `host`, and `pointed` (whether the brief's source floor names it) |
|
|
35
|
+
| `extracted_by` | the snapshot's extractor: `tool:source-snapshot@1` (fetched or executed by the script), `model` (a capture the browser lane imported; lower trust), or `extractor:<name>@<version>`; `fact-derive` for a derivation |
|
|
36
|
+
| `observed_at`, `valid_at` | when the row was registered, and the period the value describes (`--valid-at`) |
|
|
37
|
+
| `entity`, `population`, `accounting_basis`, `observation_id` | declarations the derivations check (`--entity`, `--population`, `--accounting-basis`, `--observation O<n>`) |
|
|
38
|
+
| `operation`, `operands`, `derived_from`, `formula`, `factor`, `render` | for a derived or converted row: what was computed from which rows, and the rendered text |
|
|
39
|
+
| `rationale` | why an assumed value was chosen (required for `assumed`), or why an `expr` derivation is sound |
|
|
40
|
+
| `status` | `active`, `retracted`, or `superseded`; rows are never deleted, and each change appends an event |
|
|
41
|
+
|
|
42
|
+
## Locators
|
|
43
|
+
|
|
44
|
+
| Flags | Resolves |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| `--find "<anchor>"` | one normalized anchor occurrence, then the first numeral starting within 80 characters after it, in the same sentence; `--unit-expected` checks the unit |
|
|
47
|
+
| `--table <id or caption> --row <label> --col <label>` | the cell by header labels, never by index; duplicate labels fail |
|
|
48
|
+
| `--page N --line N` | exactly one numeral on that line of an extracted document |
|
|
49
|
+
| `--match "<words>"` (`fact quote`) | the unique sentence containing the words; the whole sentence is stored, so a later partial quote cannot drop its hedge |
|
|
50
|
+
|
|
51
|
+
A locator that finds nothing returns `fact_not_located`, more than one candidate `fact_ambiguous`, and nothing is written. Read the printed row and its 60 characters of context on each side before using it; a wrong row is retracted, never edited.
|
|
52
|
+
|
|
53
|
+
## Meaning verdicts
|
|
54
|
+
|
|
55
|
+
`ingestVerdicts(pairs, verdictFiles, options)` (`scripts/meaning-check.mjs`) folds the meaning readers' verdict files over the pairs of `extractPairs` and returns four lists:
|
|
56
|
+
|
|
57
|
+
| Field | Holds |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `defects` | one `meaning_drift_confirmed` (both tiers named the same kind, never `other`) or `meaning_drift_warn` (one tier) per flagged pair, in pair order; the fragment comes from the verdict whose kind is reported |
|
|
60
|
+
| `dropped` | every verdict that was not accepted, with its file, pair, tier, and reason (unknown pair, invalid tier or verdict, unknown or empty drift kind, a fragment missing from the sentence or the source) |
|
|
61
|
+
| `unverified` | every pair no reader judged (`no_verdict`) and every `force_strong` pair no strong reader judged (`no_strong_verdict`), in pair order; a dropped verdict does not count as read |
|
|
62
|
+
| `calibrationLines` | one JSON line per flagged pair, appended to `fidelity-calibration.jsonl` when `calibrationPath` is given |
|
|
63
|
+
|
|
64
|
+
Coverage is fail-closed. A consumer treats a non-empty `unverified` list as blocking: those pairs were never read, so an empty `defects` list does not mean the report is clean. An unreadable verdict path or invalid JSON raises a `TypeError` naming the file, which the CLI maps to exit code 2.
|
|
65
|
+
|
|
66
|
+
`fact meaning-check` writes these lists into `fidelity-meaning-defects.json` through the one fidelity record writer (`writeFidelityRecord` in `scripts/fidelity-records.mjs`). The record is the envelope every fidelity record carries, `record_kind` (`meaning`), `artifact_sha256` and `report` (copied from `pairs.json`, so the record names the edition the readers judged), `written_at`, and `defects` (the folded defects plus one `meaning_unverified` per unread pair), followed by the run fields `command`, `status`, `exitCode`, `run_id`, `pairs_sha256`, `counts`, `dropped`, `unverified`, `calibration_path`, `calibration_written`, `calibration_replaced`, and `promotion_eligibility`. Any other field makes the record malformed. A pairs file without `artifact_sha256` and `report` exits 2 before anything is written. The delivery barrier refuses the record when no delivered edition's source bytes hash to its `artifact_sha256`, so a rewrite needs a fresh `fact pairs` and reader run.
|
|
67
|
+
|
|
68
|
+
## Operations
|
|
69
|
+
|
|
70
|
+
- `fact add --source S<n> <locator> --label <label>` registers a measured row; `fact add --assumed <value> --unit <unit> --rationale <why> --label <label>` registers an assumption.
|
|
71
|
+
- `fact quote --source S<n> --match "<words>" --label <label>` registers a quotation.
|
|
72
|
+
- `fact derive --op <sum|diff|growth|ratio|share|convert|expr> ...` computes a new row from active rows and prints its id; the placeholder uses that id. Operands go by position for sum, diff, and convert (`--to <unit>`), as `--from/--to`, `--part/--whole`, or `--num/--den` for growth, share, and ratio, and as one formula argument for expr. Every op except convert declares its result unit with `--unit <unit>` (`--unit null` for dimensionless); a `%` sum also needs `--disjoint --reference <denominator> --rationale <why>`. The unit rules are in `unit-rules.md`.
|
|
73
|
+
- `fact retract <id> --reason <why>` retires a row; `--replacement <id>` marks it superseded by another active row. Rows that depend on a retired row fail at fill time.
|
|
74
|
+
- `fact export --csv --out <file>` writes `fact_id,label,plot_value,unit` for every active value row: the only data a chart may plot.
|
|
75
|
+
- `fact fill <src> --out <file>` renders every placeholder from the ledger; `fact verify <file>` checks the filled edition against the ledger, the snapshots, and the claim index; `outcome set <format> delivered` records intent permissively, while the required `outcome verify` and `outcome finish` enforce the delivery barrier.
|
|
76
|
+
- `fact pairs <file>` writes `pairs.json` for the meaning readers; `fact meaning-check --pairs pairs.json --verdicts <file> ...` ingests their verdicts.
|
|
77
|
+
|
|
78
|
+
## Meaning command
|
|
79
|
+
|
|
80
|
+
`pairs.json` is `{ schemaVersion, skipped, report, format, artifact_sha256, pairs_sha256, counts, verdict_schema, pairs }`. `verdict_schema` is the machine-read verdict contract (the allowed `model_tier`, `verdict`, and `drift_kind` values and the required fields), built from the registries in `meaning-check.mjs`; hand it to the reader with the pairs. Each pair has `pair_id` (`P<n>` in document order), `kind` (`quote`, `claim`, or `translation`), `sentence_key`, `sentence`, `source_lang`, `report_lang`, `force_strong`, and either `fact_ids` with `quote` or `claim_id` with `statement`.
|
|
81
|
+
|
|
82
|
+
A reader writes one verdict file per tier: `{ "model_tier": "cheap" | "strong", "verdicts": [...] }` (a bare array works when each verdict names its own `model_tier`). One verdict per pair:
|
|
83
|
+
|
|
84
|
+
| Field | Value |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `pair_id` | a `pair_id` from `pairs.json`; any other id is dropped (`unknown_pair`) |
|
|
87
|
+
| `verdict` | `ok` or `drift` |
|
|
88
|
+
| `drift_kind` | for `drift`, exactly one of `subject_changed`, `scope_widened`, `hedge_dropped`, `certainty_added`, `causality_added`, `direction_flipped`, `population_changed`, `evidence_grade_raised`, `other` |
|
|
89
|
+
| `fragment` | for `drift`, a non-empty verbatim substring of the pair's `sentence` (whitespace-normalized) |
|
|
90
|
+
| `source_fragment` | for `drift`, a non-empty verbatim substring of the pair's `quote` or `statement` |
|
|
91
|
+
| `explanation` | one sentence, for the briefing; never read by the scripts |
|
|
92
|
+
|
|
93
|
+
A verdict that breaks any rule is dropped and listed in the record's `dropped` with its reason; it never becomes a defect. Both tiers naming the same `drift_kind` other than `other` on one pair is `meaning_drift_confirmed` (major); one tier, or two tiers that disagree, is `meaning_drift_warn` (minor). `--dispute P<n> --reason` keeps the defect and marks its calibration line `disputed`; the command still exits `1`, and the way forward is the repair loop described in deliverable-phase.md ("After a dispute"). A `{"skipped": true}` pairs file is accepted only when the locked brief says `meaning check: off`; with the check on (`meaning_check_required`) or no locked block (`fidelity_interview_incomplete`) it exits `1`. Every entry of `unverified` becomes one `meaning_unverified` defect (major), so a pair no reader judged fails the command (exit 1) through the same registry policy as any other defect. A malformed `pairs.json` or an unreadable verdict file exits 2.
|
|
94
|
+
|
|
95
|
+
`fidelity-calibration.jsonl` starts with a header line `{ "header": true, "promotion": ... }` holding the promotion criterion, then per run one run line `{ "run": true, run_id, pairs_sha256, flagged }` (written even when nothing was flagged, so `min_runs` counts real runs) and one line per flagged pair: `kind`, `pair_id`, `tiers`, `drift_kind`, `confirmed`, `disputed`, `reason`, `run_id`, `pairs_sha256`. The run id (`--run-id`, or a hash of the pairs and verdict files only, never the dispute) keys the run: rerunning the same inputs, with or without `--dispute`, replaces that run's lines in place, and a dispute recorded earlier carries forward to the rewritten lines. A corrupt log line exits `2` naming `<path>:<line>`. The record's `promotion_eligibility` evaluates the criterion over the log, counting report-level false blocks over the last `false_block_window` runs.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Fidelity Claim Kinds
|
|
2
|
+
|
|
3
|
+
A report sentence states a plain fact or quote by default. When it claims more than that (that we ran or checked something, that a number is derived, that it is an assumption), the writer marks the claim kind in the placeholder, fill renders the mark as the `data-claim-kind` attribute on the element it writes, and the fidelity gate checks that every marked fact cites a ledger row the kind accepts. The gate never infers a claim kind from wording: an unmarked sentence is checked as a plain fact or quote (so an unmarked `assumed` row is a `claim_kind_mismatch`: an unmarked assumption reads as a fact and needs its `{{A:F12:label}}` mark), and only the unmarked-warning rule raises a warning (severity minor, never blocking) when a sentence reads like the kind and cites a fact not marked with it.
|
|
4
|
+
|
|
5
|
+
A mark binds per cited fact. Each `data-fact` element takes the kind of its nearest mark (its own attribute, else the closest marked ancestor), and only that kind is checked against its row; a parent mark applies to the facts it binds, never to the sentence as a whole. A fact under marks of two different kinds is a `claim_kind_mismatch`, and a mark that binds no fact of its own (all of them are shadowed by another kind, or it cites none) is its kind's defect: shadowing never satisfies a parent.
|
|
6
|
+
|
|
7
|
+
A `verified` claim is satisfied only when the cited row itself has a locator artifact inside `sources/<source_id>/` whose snapshot `meta.json` has `kind: "command"` (recorded command or test output); a different command row elsewhere in the sentence never satisfies it. Korean phrases are shown as `\u` escapes, exactly as `claim-kinds.mjs` stores them. The defect codes are in [report-gates.md](report-gates.md).
|
|
8
|
+
|
|
9
|
+
<!-- claim-kinds:begin (rendered from CLAIM_KINDS; do not edit by hand) -->
|
|
10
|
+
| Kind | Placeholder | Attribute fill emits | Accepted row kinds | Required source kind | Defect when unsatisfied | Unmarked warning | Notes |
|
|
11
|
+
|---|---|---|---|---|---|---|---|
|
|
12
|
+
| `fact` | `{{F12:label}}` | none (or `data-claim-kind="fact"`) | `measured`, `converted`, `derived` | any | `claim_kind_mismatch` | none | Accepts exactly what an unmarked numeral accepts, so marking fact is never stricter than not marking. Neither accepts an `assumed` row: an unmarked assumption reads as a fact, so it needs its `{{A:F12:label}}` mark (`claim_kind_mismatch` otherwise). |
|
|
13
|
+
| `quote` | `{{Q7:label}}` | none (or `data-claim-kind="quote"`) | `quote` | any | `claim_kind_mismatch` | none | - |
|
|
14
|
+
| `verified` | `{{V:F12:label}}` | `data-claim-kind="verified"` | `measured`, `quote` | `command` | `unsupported_verification` | `verification_claim_unmarked` on a first-person run: we/I (have) ran, run, executed, verified by (not ran out of); by running after we/our in the sentence; \uC6B0\uB9AC or \uC800\uD76C as the subject word (+ \uAC00, \uB294, or \uD300\uC774), then \uC2E4\uD589\uD588, \uC2E4\uD589\uD558\uC5EC, \uC2E4\uD589\uD574, \uB3CC\uB838, or \uB3CC\uB824 in the clause with no third-party subject between; \uC9C1\uC811 with no third-party subject, then \uC2E4\uD589 or \uB3CC\uB9AC in the clause | The cited row itself must have a locator artifact inside `sources/<source_id>/` whose `meta.json` kind is `command`; another command row in the sentence never counts. Whether it is the right command for the claim is the meaning verifier's call (minor), not this gate's. |
|
|
15
|
+
| `derived` | `{{D:F12:label}}` | `data-claim-kind="derived"` | `derived`, `converted` | any | `claim_kind_mismatch` | none | - |
|
|
16
|
+
| `assumed` | `{{A:F12:label}}` | `data-claim-kind="assumed"` | `assumed` | any | `claim_kind_mismatch` | none | Numeric assumptions only (an assumed ledger row carries a decimal value); a qualitative assumption stays prose. |
|
|
17
|
+
<!-- claim-kinds:end -->
|
|
18
|
+
|
|
19
|
+
Regenerate the table with `node scripts/claim-kinds.mjs --render-doc`.
|
|
@@ -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,57 @@ 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 spans, numerals or units, tickers, table rows, or any markup byte (including every attribute, comments, and script/style/template content). | Revert to the pre-polish artifact and apply text-node edits only; markup changes require the full fidelity gates. |
|
|
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 fact bound to a `verified` mark (`data-claim-kind="verified"`, from a `{{V:F<n>:label}}` placeholder) cites a row whose own locator artifact does not sit in a recorded command-output snapshot, or the mark binds no fact of its own. Another command row in the same sentence never counts. Unmarked prose is never raised here. | A sentence marked verified (data-claim-kind="verified") cites a row that is not recorded command output; cite the recorded output row or drop the verified mark. |
|
|
57
|
+
| `claim_kind_mismatch` | major | false | A fact bound to a claim kind cites a row of a kind that claim kind does not accept, a fact sits under marks of two different kinds (nested marks), a mark binds no fact of its own, or a mark names an unknown kind; the kinds are in [fidelity-claim-kinds.md](fidelity-claim-kinds.md). | An element marked with a claim kind (data-claim-kind) cites a row that kind does not accept, or the kind is unknown; cite a row of that kind or fix the mark (references/fidelity-claim-kinds.md). |
|
|
58
|
+
| `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. |
|
|
59
|
+
| `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). |
|
|
60
|
+
| `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. |
|
|
61
|
+
| `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. |
|
|
62
|
+
| `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. |
|
|
63
|
+
| `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. |
|
|
64
|
+
| `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. |
|
|
65
|
+
| `meaning_unverified` | major | false | `fact meaning-check` found a pair no reader judged, or a force_strong pair no strong reader judged; an empty drift list is not a clean check. | No meaning reader judged this pair, or no strong reader judged a force_strong pair; run the missing reader on pairs.json and rerun fact meaning-check. |
|
|
66
|
+
| `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. |
|
|
67
|
+
| `polish_hedging_decreased` | major | false | The polish pass removed a hedge the source grounds. | The polish pass removed qualifiers; restore them. |
|
|
68
|
+
| `polish_text_churn` | major | false | More than half of the visible prose changed during the polish pass (`POLISH_CHURN_LIMIT` in `scripts/polish-rules.mjs`). | More than half the text changed during polish; the pass composed instead of proofreading. |
|
|
69
|
+
| `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. |
|
|
70
|
+
| `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. |
|
|
71
|
+
| `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. |
|
|
72
|
+
| `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. |
|
|
73
|
+
| `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. |
|
|
74
|
+
| `verification_claim_unmarked` | minor | false | A sentence reads as a first-person run ("we ran", "we have run", "I ran", "we executed", "we verified by", "by running" after we/our, or the Korean rule in fidelity-claim-kinds.md) and cites a fact not marked `verified` (or cites none and its block is unmarked). A warning only; it never blocks. | The sentence reads as a check we ran but carries no verified mark; mark it {{V:F<n>:label}} on a recorded command-output row, or reword it. |
|
|
75
|
+
| `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. |
|
|
76
|
+
| `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. |
|
|
77
|
+
| `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. |
|
|
78
|
+
| `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. |
|
|
79
|
+
| `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. |
|
|
80
|
+
| `polish_link_changed` | minor | false | The polish pass altered or removed an href link target, or an internal target stopped resolving. | A link was altered or removed during polish; restore it. |
|
|
81
|
+
| `polish_name_changed` | minor | false | A ledger-backed proper noun present before polish is absent afterward. | A proper noun changed during polish; restore it. |
|
|
82
|
+
|
|
32
83
|
### Layout Gate (Rendering & Presentation)
|
|
33
84
|
|
|
34
85
|
| Code | Severity | Integrity | What It Detects | How to Fix |
|
|
@@ -46,13 +97,27 @@ Gates emit a manifest-level outcome with one of three statuses:
|
|
|
46
97
|
| Status | Meaning |
|
|
47
98
|
|--------|---------|
|
|
48
99
|
| `pass` | All checks passed; no defects raised. |
|
|
49
|
-
| `fail` |
|
|
100
|
+
| `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
101
|
| `not_run` | The gate was not invoked (e.g., no probe file provided for layout, no visual inspection conducted). |
|
|
51
102
|
|
|
52
103
|
### Layout Gate Probe File Requirement
|
|
53
104
|
|
|
54
105
|
The `layout` gate only runs when a probe file (a rendering artifact: PDF, PNG, or HTML snapshot) is provided alongside the manifest. If no probe file is available, the manifest records `layout: not_run` and the gate does not emit defects.
|
|
55
106
|
|
|
107
|
+
## Polish Text-Node Contract
|
|
108
|
+
|
|
109
|
+
Polish edits change text nodes only; markup changes go through the full fidelity gates, not polish.
|
|
110
|
+
|
|
111
|
+
The primary rule is a whole-document skeleton comparison. Both gates scan the pre-polish and the polished document with the same tokenizer (`scripts/html-markup.mjs`) and require the skeleton to be byte-identical in document order: every tag token, comment, bogus comment, the frozen content of `script`, `style` and `template`, and every character reference of a text node (`&` up to the first `;` or non-name character). An accepted edit carries no `<`, `>` or `&` and may not touch a character reference, so an edited span holds no skeleton token and a legitimate polish never moves this sequence. Any difference names the first differing token and its byte offset: `polish-apply` refuses the edit, and `polish-diff` reports the blocker `polish_diff_fail` ("skeleton changed at token ..."). The character guards below are the early, actionable refusals; this comparison is what makes the guarantee complete, so a hand edit from `R&D` to `R<D` is blocked even though no edit was involved.
|
|
112
|
+
|
|
113
|
+
An edit's `before` and `after` may not contain `<`, `>` or `&` at all. `polish-apply` refuses such an edit before any other check, as `polish_edit_rejected` with the reason `edit contains markup characters (<, >, &): route this section through the full fidelity gates`, so the refusal is visible, never a silent drop. The rule holds whatever the tokenizer models: an edit without these characters cannot create, alter, close or escape a tag, comment, bogus comment, CDATA section, entity or script. The characters alone are not enough, because a located region can start right after an existing `&` or inside a character reference: `polish-apply` also refuses, as `edit touches a character reference: route this section through the full fidelity gates`, any edit whose located region overlaps a character reference or opens one. Literal `&` and `<` in prose are entities in the source (`R&D`, `p < 0.05`) and stay usable only by leaving their bytes untouched: the proofread lane narrows an edit to the words around an entity or tag (`budget grew` to `budget rose`), never one that spans it. Wording that cannot be fixed without touching an entity or markup goes through the full fidelity gates.
|
|
114
|
+
|
|
115
|
+
Before comparing, both gates refuse with `polish_diff_fail` ("ambiguous markup: ...") any document holding a construct the polish tokenizer does not model exactly: `</` followed by a non-letter (`</>` included), `<!--` inside a `script` or `style` element, `<![CDATA[`, `<?`, `--!>`, or `<` inside a tag or attribute value. Renderer output contains none of these. The tokenizer still follows the HTML spec for the bogus comment (`</` + non-letter, `<?`, `<!` up to the next `>`), the abrupt comment closes `<!-->` and `<!--->`, and the script-data escaped and double-escaped states.
|
|
116
|
+
|
|
117
|
+
The shared rule in `scripts/polish-rules.mjs` runs per edit against the current and original report in `polish-apply`, and against the whole document in `polish-diff`. The sequence of opening and closing tags, every attribute name and value (including `href`, `id`, `class`, and `style`), comments, declarations, and all content of `script`, `style`, and `template` elements must be byte-identical. Attribute reordering, different quoting, tag case, whitespace inside a tag, and a self-closing slash are markup changes too. Any difference raises the blocker `polish_diff_fail`; apply rejects it with reason `markup changed`.
|
|
118
|
+
|
|
119
|
+
Text nodes remain subject to the existing fact-span, number/unit, ticker, hedge, qualifier, name, and churn checks. Protected numbers, tickers, and required hedges cannot migrate between text nodes. A text edit inside an existing fact span is still a fact-span change, including under `aria-hidden`. Script/style/template content is frozen through the end of input when unclosed. No CSS or HTML visibility model is used by polish.
|
|
120
|
+
|
|
56
121
|
## Lineage and Citation Markers
|
|
57
122
|
|
|
58
123
|
Defect codes and their hints are delivered via the outcome manifest under `residualDefects` (if repair did not exhaust). Each defect entry includes:
|
|
@@ -62,7 +127,7 @@ Defect codes and their hints are delivered via the outcome manifest under `resid
|
|
|
62
127
|
|
|
63
128
|
Citations within reports follow one of two lineage modes:
|
|
64
129
|
|
|
65
|
-
- **inline**: Source marks appear as `[Sn]` or `[
|
|
130
|
+
- **inline**: Source marks appear as `[Sn]`, `[Source n]`, or `[^n]` hyperlinks inline with the cited text.
|
|
66
131
|
- **section**: Sources are listed in a dedicated section with numbered entries ([S1], [S2], etc.).
|
|
67
132
|
|
|
68
133
|
Both modes are valid; choose based on the report's narrative flow.
|
|
@@ -44,6 +44,8 @@ uv run --with numpy --with polars --with matplotlib python plot_<name>.py
|
|
|
44
44
|
- Keep chart text as real text: set `matplotlib.rcParams["svg.fonttype"] = "none"` before saving an SVG. The default converts text to paths, and the static gate then sees a chart with no title, ticks, or labels.
|
|
45
45
|
- Use the design spec's font family and palette tokens (`rcParams["font.family"]`, explicit colors from the spec). One accent color for the series that carries the finding; neutral tones for the rest.
|
|
46
46
|
- Title, axis labels with units, value labels on bars or end points, ticks at round values computed from the data range.
|
|
47
|
+
- Plot only from the fact ledger: export the rows with `node "$SKILL_DIR/scripts/report-tools.mjs" fact export --csv --out "$SESSION_DIR/assets/<chart>.csv" --session-dir "$SESSION_DIR"`, draw from that CSV, and give the chart figure `data-chart-source="assets/<chart>.csv"`.
|
|
48
|
+
- Emit the axis tick labels inside one `<g class="ticks" data-tick-step=".." data-tick-min=".." data-tick-max="..">` group, so the fidelity gate can check every tick against the declared grid and every value label against the ledger.
|
|
47
49
|
- One message per chart. A chart that needs a paragraph to explain is two charts.
|
|
48
50
|
- For a web deliverable, HTML/CSS bars or an inline SVG built from the same table are preferred over an image.
|
|
49
51
|
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Unit rules for derived facts
|
|
2
|
+
|
|
3
|
+
The one definition of which unit a derived or converted fact row carries, and the reviewer's checklist for
|
|
4
|
+
`scripts/unit-rules.mjs`. ONE registry (`OPERATION_RULES`) owns, per operation: arity, operand-unit guards, context
|
|
5
|
+
fields, result-unit inference, and malformed shapes. `derive()` (`fact-derive.mjs`) and `recompute()`
|
|
6
|
+
(`fact-recompute.mjs`) both call it; neither has op-specific unit code. `row.unit` is NEVER used to choose arithmetic;
|
|
7
|
+
numeric guards may read `exact` values, unit selection may not. The property tests in
|
|
8
|
+
`scripts/fact-unit-rules.test.ts` iterate the registry, so a new operation needs a table row here and cases there.
|
|
9
|
+
|
|
10
|
+
## Units
|
|
11
|
+
- Canonical unit text is stored and compared exactly (case-sensitive symbols). Registered aliases
|
|
12
|
+
(`pp` -> `%p`, `kilometre` -> `km`, ...) are canonicalized ONLY at input (derive/fact add); a relabel to an alias
|
|
13
|
+
at rest is a relabel and is detected. Unit text with no alias is stored as given: whitespace is trimmed only around
|
|
14
|
+
`*`, `/`, `^`, and parentheses, so `million people`, `metric ton`, and `USD per person` keep their inner spaces.
|
|
15
|
+
- A scale word (`million`, `M`, `bn`, `billion`, `thousand`, `e6`, ...; the `scale` rows of `units.mjs`) is a
|
|
16
|
+
multiplier, not a unit, and denomination scaling is out of scope, so it never becomes a unit atom: `million`,
|
|
17
|
+
`USD/M`, and `million*person` are refused at input (derive, and every operand read). Either store the scaled numeral
|
|
18
|
+
in the counted unit (5 million people as `5000000 person`) or keep the whole phrase as plain unit text:
|
|
19
|
+
`million people` has no table alias as a whole, so it is stored as given and sums only with `million people`, never
|
|
20
|
+
with `person`.
|
|
21
|
+
- `null` = dimensionless. Omitted unit on a derived spec is an error, not null (distinguish omission from declared null).
|
|
22
|
+
- Percent `%` stores percentage numerals (20% stores 20). Delta `%p` (percentage points). 1 basis point = 0.01 %p
|
|
23
|
+
(input alias `bp` -> `%p` with /100 scaling).
|
|
24
|
+
- Composite units are canonical algebraic strings built by the registry (`USD/kg`, `person`), never by concatenating
|
|
25
|
+
operand strings: equal factors cancel (`USD/(USD/person)` -> `person`).
|
|
26
|
+
- Affine scales (temperature: `C`, `F`) are flagged in the unit table; sum/diff/growth/share/ratio and every expr
|
|
27
|
+
node refuse them (temperatures are not summed or differenced as absolute values); only convert takes them.
|
|
28
|
+
Affine atoms in composites are refused before cancellation. Exponents are exact signed bigint integers, including zero.
|
|
29
|
+
|
|
30
|
+
## Operation table
|
|
31
|
+
|
|
32
|
+
| op | arity | operand guards | context fields (persisted on the row) | result unit | malformed -> recompute ok:false |
|
|
33
|
+
|---|---|---|---|---|---|
|
|
34
|
+
| sum | n>=2 | non-affine units, all equal after canonicalization; if `%`: `disjoint: true` AND `reference` (one denominator id/text) equal on every operand AND rationale | disjoint, reference, rationale | the common unit (`%` stays `%`) | <2 operands; missing id; no context; unequal/affine units; `%` without disjoint, reference, or rationale |
|
|
35
|
+
| diff | 2 | non-affine units; typed pairs only: U-U -> U (same non-% unit); %-% -> `%p`; %-%p -> `%`; %p-%p -> `%p`; %p-% REFUSED | none | per the pair rule | arity; invalid pair (`%p - %`, `m - person`); affine units; stray context |
|
|
36
|
+
| growth | 2 (from,to) | equal non-affine units; same entity; two different valid_at; from.exact > 0 | none | `%` (= 100(to-from)/from) | arity; unequal/affine units; entity/valid_at; from<=0; stray context |
|
|
37
|
+
| share | 2 (part,whole) | equal non-affine units; whole.exact > 0; 0 <= part <= whole | none | `%` (= 100 part/whole) | arity; units; whole<=0; part outside [0,whole]; stray context |
|
|
38
|
+
| ratio | 2 (num,den) | non-affine units; den.exact != 0; unequal `%`/`%p` REFUSED | none | registry composite: equal units -> null; else canonical `U(num)/U(den)` with cancellation | arity; den=0; stray context |
|
|
39
|
+
| convert | 1 | U(a) has a registered factor to `target`; currencies REFUSED (use expr with a dated rate row) | target (persisted as canonical text; the ONLY accepted declared unit; `row.unit` is compared to it exactly, never canonicalized at rest) | the persisted target | arity; no context; target missing; target not canonical (an alias at rest); currency target; no factor; declared unit != persisted target |
|
|
40
|
+
| expr | n>=1 | formula ids == operand set; node rules: `+`/`-` follow the sum/diff typed-pair rules, affine refusal included (so `20% - 10%` is `%p`, never `%`, and `25 C + 30 C` is refused); `+` also takes `%` + `%p` in either order -> `%` (as diff's `%-%p`), while `%` + `%` is refused (use sum); `*` and `/` compose canonical composites, `%`/`%p` operands normalize by /100 to dimensionless first; result must be fully inferred: NO rationale escape | none | the inferred unit; an explicit null->`%` conversion is a separate `convert`-like node (`pct()`) | formula/operand id mismatch; parse error; /0; uninferable unit; affine operands; stray context |
|
|
41
|
+
|
|
42
|
+
Every row's malformed column also holds the two operand-identity shapes below (`repeated operand`, `self reference`).
|
|
43
|
+
|
|
44
|
+
## Operand identity (applies to every row)
|
|
45
|
+
- Operand ids are DISTINCT within one derived row. sum of F1, F1 is not a sum of two shares, and diff, ratio, share,
|
|
46
|
+
growth, or convert of an operand with itself is meaningless and would dodge every pair guard. A repeated id is
|
|
47
|
+
refused by `derive()` (`operand F1 is repeated`) and is `ok:false` at `recompute()` (malformed shape
|
|
48
|
+
`repeated operand`). The check sits in the registry (`expectedUnit` and `malformed`), so no operation can skip it.
|
|
49
|
+
- expr may reference the same id in several leaves (`F1 * F1` is a legitimate square). Its stored operand list is the
|
|
50
|
+
formula's id SET, which must equal the formula ids (`formula id mismatch`); an id listed twice in that list is the
|
|
51
|
+
`repeated operand` shape too.
|
|
52
|
+
- A derived row may not cite itself, directly (`self reference`: its own id among its operands) or through nested
|
|
53
|
+
derived operands (a cycle). `recompute()` refuses both. `derive()` recomputes every derived operand first and
|
|
54
|
+
refuses one that does not recompute (tampered, cyclic, or self-citing), so nothing is built on such a row.
|
|
55
|
+
|
|
56
|
+
## Invariants (property tests iterate the table)
|
|
57
|
+
1. For each op: generate valid typed operands (rational boundaries, aliases at input, composites, %/%p, affine,
|
|
58
|
+
metadata, conversion targets, repeated expr refs), derive, assert `recompute(row).ok === true`.
|
|
59
|
+
2. Relabel: for each op, set `unit` to every different canonical string/null (incl. aliases and other valid targets),
|
|
60
|
+
regenerate render, keep exact: `recompute(row).ok === false` naming the expected unit; and `derive()` with that
|
|
61
|
+
declared unit is refused.
|
|
62
|
+
3. Malformed: per op, every shape in the table's malformed column has one case, named in the registry's
|
|
63
|
+
`OPERATION_RULES[op].malformed` list (the test asserts its case names equal that list): `recompute` returns
|
|
64
|
+
`ok:false` for that shape's own reason, never throws.
|
|
65
|
+
4. Nested derived rows are verified recursively (operands may be derived rows); cycles and self references are
|
|
66
|
+
refused, by `recompute()` and by `derive()` before it builds on a derived operand.
|
|
67
|
+
5. Render precision (`renderPrecision` in `unit-rules.mjs`): fewest decimal places for sum, diff, an expr whose root
|
|
68
|
+
node is `+` or `-`, and every `%p` result; fewest significant figures otherwise (an expr `*` or `/` root with a
|
|
69
|
+
non-`%p` result included). Operand values and expr literals both count.
|
|
70
|
+
|
|
71
|
+
## Decisions
|
|
72
|
+
- Q1: the canonical composite goes in `unit` (consumers compare `unit` text); no side field.
|
|
73
|
+
- Q2: expr with an unresolved unit is REFUSED; a known-unit `a*b/c` is inferable, so no rationale escape exists.
|
|
74
|
+
- Q3: canonical `%p`, input alias `pp` (matches units.mjs).
|
|
75
|
+
- Q4: strict null metadata: null matches only null; required metadata must be present.
|
|
76
|
+
|
|
77
|
+
## Out of scope (follow-ups)
|
|
78
|
+
Per-capita identity, named index/base and index-point differences, weighted means, dated FX / nominal-real bases,
|
|
79
|
+
same-currency denomination scaling (M/B), summing ratios over a common base. Each needs its own table row + tests.
|
|
80
|
+
|
|
81
|
+
## Dimensions
|
|
82
|
+
|
|
83
|
+
1. Enforced: kind and operation agree; a changed discriminator cannot disable recursive verification.
|
|
84
|
+
2. Enforced: expression and direct arithmetic check population, snapshot, and accounting metadata; common metadata propagates.
|
|
85
|
+
3. Enforced: stored `precision: { places, sigfigs }` carries operand precision independently of display trailing zeros.
|
|
86
|
+
4. Enforced: scaled aliases normalize at every composite factor and exponent, scaling the input numeral exactly.
|
|
87
|
+
5. Enforced: derive and recompute return classified refusals with `shape`, `expected`, and `detail`; derive never appends on refusal.
|
|
88
|
+
6. Enforced: aliases canonicalize at input; noncanonical stored results and conversion targets are refused, and a source unit that needs rescaling (a scaled alias) is refused as an operand.
|
|
89
|
+
7. Enforced: stored rationals are reduced integer strings with positive denominators and canonical zero.
|
|
90
|
+
8. Enforced: operation contexts have closed keys and types, including non-percent sums and context-free operations.
|
|
91
|
+
9. Enforced: formula, factor, derived_from, raw, render, metadata, precision, and compatibility are compared on replay.
|
|
92
|
+
10. Enforced: metadata object equality ignores key insertion order; missing and invalid metadata never equal explicit null.
|
|
93
|
+
11. Enforced: new derivations require active transitive dependencies; historical arithmetic remains reproducible after retraction.
|
|
94
|
+
12. Enforced: graph and expression traversal use explicit stacks; shared nodes are evaluated once per verification.
|
|
95
|
+
13. Enforced: factor exponents use bigint, preserve grouping and quotient direction, and canonicalize idempotently.
|
|
96
|
+
14. Enforced: affine atoms cannot hide in composites or cancellation; scale words are never unit atoms.
|
|
97
|
+
15. Enforced: disjoint percentage shares are individually in [0,100], total at most 100, and use exactly one reference.
|
|
98
|
+
16. Enforced: currency table conversion is refused; FX expressions require a dated rate and persist compatibility `unchecked`.
|
|
99
|
+
17. Enforced: symbols are case-sensitive; only registered spelling aliases normalize; opaque Unicode and phrases stay distinct.
|
|
100
|
+
18. Enforced: missing, undefined, and empty required fields do not substitute for explicit null; zero remains valid.
|
|
101
|
+
19. Enforced: identifiers allocate exactly beyond 2^53 using bigint; operand lists remain distinct.
|
|
102
|
+
20. Enforced: a supplied expression operand list must equal the formula's unique leaf set.
|
|
103
|
+
21. Enforced: additive expression roots and percentage-point results use decimal places; other roots count literal significant figures.
|
|
104
|
+
22. Enforced: cloned snapshots with the same spec and timestamp produce identical rows; replay appends a new identity.
|
|
105
|
+
23. Documented limitation: coherent rewrites of trusted operands, context, and all dependent audit fields require external provenance to detect.
|
|
106
|
+
24. Enforced: arity belongs to each table row; sums are permutation-invariant while ordered operations keep positional meaning.
|
|
107
|
+
25. Enforced: denominators, positive growth starts, and bounded shares obey numeric domains; ordinary negative arithmetic remains valid.
|
|
108
|
+
26. Enforced: percent, percentage-point, and fraction semantics follow typed pairs, multiplicative normalization, and explicit pct nodes.
|
|
109
|
+
27. Enforced: table factors and affine offsets compose exactly; unknown and cross-dimension conversions are refused.
|
|
110
|
+
28. Enforced: only decimal literals, fact identifiers, binary arithmetic, parentheses, and pct parse; unsupported syntax is refused.
|
|
111
|
+
29. Enforced: rounding is half away from zero; values are plain decimals and display uses canonical units and grouping.
|
|
112
|
+
30. Enforced: seeded factor trees and conversion compositions have expected values computed independently of OPERATION_RULES.
|
|
113
|
+
31. Enforced: a ledger written before `context`, `precision`, and `compatibility` existed still loads and accepts new derivations. On measured, quote, and assumed rows a missing column reads as null, and a registered alias unit is canonicalized on read (unknown or scaled text stays as given); the file changes only on the next write. Derived and converted rows without those columns load, but `recompute` reports shape `legacy derived row` and `derive` refuses them as operands with the same shape until they are regenerated.
|
|
114
|
+
32. Enforced: value/exact agreement. When a row stores both, `exact` must equal `value` at the value's decimal places; a legacy row that disagrees loads and is flagged `dimension 32`, and `addRow` refuses a new one.
|
|
115
|
+
|
|
116
|
+
## Precedence: dimension 31 wins at read time
|
|
117
|
+
|
|
118
|
+
Anything dev's shipped writer could write loads and validates. Every row is first read through `readRow`: exacts that
|
|
119
|
+
are integer pairs are reduced (sign on the numerator, no leading zeros, positive denominator), decimal values lose
|
|
120
|
+
leading zeros, and source rows get canonical units and null later columns. Measured exacts stay as stored because they
|
|
121
|
+
are always the reduced exact of `value`. Only then do the strict dimensions run. They apply in full to derived and
|
|
122
|
+
converted rows that carry this version's columns, and to every row this version writes. A source row that loads but
|
|
123
|
+
still breaks a strict rule (a scale word as unit, empty metadata, an operation or derivation fields) is flagged when it
|
|
124
|
+
is used: `derive` and `recompute` refuse it with shape `dimension 6`, `dimension 18`, or `dimension 1`, and `addRow`
|
|
125
|
+
refuses to write a new one. Normalization never strips user data: an `exact` carrying keys beyond `num` and `den` is left exactly as written and flagged `dimension 7` on use, never silently reduced to `{ num, den }`. Reading a normalized file again changes nothing. The legacy test fixture is generated by
|
|
126
|
+
dev's own `addRow` (`scripts/tests/fixtures/fidelity/gen-legacy-dev.mjs`, which pins the dev commit).
|
|
127
|
+
|
|
128
|
+
## Trust boundary
|
|
129
|
+
|
|
130
|
+
Recomputation verifies arithmetic against the ledger's trusted operands and operation context, not against an external
|
|
131
|
+
immutable source. A zero-metre conversion rewritten from km to cm together with its target, formula, factor, precision,
|
|
132
|
+
and display is indistinguishable from an honestly generated cm conversion. Single-field relabels are detected; a coherent
|
|
133
|
+
rewrite needs an immutable ledger baseline or source provenance outside this arithmetic verifier.
|
|
134
|
+
|
|
135
|
+
Rows carry no per-row schema marker, so a current derived row with `context`, `precision`, and `compatibility` all
|
|
136
|
+
deleted reads as a legacy row: `validateLedger` skips its at-rest unit and row-shape checks, and a relabeled unit on
|
|
137
|
+
it passes validation. It never becomes trusted again: `recompute` and `derive` refuse it as `legacy derived row`.
|
|
138
|
+
|
|
139
|
+
## Implementation notes
|
|
140
|
+
|
|
141
|
+
- Context fields live in the row's `context` column (null or an object on derived and converted rows, always null on
|
|
142
|
+
measured, quote, and assumed rows: a `KIND_RULES` column):
|
|
143
|
+
sum stores `{ disjoint, reference }`, convert stores `{ target }`. The sum rationale stays in `rationale`.
|
|
144
|
+
Schema and recomputation both require the operation's context. Context-free rows carry explicit null.
|
|
145
|
+
- `schemaVersion` remains 1. A derived or converted row from an older writer (no `context`, `precision`, or
|
|
146
|
+
`compatibility`) is kept as written and never used as an operand: regenerate it with `derive` to carry precision,
|
|
147
|
+
compatibility, and complete audit fields. Older source rows need nothing: they are read with null later columns.
|
|
148
|
+
- `reference` is either one text (the caller asserts one shared denominator) or a map from each operand id to its
|
|
149
|
+
denominator; the map passes only when every operand names the same non-empty denominator.
|
|
150
|
+
- `addRow` canonicalizes source units and scales alias numerals, including `100 bp/person` to `1 %p/person`.
|
|
151
|
+
At rest, source-row aliases are canonicalized on read (dimension 31); current derived rows with alias units are refused. A declared result unit with a nontrivial alias scale is refused.
|
|
152
|
+
Scale exponents with absolute value above 10000 are explicitly refused instead of allocating an unbounded numeral.
|
|
153
|
+
- A ratio over `%` or `%p` operands with unequal units is refused (use expr, where `%` enters `*` and `/` as a fraction).
|
|
154
|
+
- convert reads its target from `to`; a declared `unit` is optional and must equal that target.
|
|
155
|
+
- expr persists compatibility `unchecked` on the row as well as returning it. Population, snapshot, and accounting
|
|
156
|
+
predicates apply; a currency-rate operand needs a nonempty `valid_at`. This is arithmetic and unit verification,
|
|
157
|
+
not a guarantee of rate freshness, matching dates, population identity, or financial comparability.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// claim-kinds.mjs - the claim kinds a report sentence can carry, as one table, CLAIM_KINDS.
|
|
2
|
+
//
|
|
3
|
+
// A claim kind is structural: the writer marks it in the placeholder ({{V:F12:label}}), fill
|
|
4
|
+
// emits it as the data-claim-kind attribute on the element it renders, and the fidelity gate
|
|
5
|
+
// (fidelity-claims.mjs) checks that every marked element cites a row the kind accepts. An
|
|
6
|
+
// unmarked element is a plain fact or quote and is checked only by the value and quote checks.
|
|
7
|
+
// The one lexical piece is `unmarked`: a few first-person run patterns that raise a minor warning
|
|
8
|
+
// when a sentence reads like the kind but carries no mark; they never raise a major. The table in
|
|
9
|
+
// references/fidelity-claim-kinds.md is rendered from CLAIM_KINDS (`node claim-kinds.mjs --render-doc`).
|
|
10
|
+
// Pure; node: builtins only. Korean phrases are \u escapes.
|
|
11
|
+
|
|
12
|
+
import { isCliEntry } from "./entry-guard.mjs"
|
|
13
|
+
|
|
14
|
+
export const CLAIM_ATTRIBUTE = "data-claim-kind"
|
|
15
|
+
|
|
16
|
+
const kind = (entry) => Object.freeze({ ...entry, rowKinds: Object.freeze(entry.rowKinds), sourceKinds: entry.sourceKinds && Object.freeze(entry.sourceKinds), unmarked: entry.unmarked && Object.freeze({ ...entry.unmarked, patterns: Object.freeze(entry.unmarked.patterns) }) })
|
|
17
|
+
|
|
18
|
+
// Korean pieces as \u escapes: WE_SUBJECT = uri|jeohui as a standalone subject word (+ ga|neun, or " tim-i"),
|
|
19
|
+
// WE_RUN = silhaeng-haet/hayeo/hae | dol-lyeot/lyeo, DIRECT = jikjeop, RUN = silhaeng | dol-li/ryeo/ryeot/rin/ril,
|
|
20
|
+
// SUBJECT = a word ending in the particle ga|i|eun|neun|kkeseo (a third party ran it, not us).
|
|
21
|
+
const KO_WE_SUBJECT = "(?:^|[\\s,.;!?(])(?:\uC6B0\uB9AC|\uC800\uD76C)(?:[\uAC00\uB294]|\\s+\uD300\uC774)\\s+"
|
|
22
|
+
const KO_WE_RUN = "(?:\uC2E4\uD589(?:\uD588|\uD558\uC5EC|\uD574)|\uB3CC[\uB838\uB824])"
|
|
23
|
+
const KO_RUN = "(?:\uC2E4\uD589|\uB3CC[\uB9AC\uB824\uB838\uB9B0\uB9B4])"
|
|
24
|
+
const KO_SUBJECT = "[^\\s,.;!?]*(?:[\uAC00\uC774\uC740\uB294]|\uAED8\uC11C)(?=\\s)"
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* kind -> { prefix: placeholder prefix (null = the default form), placeholder: an example,
|
|
28
|
+
* rowKinds: ledger row kinds it accepts, sourceKinds: meta.json kinds the snapshot holding the
|
|
29
|
+
* cited row's own locator artifact must have (null = any), defect: code when a marked fact cites a
|
|
30
|
+
* row it refuses, note: the rule's limits, unmarked: { code, rule, patterns } for an unmarked
|
|
31
|
+
* sentence that reads like the kind (a minor warning only), or null }.
|
|
32
|
+
*/
|
|
33
|
+
export const CLAIM_KINDS = Object.freeze({
|
|
34
|
+
fact: kind({
|
|
35
|
+
prefix: null,
|
|
36
|
+
placeholder: "{{F12:label}}",
|
|
37
|
+
rowKinds: ["measured", "converted", "derived"],
|
|
38
|
+
sourceKinds: null,
|
|
39
|
+
defect: "claim_kind_mismatch",
|
|
40
|
+
note: "Accepts exactly what an unmarked numeral accepts, so marking fact is never stricter than not marking. Neither accepts an `assumed` row: an unmarked assumption reads as a fact, so it needs its `{{A:F12:label}}` mark (`claim_kind_mismatch` otherwise).",
|
|
41
|
+
unmarked: null,
|
|
42
|
+
}),
|
|
43
|
+
quote: kind({ prefix: null, placeholder: "{{Q7:label}}", rowKinds: ["quote"], sourceKinds: null, defect: "claim_kind_mismatch", note: "", unmarked: null }),
|
|
44
|
+
verified: kind({
|
|
45
|
+
prefix: "V",
|
|
46
|
+
placeholder: "{{V:F12:label}}",
|
|
47
|
+
rowKinds: ["measured", "quote"],
|
|
48
|
+
sourceKinds: ["command"],
|
|
49
|
+
defect: "unsupported_verification",
|
|
50
|
+
note: "The cited row itself must have a locator artifact inside `sources/<source_id>/` whose `meta.json` kind is `command`; another command row in the sentence never counts. Whether it is the right command for the claim is the meaning verifier's call (minor), not this gate's.",
|
|
51
|
+
unmarked: {
|
|
52
|
+
code: "verification_claim_unmarked",
|
|
53
|
+
rule: "a first-person run: we/I (have) ran, run, executed, verified by (not ran out of); by running after we/our in the sentence; \\uC6B0\\uB9AC or \\uC800\\uD76C as the subject word (+ \\uAC00, \\uB294, or \\uD300\\uC774), then \\uC2E4\\uD589\\uD588, \\uC2E4\\uD589\\uD558\\uC5EC, \\uC2E4\\uD589\\uD574, \\uB3CC\\uB838, or \\uB3CC\\uB824 in the clause with no third-party subject between; \\uC9C1\\uC811 with no third-party subject, then \\uC2E4\\uD589 or \\uB3CC\\uB9AC in the clause",
|
|
54
|
+
patterns: [
|
|
55
|
+
/\b(?:we|I)(?:'ve)?\s+(?:(?:have|had|also|then|first|just|again)\s+)*(?:ran|run|re-?ran|re-?run|executed|verified\s+by)\b(?!\s+out\s+of\b)/i,
|
|
56
|
+
/\b(?:we|our)\b.*?\bby\s+running\b/i,
|
|
57
|
+
new RegExp(`${KO_WE_SUBJECT}(?:(?!${KO_SUBJECT})[^\\s,.;!?]+\\s+)*?${KO_WE_RUN}`),
|
|
58
|
+
new RegExp(`(?:^|[,.;!?])\\s*(?:(?!${KO_SUBJECT})[^\\s,.;!?]+\\s+)*\uC9C1\uC811\\s*(?:[^\\s,.;!?]+\\s*)??${KO_RUN}`),
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
derived: kind({ prefix: "D", placeholder: "{{D:F12:label}}", rowKinds: ["derived", "converted"], sourceKinds: null, defect: "claim_kind_mismatch", note: "", unmarked: null }),
|
|
63
|
+
assumed: kind({
|
|
64
|
+
prefix: "A",
|
|
65
|
+
placeholder: "{{A:F12:label}}",
|
|
66
|
+
rowKinds: ["assumed"],
|
|
67
|
+
sourceKinds: null,
|
|
68
|
+
defect: "claim_kind_mismatch",
|
|
69
|
+
note: "Numeric assumptions only (an assumed ledger row carries a decimal value); a qualitative assumption stays prose.",
|
|
70
|
+
unmarked: null,
|
|
71
|
+
}),
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
/** Whether a row satisfies a claim kind, given the meta.json kind of the snapshot holding its own locator artifact. */
|
|
75
|
+
export function claimSatisfied(name, row, sourceKind) {
|
|
76
|
+
const entry = CLAIM_KINDS[name]
|
|
77
|
+
return Boolean(entry && row && entry.rowKinds.includes(row.kind) && (entry.sourceKinds === null || entry.sourceKinds.includes(sourceKind)))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** The kind an unmarked element citing `row` must be marked with (an assumed row needs `assumed`), or null when unmarked is fine. */
|
|
81
|
+
export function unmarkedRequires(row) {
|
|
82
|
+
if (!row || ["fact", "quote"].some((name) => CLAIM_KINDS[name].rowKinds.includes(row.kind))) return null
|
|
83
|
+
return Object.keys(CLAIM_KINDS).find((name) => CLAIM_KINDS[name].rowKinds.includes(row.kind)) ?? null
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** The kinds whose unmarked patterns match the sentence. */
|
|
87
|
+
export function unmarkedKinds(text) {
|
|
88
|
+
return Object.entries(CLAIM_KINDS)
|
|
89
|
+
.filter(([, entry]) => entry.unmarked?.patterns.some((re) => re.test(text)))
|
|
90
|
+
.map(([name]) => name)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const CLAIM_TABLE_BEGIN = "<!-- claim-kinds:begin (rendered from CLAIM_KINDS; do not edit by hand) -->"
|
|
94
|
+
export const CLAIM_TABLE_END = "<!-- claim-kinds:end -->"
|
|
95
|
+
|
|
96
|
+
const code = (text) => `\`${text}\``
|
|
97
|
+
|
|
98
|
+
/** The Markdown table of references/fidelity-claim-kinds.md. */
|
|
99
|
+
export function renderClaimKindTable() {
|
|
100
|
+
const head = ["| Kind | Placeholder | Attribute fill emits | Accepted row kinds | Required source kind | Defect when unsatisfied | Unmarked warning | Notes |", "|---|---|---|---|---|---|---|---|"]
|
|
101
|
+
const lines = Object.entries(CLAIM_KINDS).map(([name, entry]) => {
|
|
102
|
+
const attribute = entry.prefix === null ? `none (or ${code(`${CLAIM_ATTRIBUTE}="${name}"`)})` : code(`${CLAIM_ATTRIBUTE}="${name}"`)
|
|
103
|
+
const source = entry.sourceKinds === null ? "any" : entry.sourceKinds.map(code).join(", ")
|
|
104
|
+
const warn = entry.unmarked ? `${code(entry.unmarked.code)} on ${entry.unmarked.rule}` : "none"
|
|
105
|
+
return `| ${code(name)} | ${code(entry.placeholder)} | ${attribute} | ${entry.rowKinds.map(code).join(", ")} | ${source} | ${code(entry.defect)} | ${warn} | ${entry.note || "-"} |`
|
|
106
|
+
})
|
|
107
|
+
return `${[...head, ...lines].join("\n")}\n`
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (isCliEntry(import.meta.url)) {
|
|
111
|
+
if (process.argv[2] === "--render-doc" && process.argv.length === 3) process.stdout.write(renderClaimKindTable())
|
|
112
|
+
else {
|
|
113
|
+
process.stderr.write("usage: node claim-kinds.mjs --render-doc\n")
|
|
114
|
+
process.exitCode = 2
|
|
115
|
+
}
|
|
116
|
+
}
|