oh-my-opencode 5.1.48 → 5.1.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/refusal-rule.d.ts +7 -0
- package/dist/cli/index.js +1194 -752
- package/dist/cli/service-auth/accounts-gate.d.ts +11 -0
- package/dist/cli/service-auth/commands.d.ts +2 -4
- package/dist/cli/service-auth/index.d.ts +1 -1
- package/dist/cli/service-auth/keystore.d.ts +26 -2
- package/dist/cli/service-auth/protocol.d.ts +7 -1
- package/dist/cli/service-auth/session.d.ts +6 -0
- package/dist/cli/service-auth/signed-out-marker.d.ts +11 -0
- package/dist/cli-node/index.js +1194 -752
- package/dist/config/schema/hooks.d.ts +1 -0
- package/dist/create-hooks.d.ts +1 -0
- package/dist/features/boulder-state/storage.d.ts +1 -1
- package/dist/features/boulder-state/types.d.ts +1 -1
- package/dist/hooks/atlas/idle-continuation.d.ts +2 -1
- package/dist/hooks/atlas/types.d.ts +9 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/momus-review-persistence/hook.d.ts +19 -0
- package/dist/hooks/momus-review-persistence/index.d.ts +1 -0
- package/dist/hooks/momus-review-persistence/review-resolution.d.ts +20 -0
- package/dist/hooks/prometheus-md-only/constants.d.ts +2 -0
- package/dist/hooks/prometheus-md-only/fixtures/denial-log.d.ts +1 -0
- package/dist/hooks/prometheus-md-only/fixtures/guarded-hashline.d.ts +1 -0
- package/dist/hooks/prometheus-md-only/fixtures/invoke-before.d.ts +7 -0
- package/dist/hooks/prometheus-md-only/fixtures/opencode-patch-parser.d.ts +2 -0
- package/dist/hooks/prometheus-md-only/hook.d.ts +5 -1
- package/dist/hooks/prometheus-md-only/path-policy.d.ts +2 -9
- package/dist/hooks/prometheus-md-only/vendor/opencode-patch-parser.d.ts +22 -0
- package/dist/index.js +2322 -1045
- package/dist/plugin/hooks/create-core-hooks.d.ts +1 -0
- package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +2 -1
- package/dist/shared/posthog-activity-state.d.ts +1 -0
- package/dist/shared/posthog.d.ts +1 -2
- package/dist/shared/resolve-file-write-path.d.ts +6 -0
- package/dist/skills/ast-grep/README.md +1 -1
- package/dist/skills/ast-grep/install.ps1 +5 -3
- package/dist/skills/ast-grep/install.sh +4 -5
- package/dist/skills/ast-grep/references/install.md +2 -2
- package/dist/skills/ast-grep/scripts/ast_grep_helper.py +13 -3
- package/dist/skills/browser/runtime/omowright/manifest.json +1 -1
- package/dist/skills/coding-agent-sessions/AGENTS.md +5 -4
- package/dist/skills/coding-agent-sessions/SKILL.md +11 -11
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +2 -2
- package/dist/skills/coding-agent-sessions/references/codex.md +4 -4
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +1 -1
- package/dist/skills/coding-agent-sessions/scripts/find-agent-sessions.py +6 -3
- package/dist/skills/frontend/ATTRIBUTION.md +1 -1
- package/dist/skills/frontend/SKILL.md +34 -12
- package/dist/skills/frontend/references/design/README.md +2 -2
- package/dist/skills/frontend/references/design/_INDEX.md +2 -1
- package/dist/skills/frontend/references/design/component-catalogs.md +14 -10
- package/dist/skills/frontend/references/design/design-system-architecture.md +19 -6
- package/dist/skills/frontend/references/design/grounding.md +29 -0
- package/dist/skills/frontend/references/ui-ux-db/scripts/design_system.py +2 -0
- package/dist/skills/frontend/references/ui-ux-db/scripts/search.py +2 -0
- package/dist/skills/ultimate-browsing/SKILL.md +5 -4
- package/dist/skills/ultimate-browsing/engine/AGENTS.md +2 -2
- package/dist/skills/ultimate-browsing/engine/__main__.py +9 -6
- package/dist/skills/ultimate-browsing/engine/summary.py +1 -1
- package/dist/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/dist/skills/ultimate-browsing/scripts/extract_cookies.py +4 -2
- package/dist/skills/ulw-research/AGENTS.md +8 -4
- package/dist/skills/ulw-research/SKILL.md +7 -316
- package/dist/skills/ulw-research/references/deliverable-phase.md +23 -21
- package/dist/skills/ulw-research/references/fact-ledger-grammar.md +7 -3
- package/dist/skills/ulw-research/references/fact-ledger.md +42 -8
- package/dist/skills/ulw-research/references/fidelity-claim-kinds.md +1 -1
- package/dist/skills/ulw-research/references/markdown-blocks.md +12 -0
- package/dist/skills/ulw-research/references/report-gates.md +12 -5
- package/dist/skills/ulw-research/references/research-collection.md +195 -0
- package/dist/skills/ulw-research/references/research-delivery.md +123 -0
- package/dist/skills/ulw-research/scripts/claim-kinds.mjs +33 -5
- package/dist/skills/ulw-research/scripts/claim-kinds.test.ts +37 -2
- package/dist/skills/ulw-research/scripts/claim-prefix.test.ts +76 -0
- package/dist/skills/ulw-research/scripts/contracts-validation.test.ts +83 -0
- package/dist/skills/ulw-research/scripts/contracts.mjs +13 -4
- package/dist/skills/ulw-research/scripts/contracts.test.ts +6 -110
- package/dist/skills/ulw-research/scripts/conversion-altered.test.ts +154 -0
- package/dist/skills/ulw-research/scripts/conversion-originals.test.ts +297 -0
- package/dist/skills/ulw-research/scripts/conversion-probe-classes.test.ts +361 -0
- package/dist/skills/ulw-research/scripts/conversion-probe.mjs +229 -0
- package/dist/skills/ulw-research/scripts/conversion-probe.test.ts +218 -0
- package/dist/skills/ulw-research/scripts/copy-returns-polish.test.ts +4 -3
- package/dist/skills/ulw-research/scripts/css-hiding.mjs +158 -0
- package/dist/skills/ulw-research/scripts/css-lite.mjs +4 -2
- package/dist/skills/ulw-research/scripts/delivery-barrier-meaning.test.ts +186 -0
- package/dist/skills/ulw-research/scripts/delivery-barrier.test.ts +40 -87
- package/dist/skills/ulw-research/scripts/entities.mjs +13 -4
- package/dist/skills/ulw-research/scripts/fact-commands-fill.mjs +11 -1
- package/dist/skills/ulw-research/scripts/fact-commands-meaning.mjs +13 -9
- package/dist/skills/ulw-research/scripts/fact-commands-polish.mjs +40 -18
- package/dist/skills/ulw-research/scripts/fact-commands-verify.mjs +25 -8
- package/dist/skills/ulw-research/scripts/fact-commands.mjs +35 -16
- package/dist/skills/ulw-research/scripts/fact-derive-2.test.ts +149 -0
- package/dist/skills/ulw-research/scripts/fact-derive.mjs +7 -2
- package/dist/skills/ulw-research/scripts/fact-derive.test.ts +7 -192
- package/dist/skills/ulw-research/scripts/fact-fill.mjs +6 -4
- package/dist/skills/ulw-research/scripts/fact-ledger-kinds.mjs +6 -7
- package/dist/skills/ulw-research/scripts/fact-ledger-kinds.test.ts +2 -1
- package/dist/skills/ulw-research/scripts/fact-ledger-legacy.test.ts +2 -1
- package/dist/skills/ulw-research/scripts/fact-locate.mjs +15 -9
- package/dist/skills/ulw-research/scripts/fact-unit-dimensions-2.test.ts +149 -0
- package/dist/skills/ulw-research/scripts/fact-unit-dimensions.test.ts +4 -168
- package/dist/skills/ulw-research/scripts/fact-unit-rules.test.ts +3 -229
- package/dist/skills/ulw-research/scripts/fidelity-claims.mjs +4 -3
- package/dist/skills/ulw-research/scripts/fidelity-csv.mjs +32 -0
- package/dist/skills/ulw-research/scripts/fidelity-lexicon.mjs +1 -1
- package/dist/skills/ulw-research/scripts/fidelity-originals.mjs +161 -0
- package/dist/skills/ulw-research/scripts/fidelity-policy.mjs +4 -4
- package/dist/skills/ulw-research/scripts/fidelity-records.mjs +81 -14
- package/dist/skills/ulw-research/scripts/fidelity-snapshot-readability.mjs +49 -0
- package/dist/skills/ulw-research/scripts/fidelity-sources.mjs +76 -0
- package/dist/skills/ulw-research/scripts/fidelity-trace.mjs +25 -11
- package/dist/skills/ulw-research/scripts/fidelity-value-unit.mjs +202 -0
- package/dist/skills/ulw-research/scripts/fidelity-values.mjs +40 -39
- package/dist/skills/ulw-research/scripts/fidelity-values.test.ts +8 -29
- package/dist/skills/ulw-research/scripts/gates-fidelity.mjs +8 -6
- package/dist/skills/ulw-research/scripts/gates-static-headings.test.ts +17 -0
- package/dist/skills/ulw-research/scripts/gates-static.mjs +10 -1
- package/dist/skills/ulw-research/scripts/html-lite.mjs +6 -2
- package/dist/skills/ulw-research/scripts/html-markup.mjs +2 -2
- package/dist/skills/ulw-research/scripts/html-text-map.mjs +140 -0
- package/dist/skills/ulw-research/scripts/html-text-map.test.ts +148 -0
- package/dist/skills/ulw-research/scripts/markdown-closers.mjs +126 -0
- package/dist/skills/ulw-research/scripts/md-lite-boundaries.test.ts +46 -0
- package/dist/skills/ulw-research/scripts/md-lite.mjs +1 -1
- package/dist/skills/ulw-research/scripts/number-grammar.mjs +33 -0
- package/dist/skills/ulw-research/scripts/number-grammar.test.ts +36 -0
- package/dist/skills/ulw-research/scripts/numerals.mjs +18 -7
- package/dist/skills/ulw-research/scripts/numerals.test.ts +3 -0
- package/dist/skills/ulw-research/scripts/outcome-start.mjs +66 -0
- package/dist/skills/ulw-research/scripts/outcome-start.test.ts +109 -0
- package/dist/skills/ulw-research/scripts/outcome.mjs +11 -22
- package/dist/skills/ulw-research/scripts/page-source-locator.test.ts +187 -0
- package/dist/skills/ulw-research/scripts/placeholder.mjs +18 -6
- package/dist/skills/ulw-research/scripts/polish-apply.mjs +3 -2
- package/dist/skills/ulw-research/scripts/polish-markup.test.ts +15 -1
- package/dist/skills/ulw-research/scripts/polish-partial.test.ts +42 -0
- package/dist/skills/ulw-research/scripts/raw-decode.mjs +110 -0
- package/dist/skills/ulw-research/scripts/raw-locator.mjs +47 -0
- package/dist/skills/ulw-research/scripts/raw-snapshot.test.ts +139 -0
- package/dist/skills/ulw-research/scripts/report-tools-2.test.ts +233 -0
- package/dist/skills/ulw-research/scripts/report-tools-3.test.ts +141 -0
- package/dist/skills/ulw-research/scripts/report-tools-4.test.ts +135 -0
- package/dist/skills/ulw-research/scripts/report-tools-5.test.ts +231 -0
- package/dist/skills/ulw-research/scripts/report-tools-commands.mjs +1 -1
- package/dist/skills/ulw-research/scripts/report-tools.mjs +7 -1
- package/dist/skills/ulw-research/scripts/report-tools.test.ts +5 -800
- package/dist/skills/ulw-research/scripts/snapshot-readability.test.ts +116 -0
- package/dist/skills/ulw-research/scripts/source-commands.mjs +79 -26
- package/dist/skills/ulw-research/scripts/source-integrity.test.ts +243 -0
- package/dist/skills/ulw-research/scripts/source-refresh.mjs +82 -0
- package/dist/skills/ulw-research/scripts/source-snapshot.mjs +73 -69
- package/dist/skills/ulw-research/scripts/source-snapshot.test.ts +7 -4
- package/dist/skills/ulw-research/scripts/source-view.mjs +89 -0
- package/dist/skills/ulw-research/scripts/sources-citation.mjs +203 -0
- package/dist/skills/ulw-research/scripts/sources-citation.test.ts +236 -0
- package/dist/skills/ulw-research/scripts/tests/contracts-support.ts +147 -0
- package/dist/skills/ulw-research/scripts/tests/delivery-barrier-session.ts +59 -0
- package/dist/skills/ulw-research/scripts/tests/derive-clock.ts +4 -0
- package/dist/skills/ulw-research/scripts/tests/fact-derive-support.ts +65 -0
- package/dist/skills/ulw-research/scripts/tests/fact-unit-dimensions-support.ts +41 -0
- package/dist/skills/ulw-research/scripts/tests/fact-unit-rules-support.ts +241 -0
- package/dist/skills/ulw-research/scripts/tests/fidelity-values-support.ts +30 -0
- package/dist/skills/ulw-research/scripts/tests/fixtures/conversion-probe.html +14 -0
- package/dist/skills/ulw-research/scripts/tests/fixtures/sources-shapes.html +20 -0
- package/dist/skills/ulw-research/scripts/tests/numeral-classes.ts +196 -0
- package/dist/skills/ulw-research/scripts/tests/report-tools-support.ts +182 -0
- package/dist/skills/ulw-research/scripts/tests/value-mode-support.ts +48 -0
- package/dist/skills/ulw-research/scripts/units.mjs +14 -3
- package/dist/skills/ulw-research/scripts/units.test.ts +10 -0
- package/dist/skills/ulw-research/scripts/value-mode-unit-classes.test.ts +255 -0
- package/dist/skills/ulw-research/scripts/value-mode-unit.test.ts +179 -0
- package/dist/skills/ulw-research/scripts/value-rules-cli.test.ts +157 -0
- package/dist/skills/ulw-research/scripts/value-rules-followups.test.ts +72 -0
- package/dist/skills/ulw-research/scripts/value-rules-priority.test.ts +80 -0
- package/dist/tools/delegate-task/executor-types.d.ts +1 -0
- package/dist/tools/delegate-task/sync-session-existence.d.ts +4 -0
- package/dist/tools/delegate-task/types.d.ts +1 -0
- package/dist/tools/skill/description-formatter.d.ts +2 -1
- package/dist/tools/skill/types.d.ts +6 -0
- package/dist/tui.js +131 -33
- package/package.json +18 -15
- package/packages/git-bash-mcp/package.json +1 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/README.md +1 -1
- 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/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- 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/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-contribute-bug-fix/SKILL.md +51 -55
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-report-bug/SKILL.md +7 -7
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-report-bug/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +2 -2
- package/packages/omo-codex/plugin/components/telemetry/README.md +2 -2
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +52 -15
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +52 -19
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +2 -9
- package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -13
- package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +0 -2
- package/packages/omo-codex/plugin/components/telemetry/test/codex-hook-diagnostics.test.ts +0 -3
- package/packages/omo-codex/plugin/components/telemetry/test/codex-hook.test.ts +3 -8
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +3 -0
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +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 +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- 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 +16 -16
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/shared/package.json +1 -1
- package/packages/omo-codex/plugin/skills/ast-grep/README.md +1 -1
- package/packages/omo-codex/plugin/skills/ast-grep/install.ps1 +5 -3
- package/packages/omo-codex/plugin/skills/ast-grep/install.sh +4 -5
- package/packages/omo-codex/plugin/skills/ast-grep/references/install.md +2 -2
- package/packages/omo-codex/plugin/skills/ast-grep/scripts/ast_grep_helper.py +13 -3
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +5 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +11 -11
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +2 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/codex.md +4 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/find-agent-sessions.py +6 -3
- package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +34 -12
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +2 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/component-catalogs.md +14 -10
- package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +19 -6
- package/packages/omo-codex/plugin/skills/frontend/references/design/grounding.md +29 -0
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/design_system.py +2 -0
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/search.py +2 -0
- package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/SKILL.md +51 -55
- package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/lcx-report-bug/SKILL.md +7 -7
- package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +5 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +2 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/__main__.py +9 -6
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/summary.py +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/extract_cookies.py +4 -2
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +3 -0
- package/packages/omo-codex/plugin/skills/ulw-research/AGENTS.md +8 -4
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +7 -316
- package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +23 -21
- package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger-grammar.md +7 -3
- package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger.md +42 -8
- package/packages/omo-codex/plugin/skills/ulw-research/references/fidelity-claim-kinds.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/references/markdown-blocks.md +12 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/report-gates.md +12 -5
- package/packages/omo-codex/plugin/skills/ulw-research/references/research-collection.md +195 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/research-delivery.md +123 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/claim-kinds.mjs +33 -5
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/contracts.mjs +13 -4
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/conversion-probe.mjs +229 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/css-hiding.mjs +158 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/css-lite.mjs +4 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/entities.mjs +13 -4
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-fill.mjs +11 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-meaning.mjs +13 -9
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-polish.mjs +40 -18
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-verify.mjs +25 -8
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands.mjs +35 -16
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-derive.mjs +7 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-fill.mjs +6 -4
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger-kinds.mjs +6 -7
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-locate.mjs +15 -9
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-claims.mjs +4 -3
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-csv.mjs +32 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-lexicon.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-originals.mjs +161 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-policy.mjs +4 -4
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-records.mjs +81 -14
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-snapshot-readability.mjs +49 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-sources.mjs +76 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-trace.mjs +25 -11
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-value-unit.mjs +202 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-values.mjs +40 -39
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-fidelity.mjs +8 -6
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-static.mjs +10 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-lite.mjs +6 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-markup.mjs +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-text-map.mjs +140 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/markdown-closers.mjs +126 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/md-lite.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/number-grammar.mjs +33 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/numerals.mjs +18 -7
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/outcome-start.mjs +66 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/outcome.mjs +11 -22
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/placeholder.mjs +18 -6
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-apply.mjs +3 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/raw-decode.mjs +110 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/raw-locator.mjs +47 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools-commands.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools.mjs +7 -1
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-commands.mjs +79 -26
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-refresh.mjs +82 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-snapshot.mjs +73 -69
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-view.mjs +89 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/sources-citation.mjs +203 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/units.mjs +14 -3
- package/packages/omo-codex/plugin/test/payload-equivalence.test.mjs +6 -4
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +4 -3
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +338 -237
- package/packages/prompts-core/prompts/ultrawork/codex.md +3 -0
- package/packages/shared-skills/skill-source-filter.mjs +6 -2
- package/packages/shared-skills/skills/ast-grep/README.md +1 -1
- package/packages/shared-skills/skills/ast-grep/install.ps1 +5 -3
- package/packages/shared-skills/skills/ast-grep/install.sh +4 -5
- package/packages/shared-skills/skills/ast-grep/references/install.md +2 -2
- package/packages/shared-skills/skills/ast-grep/scripts/ast_grep_helper.py +13 -3
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +5 -4
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +11 -11
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +2 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/codex.md +4 -4
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/find-agent-sessions.py +6 -3
- package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +1 -1
- package/packages/shared-skills/skills/frontend/SKILL.md +34 -12
- package/packages/shared-skills/skills/frontend/references/design/README.md +2 -2
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +2 -1
- package/packages/shared-skills/skills/frontend/references/design/component-catalogs.md +14 -10
- package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +19 -6
- package/packages/shared-skills/skills/frontend/references/design/grounding.md +29 -0
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/design_system.py +2 -0
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/search.py +2 -0
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +5 -4
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +2 -2
- package/packages/shared-skills/skills/ultimate-browsing/engine/__main__.py +9 -6
- package/packages/shared-skills/skills/ultimate-browsing/engine/summary.py +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/packages/shared-skills/skills/ultimate-browsing/scripts/extract_cookies.py +4 -2
- package/packages/shared-skills/skills/ulw-research/AGENTS.md +8 -4
- package/packages/shared-skills/skills/ulw-research/SKILL.md +7 -316
- package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +23 -21
- package/packages/shared-skills/skills/ulw-research/references/fact-ledger-grammar.md +7 -3
- package/packages/shared-skills/skills/ulw-research/references/fact-ledger.md +42 -8
- package/packages/shared-skills/skills/ulw-research/references/fidelity-claim-kinds.md +1 -1
- package/packages/shared-skills/skills/ulw-research/references/markdown-blocks.md +12 -0
- package/packages/shared-skills/skills/ulw-research/references/report-gates.md +12 -5
- package/packages/shared-skills/skills/ulw-research/references/research-collection.md +195 -0
- package/packages/shared-skills/skills/ulw-research/references/research-delivery.md +123 -0
- package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.mjs +33 -5
- package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.test.ts +37 -2
- package/packages/shared-skills/skills/ulw-research/scripts/claim-prefix.test.ts +76 -0
- package/packages/shared-skills/skills/ulw-research/scripts/contracts-validation.test.ts +83 -0
- package/packages/shared-skills/skills/ulw-research/scripts/contracts.mjs +13 -4
- package/packages/shared-skills/skills/ulw-research/scripts/contracts.test.ts +6 -110
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-altered.test.ts +154 -0
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-originals.test.ts +297 -0
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-probe-classes.test.ts +361 -0
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-probe.mjs +229 -0
- package/packages/shared-skills/skills/ulw-research/scripts/conversion-probe.test.ts +218 -0
- package/packages/shared-skills/skills/ulw-research/scripts/copy-returns-polish.test.ts +4 -3
- package/packages/shared-skills/skills/ulw-research/scripts/css-hiding.mjs +158 -0
- package/packages/shared-skills/skills/ulw-research/scripts/css-lite.mjs +4 -2
- package/packages/shared-skills/skills/ulw-research/scripts/delivery-barrier-meaning.test.ts +186 -0
- package/packages/shared-skills/skills/ulw-research/scripts/delivery-barrier.test.ts +40 -87
- package/packages/shared-skills/skills/ulw-research/scripts/entities.mjs +13 -4
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-fill.mjs +11 -1
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-meaning.mjs +13 -9
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-polish.mjs +40 -18
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-verify.mjs +25 -8
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands.mjs +35 -16
- package/packages/shared-skills/skills/ulw-research/scripts/fact-derive-2.test.ts +149 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.mjs +7 -2
- package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.test.ts +7 -192
- package/packages/shared-skills/skills/ulw-research/scripts/fact-fill.mjs +6 -4
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.mjs +6 -7
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.test.ts +2 -1
- package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-legacy.test.ts +2 -1
- package/packages/shared-skills/skills/ulw-research/scripts/fact-locate.mjs +15 -9
- package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-dimensions-2.test.ts +149 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-dimensions.test.ts +4 -168
- package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-rules.test.ts +3 -229
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-claims.mjs +4 -3
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-csv.mjs +32 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-lexicon.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-originals.mjs +161 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-policy.mjs +4 -4
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-records.mjs +81 -14
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-snapshot-readability.mjs +49 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-sources.mjs +76 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-trace.mjs +25 -11
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-value-unit.mjs +202 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.mjs +40 -39
- package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.test.ts +8 -29
- package/packages/shared-skills/skills/ulw-research/scripts/gates-fidelity.mjs +8 -6
- package/packages/shared-skills/skills/ulw-research/scripts/gates-static-headings.test.ts +17 -0
- package/packages/shared-skills/skills/ulw-research/scripts/gates-static.mjs +10 -1
- package/packages/shared-skills/skills/ulw-research/scripts/html-lite.mjs +6 -2
- package/packages/shared-skills/skills/ulw-research/scripts/html-markup.mjs +2 -2
- package/packages/shared-skills/skills/ulw-research/scripts/html-text-map.mjs +140 -0
- package/packages/shared-skills/skills/ulw-research/scripts/html-text-map.test.ts +148 -0
- package/packages/shared-skills/skills/ulw-research/scripts/markdown-closers.mjs +126 -0
- package/packages/shared-skills/skills/ulw-research/scripts/md-lite-boundaries.test.ts +46 -0
- package/packages/shared-skills/skills/ulw-research/scripts/md-lite.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/scripts/number-grammar.mjs +33 -0
- package/packages/shared-skills/skills/ulw-research/scripts/number-grammar.test.ts +36 -0
- package/packages/shared-skills/skills/ulw-research/scripts/numerals.mjs +18 -7
- package/packages/shared-skills/skills/ulw-research/scripts/numerals.test.ts +3 -0
- package/packages/shared-skills/skills/ulw-research/scripts/outcome-start.mjs +66 -0
- package/packages/shared-skills/skills/ulw-research/scripts/outcome-start.test.ts +109 -0
- package/packages/shared-skills/skills/ulw-research/scripts/outcome.mjs +11 -22
- package/packages/shared-skills/skills/ulw-research/scripts/page-source-locator.test.ts +187 -0
- package/packages/shared-skills/skills/ulw-research/scripts/placeholder.mjs +18 -6
- package/packages/shared-skills/skills/ulw-research/scripts/polish-apply.mjs +3 -2
- package/packages/shared-skills/skills/ulw-research/scripts/polish-markup.test.ts +15 -1
- package/packages/shared-skills/skills/ulw-research/scripts/polish-partial.test.ts +42 -0
- package/packages/shared-skills/skills/ulw-research/scripts/raw-decode.mjs +110 -0
- package/packages/shared-skills/skills/ulw-research/scripts/raw-locator.mjs +47 -0
- package/packages/shared-skills/skills/ulw-research/scripts/raw-snapshot.test.ts +139 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-2.test.ts +233 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-3.test.ts +141 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-4.test.ts +135 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-5.test.ts +231 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools-commands.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools.mjs +7 -1
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools.test.ts +5 -800
- package/packages/shared-skills/skills/ulw-research/scripts/snapshot-readability.test.ts +116 -0
- package/packages/shared-skills/skills/ulw-research/scripts/source-commands.mjs +79 -26
- package/packages/shared-skills/skills/ulw-research/scripts/source-integrity.test.ts +243 -0
- package/packages/shared-skills/skills/ulw-research/scripts/source-refresh.mjs +82 -0
- package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.mjs +73 -69
- package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.test.ts +7 -4
- package/packages/shared-skills/skills/ulw-research/scripts/source-view.mjs +89 -0
- package/packages/shared-skills/skills/ulw-research/scripts/sources-citation.mjs +203 -0
- package/packages/shared-skills/skills/ulw-research/scripts/sources-citation.test.ts +236 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/contracts-support.ts +147 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/delivery-barrier-session.ts +59 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/derive-clock.ts +4 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fact-derive-support.ts +65 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fact-unit-dimensions-support.ts +41 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fact-unit-rules-support.ts +241 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fidelity-values-support.ts +30 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/conversion-probe.html +14 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/sources-shapes.html +20 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/numeral-classes.ts +196 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/report-tools-support.ts +182 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/value-mode-support.ts +48 -0
- package/packages/shared-skills/skills/ulw-research/scripts/units.mjs +14 -3
- package/packages/shared-skills/skills/ulw-research/scripts/units.test.ts +10 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-mode-unit-classes.test.ts +255 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-mode-unit.test.ts +179 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-rules-cli.test.ts +157 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-rules-followups.test.ts +72 -0
- package/packages/shared-skills/skills/ulw-research/scripts/value-rules-priority.test.ts +80 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +0 -7
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +0 -19
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +0 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +0 -1128
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_fetch_chain.py +0 -77
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +0 -86
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +0 -279
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate.py +0 -252
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +0 -78
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
// placeholder.mjs - the fact pointer grammar of the fill step and its render helpers.
|
|
2
2
|
// Value pointers: {{F12:label}}, {{F12:label:value}}, {{F12:label:unit}}, {{F12:label:q}}.
|
|
3
|
+
// Claim prefixes from CLAIM_KINDS (V, D, A) precede any one pointer: {{D:F12:label:value}}, {{V:Q7:label:lead=18}}.
|
|
3
4
|
// Quote pointers: {{Q7:label}}, {{Q7:label:lead=18}}, {{Q7:label:from="x":to="y"}} (anchors are
|
|
4
5
|
// JSON strings, so they may hold a colon or an escaped quote). Labels are compared exactly by the
|
|
5
6
|
// caller; this module never guesses an id. Pure functions; node: builtins only.
|
|
6
7
|
|
|
7
8
|
import { parseNumeral } from "./numerals.mjs"
|
|
9
|
+
import { CLAIM_KINDS } from "./claim-kinds.mjs"
|
|
8
10
|
|
|
9
11
|
export const ELLIPSIS = "\u2026"
|
|
10
12
|
|
|
11
|
-
const ID = /^([FQ])\d
|
|
13
|
+
const ID = /^([FQ])[1-9]\d*$/
|
|
12
14
|
const LABEL = /^[^\s:{}"]+$/
|
|
13
15
|
const VALUE_MODES = new Set(["value", "unit", "q"])
|
|
14
16
|
const LEAD = /^lead=([1-9]\d*)$/
|
|
@@ -45,6 +47,12 @@ function parseAnchors(tail) {
|
|
|
45
47
|
export function parsePlaceholder(token) {
|
|
46
48
|
if (!token.startsWith("{{") || !token.endsWith("}}")) return { error: "a placeholder is {{ID:label...}}" }
|
|
47
49
|
const body = token.slice(2, -2)
|
|
50
|
+
const marked = Object.entries(CLAIM_KINDS).find(([, entry]) => entry.prefix && body.startsWith(`${entry.prefix}:`))
|
|
51
|
+
if (marked) {
|
|
52
|
+
const [claimKind, entry] = marked
|
|
53
|
+
const parsed = parsePlaceholder(`{{${body.slice(entry.prefix.length + 1)}}}`)
|
|
54
|
+
return parsed.error || parsed.claimKind ? { error: "a claim prefix must precede one fact or quote pointer" } : { ...parsed, claimKind }
|
|
55
|
+
}
|
|
48
56
|
const colon = body.indexOf(":")
|
|
49
57
|
const id = colon === -1 ? body : body.slice(0, colon)
|
|
50
58
|
const idMatch = ID.exec(id)
|
|
@@ -130,7 +138,7 @@ export function lead(quote, n) {
|
|
|
130
138
|
/** The value and unit parts of a row's raw text ("4.2 eok won" -> value "4.2 eok", unit "won"). */
|
|
131
139
|
export function valueParts(row) {
|
|
132
140
|
const unitText = parseNumeral(row.raw)?.unitRaw ?? row.unit
|
|
133
|
-
const valueText = unitText && row.raw.endsWith(unitText) ? row.raw.slice(0, -unitText.length).trimEnd() :
|
|
141
|
+
const valueText = unitText && row.raw.endsWith(unitText) ? row.raw.slice(0, -unitText.length).trimEnd() : row.raw
|
|
134
142
|
return { valueText, unitText: unitText ?? "" }
|
|
135
143
|
}
|
|
136
144
|
|
|
@@ -156,15 +164,19 @@ export function escapeHtml(text) {
|
|
|
156
164
|
/** The elements the renderers below emit as fact spans; recognizers build their patterns from this. */
|
|
157
165
|
export const FACT_ELEMENT_TAGS = Object.freeze(["data", "q", "blockquote"])
|
|
158
166
|
|
|
159
|
-
|
|
167
|
+
/** `mode` "value" marks a bare value whose unit verify checks beside it; `claimKind` is the claim mark. */
|
|
168
|
+
export function renderValueHtml(row, text, { mode = "full", claimKind = null } = {}) {
|
|
160
169
|
const unit = row.unit === null ? "" : ` data-unit="${escapeHtml(row.unit)}"`
|
|
161
|
-
|
|
170
|
+
const marker = mode === "value" ? ' data-fact-mode="value"' : ""
|
|
171
|
+
const mark = claimKind === null ? "" : ` data-claim-kind="${escapeHtml(claimKind)}"`
|
|
172
|
+
return `<data class="fact" value="${escapeHtml(row.value)}" data-fact="${row.fact_id}"${unit}${marker}${mark} data-lineage="${LINEAGE[row.kind]}">${escapeHtml(text)}</data>`
|
|
162
173
|
}
|
|
163
174
|
|
|
164
|
-
export function renderQuote(row, selector, text, format) {
|
|
175
|
+
export function renderQuote(row, selector, text, format, claimKind = null) {
|
|
165
176
|
const marker = `[${row.source_id}]`
|
|
166
177
|
if (format === "md") return `"${text}" ${marker}`
|
|
167
|
-
|
|
178
|
+
const mark = claimKind === null ? "" : ` data-claim-kind="${escapeHtml(claimKind)}"`
|
|
179
|
+
return `<q data-fact="${row.fact_id}"${mark} data-quote-sel="${escapeHtml(selector)}">${escapeHtml(text)}</q> ${marker}`
|
|
168
180
|
}
|
|
169
181
|
|
|
170
182
|
const RENDERED_MD_QUOTE = /^"([\s\S]*)" (\[S\d+\])$/u
|
|
@@ -54,9 +54,10 @@ export const POLISH_REFERENCE_REASON = "edit touches a character reference: rout
|
|
|
54
54
|
/** True when [start, end) overlaps a character reference of html or starts inside one. */
|
|
55
55
|
export function touchesReference(html, start, end) {
|
|
56
56
|
for (const match of String(html).matchAll(CHARACTER_REFERENCE)) {
|
|
57
|
-
|
|
57
|
+
const stop = match.index + match[0].length
|
|
58
|
+
if (match.index < end && (stop > start || (stop === start && !match[0].endsWith(";")))) return true
|
|
58
59
|
}
|
|
59
|
-
return
|
|
60
|
+
return false
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
const escape = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// raw-decode.mjs - decode a source's raw bytes in their declared encoding and keep a byte map.
|
|
2
|
+
//
|
|
3
|
+
// decodeRaw returns { text, encoding, bytes } where bytes[i] is the raw byte offset at which UTF-16
|
|
4
|
+
// unit i of `text` starts and bytes[text.length] === raw.length, so any text range maps back to the
|
|
5
|
+
// bytes the source actually holds (never to a lossy UTF-8 re-encode). The encoding comes from a
|
|
6
|
+
// BOM, then the caller's declared charset (HTTP header or meta.json), then an HTML <meta> charset,
|
|
7
|
+
// and defaults to UTF-8. node: builtins only (TextDecoder).
|
|
8
|
+
|
|
9
|
+
const SNIFF_BYTES = 1024
|
|
10
|
+
const META_CHARSET = /<meta\b[^>]*?charset\s*=\s*["']?\s*([\w.:-]+)/i
|
|
11
|
+
|
|
12
|
+
/** The WHATWG encoding name for a label, or null when the runtime does not know it. */
|
|
13
|
+
export function encodingOf(label) {
|
|
14
|
+
if (typeof label !== "string" || label.trim() === "") return null
|
|
15
|
+
try {
|
|
16
|
+
return new TextDecoder(label.trim()).encoding
|
|
17
|
+
} catch {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** charset=... from a Content-Type header value, as an encoding name, or null. */
|
|
23
|
+
export function headerCharset(contentType) {
|
|
24
|
+
const match = /charset\s*=\s*["']?([\w.:-]+)/i.exec(String(contentType ?? ""))
|
|
25
|
+
return match ? encodingOf(match[1]) : null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function bomOf(raw) {
|
|
29
|
+
if (raw[0] === 0xef && raw[1] === 0xbb && raw[2] === 0xbf) return { encoding: "utf-8", skip: 3 }
|
|
30
|
+
if (raw[0] === 0xff && raw[1] === 0xfe) return { encoding: "utf-16le", skip: 2 }
|
|
31
|
+
if (raw[0] === 0xfe && raw[1] === 0xff) return { encoding: "utf-16be", skip: 2 }
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** BOM, then the declared charset, then (for markup) a <meta> charset in the first 1 KiB, then UTF-8. */
|
|
36
|
+
export function detectEncoding(raw, declared = null, markup = false) {
|
|
37
|
+
const bom = bomOf(raw)
|
|
38
|
+
if (bom) return bom.encoding
|
|
39
|
+
const given = encodingOf(declared)
|
|
40
|
+
if (given) return given
|
|
41
|
+
if (markup) {
|
|
42
|
+
const sniffed = META_CHARSET.exec(Buffer.from(raw.subarray(0, SNIFF_BYTES)).toString("latin1"))
|
|
43
|
+
const named = sniffed ? encodingOf(sniffed[1]) : null
|
|
44
|
+
// A page that is already decoded to UTF-16 cannot declare a UTF-16 charset in ASCII bytes.
|
|
45
|
+
if (named && !named.startsWith("utf-16")) return named
|
|
46
|
+
}
|
|
47
|
+
return "utf-8"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function utf8Map(text, bytes, from) {
|
|
51
|
+
let at = from
|
|
52
|
+
for (let i = 0; i < text.length; i++) {
|
|
53
|
+
bytes[i] = at
|
|
54
|
+
const code = text.charCodeAt(i)
|
|
55
|
+
if (code >= 0xd800 && code <= 0xdbff && i + 1 < text.length) {
|
|
56
|
+
bytes[++i] = at
|
|
57
|
+
at += 4
|
|
58
|
+
} else at += code < 0x80 ? 1 : code < 0x800 ? 2 : 3
|
|
59
|
+
}
|
|
60
|
+
return at
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Byte-at-a-time streaming decode: correct for any encoding, used when no shortcut applies. */
|
|
64
|
+
function streamMap(raw, encoding, from) {
|
|
65
|
+
const decoder = new TextDecoder(encoding)
|
|
66
|
+
const units = []
|
|
67
|
+
const starts = []
|
|
68
|
+
let pending = from
|
|
69
|
+
for (let i = from; i < raw.length; i++) {
|
|
70
|
+
const out = decoder.decode(raw.subarray(i, i + 1), { stream: true })
|
|
71
|
+
if (out.length === 0) continue
|
|
72
|
+
// A replacement for an earlier broken sequence can arrive with this byte's own character.
|
|
73
|
+
const own = out.length > 1 && raw[i] < 0x80 ? 1 : 0
|
|
74
|
+
for (let k = 0; k < out.length; k++) starts.push(k >= out.length - own ? i : pending)
|
|
75
|
+
units.push(out)
|
|
76
|
+
pending = i + 1
|
|
77
|
+
}
|
|
78
|
+
const tail = decoder.decode()
|
|
79
|
+
for (let k = 0; k < tail.length; k++) starts.push(pending)
|
|
80
|
+
units.push(tail)
|
|
81
|
+
return { text: units.join(""), starts }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Decode raw bytes; bytes is an Int32Array of length text.length + 1 (see the file comment). */
|
|
85
|
+
export function decodeRaw(raw, declared = null, markup = false) {
|
|
86
|
+
const buffer = Buffer.from(raw)
|
|
87
|
+
const encoding = detectEncoding(buffer, declared, markup)
|
|
88
|
+
const skip = bomOf(buffer)?.encoding === encoding ? bomOf(buffer).skip : 0
|
|
89
|
+
if (encoding === "utf-8") {
|
|
90
|
+
try {
|
|
91
|
+
const text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(buffer.subarray(skip))
|
|
92
|
+
const bytes = new Int32Array(text.length + 1)
|
|
93
|
+
bytes[text.length] = utf8Map(text, bytes, skip)
|
|
94
|
+
return { text, encoding, bytes }
|
|
95
|
+
} catch {
|
|
96
|
+
// invalid UTF-8: fall through to the streaming map, which counts each broken byte once
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (encoding !== "utf-8" && !encoding.startsWith("utf-16")) {
|
|
100
|
+
const text = new TextDecoder(encoding).decode(buffer.subarray(skip))
|
|
101
|
+
if (text.length === buffer.length - skip) {
|
|
102
|
+
const bytes = new Int32Array(text.length + 1)
|
|
103
|
+
for (let i = 0; i <= text.length; i++) bytes[i] = skip + i
|
|
104
|
+
return { text, encoding, bytes }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const { text, starts } = streamMap(buffer, encoding, skip)
|
|
108
|
+
const bytes = Int32Array.from([...starts, buffer.length])
|
|
109
|
+
return { text, encoding, bytes }
|
|
110
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Byte locators over a source view (source-view.mjs) and exact, context-bound re-anchoring.
|
|
2
|
+
// Matching always happens on the view's text (text nodes of a page, never markup); only the
|
|
3
|
+
// stored offsets are bytes of the view's artifact. value_span remains quote-relative text.
|
|
4
|
+
|
|
5
|
+
const chars = (text) => [...text]
|
|
6
|
+
|
|
7
|
+
/** Context is copied before normalization, around the value (or the whole quote for Q rows). */
|
|
8
|
+
export function quoteContext(text, start, end) {
|
|
9
|
+
return { prefix: chars(text.slice(0, start)).slice(-32).join(""), suffix: chars(text.slice(end)).slice(0, 32).join("") }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Convert a text-space locator from fact-locate.mjs into artifact byte offsets. */
|
|
13
|
+
export function rawLocated(view, found) {
|
|
14
|
+
if (found.error) return found
|
|
15
|
+
const { char_start: start, char_end: end } = found.locator
|
|
16
|
+
const from = start + (found.value_span?.[0] ?? 0)
|
|
17
|
+
const to = found.value_span ? start + found.value_span[1] : end
|
|
18
|
+
const [byteStart, byteEnd] = view.byteSpan(start, end)
|
|
19
|
+
return {
|
|
20
|
+
...found,
|
|
21
|
+
context: quoteContext(view.text, from, to),
|
|
22
|
+
locator: { ...found.locator, artifact: view.artifact, unit: "bytes", char_start: byteStart, char_end: byteEnd },
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function contextMatches(text, row, start, end) {
|
|
27
|
+
if (!row.context) return false
|
|
28
|
+
const from = row.value_span ? start + row.value_span[0] : start
|
|
29
|
+
const to = row.value_span ? start + row.value_span[1] : end
|
|
30
|
+
const { prefix, suffix } = row.context
|
|
31
|
+
return from >= prefix.length && text.slice(from - prefix.length, from) === prefix && text.slice(to, to + suffix.length) === suffix
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The row's quote in the view: unchanged when an exact occurrence sits at the pinned byte range,
|
|
36
|
+
* else exactly one occurrence whose context matches (relocated), else null. Never rewrites the row.
|
|
37
|
+
*/
|
|
38
|
+
export function reanchor(view, row) {
|
|
39
|
+
const quote = String(row.quote ?? "")
|
|
40
|
+
if (quote === "" || !view.byteSpan) return null
|
|
41
|
+
const { char_start: start, char_end: end } = row.locator
|
|
42
|
+
const hits = []
|
|
43
|
+
for (let at = view.text.indexOf(quote); at !== -1; at = view.text.indexOf(quote, at + 1)) hits.push({ at, span: view.byteSpan(at, at + quote.length) })
|
|
44
|
+
if (hits.some(({ span }) => span[0] === start && span[1] === end)) return { start, end, relocated: false }
|
|
45
|
+
const matching = hits.filter(({ at }) => contextMatches(view.text, row, at, at + quote.length))
|
|
46
|
+
return matching.length === 1 ? { start: matching[0].span[0], end: matching[0].span[1], relocated: true } : null
|
|
47
|
+
}
|
|
@@ -133,7 +133,7 @@ export async function runOutcome(argv) {
|
|
|
133
133
|
switch (sub) {
|
|
134
134
|
case "init": {
|
|
135
135
|
const promised = args.required("promised").split(",").map((s) => s.trim()).filter(Boolean)
|
|
136
|
-
const manifest = outcome.initManifest({ sessionDir: sessionDirFrom(args.flags), promised, lane: args.flags.lane ?? null, now: nowFrom(args.flags) })
|
|
136
|
+
const manifest = outcome.initManifest({ sessionDir: sessionDirFrom(args.flags), promised, lane: args.flags.lane ?? null, now: nowFrom(args.flags), startedAt: args.flags["started-at"] })
|
|
137
137
|
outcome.writeManifest(file, manifest)
|
|
138
138
|
return { json: { command: "outcome init", path: file, deliverables: manifest.deliverables }, exitCode: 0 }
|
|
139
139
|
}
|
|
@@ -28,6 +28,8 @@ export const COMMANDS = Object.freeze([
|
|
|
28
28
|
"fact verify",
|
|
29
29
|
"fact derive",
|
|
30
30
|
"source snapshot",
|
|
31
|
+
"source refresh",
|
|
32
|
+
"source probe-conversion",
|
|
31
33
|
"claims index",
|
|
32
34
|
])
|
|
33
35
|
|
|
@@ -53,7 +55,11 @@ export async function run(argv) {
|
|
|
53
55
|
return (await import("./source-commands.mjs")).runClaims(rest)
|
|
54
56
|
case "--help":
|
|
55
57
|
case "help":
|
|
56
|
-
if (rest.includes("--json"))
|
|
58
|
+
if (rest.includes("--json")) {
|
|
59
|
+
const { SNAPSHOT_USAGE } = await import("./source-commands.mjs")
|
|
60
|
+
const { REFRESH_USAGE } = await import("./source-refresh.mjs")
|
|
61
|
+
return { json: { commands: COMMANDS, usage: { "source snapshot": SNAPSHOT_USAGE, "source refresh": REFRESH_USAGE } }, exitCode: 0 }
|
|
62
|
+
}
|
|
57
63
|
return { text: `report-tools <command>\n${COMMANDS.map((name) => ` ${name}`).join("\n")}`, exitCode: 0 }
|
|
58
64
|
default:
|
|
59
65
|
throw new CliError(`usage: report-tools <${COMMANDS.join(" | ")}> (run --help)`)
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
// source-commands.mjs - the `source snapshot` and `claims index` subcommands of
|
|
2
|
-
// A source dir is immutable: the same id with identical
|
|
3
|
-
// (exit 1, snapshot_exists), because ledger rows pin the old hash
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
1
|
+
// source-commands.mjs - the `source snapshot`, `source refresh` and `claims index` subcommands of
|
|
2
|
+
// report-tools. A source dir is immutable: the same id with identical bytes is a no-op, different
|
|
3
|
+
// bytes fail (exit 1, snapshot_exists), because ledger rows pin the old hash; `source refresh`
|
|
4
|
+
// (source-refresh.mjs) is the one explicit repin. `--replace` swaps in a corrected capture under the
|
|
5
|
+
// same id (the conversion_altered_number recovery) only while no active ledger row cites the id
|
|
6
|
+
// (exit 1, snapshot_pinned, listing them). `--url` fetches with plain fetch (30 s timeout,
|
|
7
|
+
// no browser) and records extractor tool:source-snapshot@1; `--html` imports a browser-lane page
|
|
8
|
+
// capture and `--raw` alone a saved file's bytes (extractor model). `--text` alone registers a converted-only source (no raw bytes:
|
|
9
|
+
// quotes only); `--raw <bytes> --text <extraction> --extractor NAME@VERSION` keeps the original
|
|
10
|
+
// bytes and declares the text their extraction. `--command` runs an argv without a shell and
|
|
7
11
|
// snapshots its stdout, with the argv, cwd, exit status, and output hashes in command.json.
|
|
8
12
|
// node: builtins and sibling imports only.
|
|
9
13
|
|
|
@@ -13,14 +17,18 @@ import { join, resolve } from "node:path"
|
|
|
13
17
|
|
|
14
18
|
import { indexClaims } from "./claims-index.mjs"
|
|
15
19
|
import { CliError, parseArgs, sha256Of, writeJsonAtomic } from "./cli-support.mjs"
|
|
20
|
+
import { runConversionProbe } from "./conversion-probe.mjs"
|
|
21
|
+
import { readLedger } from "./fact-ledger.mjs"
|
|
16
22
|
import { parseFidelityBlock } from "./fidelity-brief.mjs"
|
|
17
23
|
import { parseSourceFloor } from "./fidelity-policy.mjs"
|
|
24
|
+
import { encodingOf, headerCharset } from "./raw-decode.mjs"
|
|
18
25
|
import { writeSnapshot } from "./source-snapshot.mjs"
|
|
26
|
+
import { readSnapshot } from "./source-view.mjs"
|
|
19
27
|
|
|
20
28
|
const FETCH_TIMEOUT_MS = 30_000
|
|
21
29
|
const TOOL_EXTRACTOR = "tool:source-snapshot@1"
|
|
22
|
-
const SNAPSHOT_USAGE =
|
|
23
|
-
"usage: source snapshot --id S<n> (--url <u> | --html <file> | --
|
|
30
|
+
export const SNAPSHOT_USAGE =
|
|
31
|
+
"usage: source probe-conversion <raw-file> <converted-file> | source snapshot --id S<n> (--url <u> | --html <file> | --raw <file> [--text <file> --extractor NAME@VERSION] | --text <file> (converted-only) | --command '<argv json>' --cwd DIR) [--charset NAME] [--kind page|command|document|converted-only] [--provenance primary|secondary] [--revision R] [--replace] --session-dir D"
|
|
24
32
|
|
|
25
33
|
function readInput(path) {
|
|
26
34
|
try {
|
|
@@ -37,12 +45,15 @@ export function sessionDirOf(flags) {
|
|
|
37
45
|
return resolve(dir)
|
|
38
46
|
}
|
|
39
47
|
|
|
40
|
-
/** The snapshot
|
|
48
|
+
/** The snapshot as source-view.mjs reads it ({ meta, raw, sha256, drift, view }); unreadable is a usage error. */
|
|
41
49
|
export function snapshotOf(sessionDir, id) {
|
|
42
50
|
const dir = join(sessionDir, "sources", String(id))
|
|
43
51
|
if (!existsSync(join(dir, "meta.json"))) throw new CliError(`source ${id} has no snapshot; run source snapshot --id ${id} first`)
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
try {
|
|
53
|
+
return readSnapshot(dir)
|
|
54
|
+
} catch (error) {
|
|
55
|
+
throw new CliError(`source ${id}: ${error.message}`)
|
|
56
|
+
}
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
/**
|
|
@@ -72,10 +83,10 @@ async function fetchSource(url) {
|
|
|
72
83
|
const type = response.headers.get("content-type") ?? ""
|
|
73
84
|
if (/pdf/i.test(type)) {
|
|
74
85
|
await response.body?.cancel()
|
|
75
|
-
throw new CliError(`pdf response: ${url};
|
|
86
|
+
throw new CliError(`pdf response: ${url}; save the bytes and use --raw <file.pdf> --text <extracted.txt> --extractor NAME@VERSION`)
|
|
76
87
|
}
|
|
77
|
-
const
|
|
78
|
-
return /html|xml/i.test(type) || /^\s*</.test(
|
|
88
|
+
const raw = Buffer.from(await response.arrayBuffer())
|
|
89
|
+
return { url, raw, charset: headerCharset(type), markup: /html|xml/i.test(type) || /^\s*</.test(raw.subarray(0, 1024).toString("latin1")) }
|
|
79
90
|
}
|
|
80
91
|
|
|
81
92
|
function runCommand(argvJson, cwd) {
|
|
@@ -89,35 +100,76 @@ function runCommand(argvJson, cwd) {
|
|
|
89
100
|
throw new CliError("--command must be a non-empty JSON array of non-empty strings")
|
|
90
101
|
}
|
|
91
102
|
if (!cwd || cwd === true) throw new CliError("--command needs --cwd DIR")
|
|
92
|
-
const proc = spawnSync(argv[0], argv.slice(1), { cwd: resolve(cwd),
|
|
103
|
+
const proc = spawnSync(argv[0], argv.slice(1), { cwd: resolve(cwd), shell: false, maxBuffer: 64 * 1024 * 1024 })
|
|
93
104
|
if (proc.error) throw new CliError(`--command could not start: ${proc.error.message}`)
|
|
94
105
|
const receipt = { argv, cwd: resolve(cwd), exit_status: proc.status, stdout_sha256: sha256Of(proc.stdout), stderr_sha256: sha256Of(proc.stderr) }
|
|
95
|
-
return { path: `command:${argv.join(" ")}`,
|
|
106
|
+
return { path: `command:${argv.join(" ")}`, raw: proc.stdout, kind: "command", receipt }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function readBytes(path) {
|
|
110
|
+
try {
|
|
111
|
+
return readFileSync(path)
|
|
112
|
+
} catch (error) {
|
|
113
|
+
throw new CliError(`cannot read ${path}: ${error.code ?? error.message}`)
|
|
114
|
+
}
|
|
96
115
|
}
|
|
97
116
|
|
|
98
|
-
|
|
117
|
+
/** The snapshot input the flags describe; shared by `source snapshot` and `source refresh`. */
|
|
118
|
+
export async function acquire(flags) {
|
|
99
119
|
const given = ["url", "html", "text", "command"].filter((name) => flags[name] !== undefined)
|
|
100
|
-
if (given.
|
|
120
|
+
if (flags.raw !== undefined && given.some((name) => name !== "text")) throw new CliError("--raw goes alone or with --text (--url, --html and --command already keep the raw bytes)")
|
|
121
|
+
if (given.length + (flags.raw !== undefined && flags.text === undefined ? 1 : 0) !== 1) throw new CliError(SNAPSHOT_USAGE)
|
|
101
122
|
if (flags.extractor !== undefined && flags.text === undefined) throw new CliError("--extractor goes with --text only")
|
|
102
|
-
if (flags.
|
|
103
|
-
|
|
104
|
-
if (flags.
|
|
123
|
+
if (flags.charset !== undefined && encodingOf(flags.charset) === null) throw new CliError(`--charset ${flags.charset} is not a known encoding`)
|
|
124
|
+
const charset = flags.charset === undefined ? {} : { charset: encodingOf(flags.charset) }
|
|
125
|
+
if (flags.url !== undefined) return { ...(await fetchSource(flags.url)), ...charset, extractor: TOOL_EXTRACTOR }
|
|
126
|
+
if (flags.html !== undefined) return { path: resolve(flags.html), raw: readBytes(flags.html), markup: true, ...charset, extractor: "model" }
|
|
127
|
+
if (flags.raw !== undefined && flags.text === undefined) return { path: resolve(flags.raw), raw: readBytes(flags.raw), ...charset, extractor: "model" }
|
|
128
|
+
if (flags.text !== undefined) {
|
|
129
|
+
const extractor = flags.extractor === undefined ? "model" : `extractor:${flags.extractor}`
|
|
130
|
+
if (flags.raw !== undefined) return { path: resolve(flags.raw), raw: readBytes(flags.raw), text: readInput(flags.text), ...charset, extractor }
|
|
131
|
+
if (flags.kind !== undefined && flags.kind !== "converted-only") throw new CliError("--text without --raw registers a converted-only source; pass --raw <original bytes> to keep a measurable snapshot")
|
|
132
|
+
return { path: resolve(flags.text), text: readInput(flags.text), kind: "converted-only", extractor }
|
|
133
|
+
}
|
|
105
134
|
return { ...runCommand(flags.command, flags.cwd), extractor: TOOL_EXTRACTOR }
|
|
106
135
|
}
|
|
107
136
|
|
|
137
|
+
/**
|
|
138
|
+
* `--replace` with `--text` alone (the conversion_altered_number recovery) keeps the source's raw.bin and
|
|
139
|
+
* declares the verified text its extraction, so value rows locate in text.txt while the original bytes stay
|
|
140
|
+
* pinned; plain `--text` without `--replace`, or over an id with no raw.bin, stays converted-only.
|
|
141
|
+
*/
|
|
142
|
+
function declareOverKeptRaw(sourcesDir, id, input) {
|
|
143
|
+
const dir = join(sourcesDir, String(id))
|
|
144
|
+
if (input.kind !== "converted-only" || !existsSync(join(dir, "raw.bin")) || !existsSync(join(dir, "meta.json"))) return
|
|
145
|
+
const before = JSON.parse(readFileSync(join(dir, "meta.json"), "utf8"))
|
|
146
|
+
Object.assign(input, { url: before.url, raw: readFileSync(join(dir, "raw.bin")), kind: before.kind, declared: true })
|
|
147
|
+
delete input.path
|
|
148
|
+
}
|
|
149
|
+
|
|
108
150
|
export async function runSource(argv) {
|
|
109
151
|
const [sub, ...rest] = argv
|
|
152
|
+
if (sub === "refresh") return (await import("./source-refresh.mjs")).runRefresh(rest)
|
|
153
|
+
if (sub === "probe-conversion") return runConversionProbe(rest)
|
|
110
154
|
if (sub !== "snapshot") throw new CliError(SNAPSHOT_USAGE)
|
|
111
|
-
const args = parseArgs(rest)
|
|
155
|
+
const args = parseArgs(rest, { booleans: ["replace"] })
|
|
112
156
|
const id = args.required("id")
|
|
113
|
-
const
|
|
157
|
+
const sessionDir = sessionDirOf(args.flags)
|
|
158
|
+
const sourcesDir = join(sessionDir, "sources")
|
|
159
|
+
const replace = args.flags.replace === true
|
|
160
|
+
const pinned = replace ? readLedger(sessionDir).rows.filter((row) => row.source_id === id && (row.status ?? "active") === "active").map((row) => row.fact_id) : []
|
|
161
|
+
if (pinned.length > 0) {
|
|
162
|
+
const message = `${id} is cited by active row(s) ${pinned.join(", ")}; retract them first, or snapshot the corrected text under a new id`
|
|
163
|
+
return { json: { command: "source snapshot", status: "fail", exitCode: 1, error: "snapshot_pinned", message, rows: pinned }, summary: `source snapshot: ${message}`, exitCode: 1 }
|
|
164
|
+
}
|
|
114
165
|
const { receipt, ...input } = await acquire(args.flags)
|
|
166
|
+
if (replace) declareOverKeptRaw(sourcesDir, id, input)
|
|
115
167
|
if (args.flags.kind !== undefined) input.kind = args.flags.kind
|
|
116
168
|
if (args.flags.provenance !== undefined) input.provenance = args.flags.provenance
|
|
117
169
|
if (args.flags.revision !== undefined) input.revision = args.flags.revision
|
|
118
170
|
let written
|
|
119
171
|
try {
|
|
120
|
-
written = writeSnapshot(sourcesDir, id, input)
|
|
172
|
+
written = writeSnapshot(sourcesDir, id, input, { replace })
|
|
121
173
|
} catch (error) {
|
|
122
174
|
if (String(error.message).startsWith("snapshot_exists")) {
|
|
123
175
|
return { json: { command: "source snapshot", status: "fail", exitCode: 1, error: "snapshot_exists", message: error.message }, summary: `source snapshot: ${error.message}`, exitCode: 1 }
|
|
@@ -127,8 +179,9 @@ export async function runSource(argv) {
|
|
|
127
179
|
}
|
|
128
180
|
if (receipt) writeFileSync(join(written.dir, "command.json"), `${JSON.stringify(receipt, null, 2)}\n`)
|
|
129
181
|
const meta = JSON.parse(readFileSync(join(written.dir, "meta.json"), "utf8"))
|
|
130
|
-
const data = { source_id: id, directory: written.dir, snapshot_sha256: written.sha256, extractor: meta.extractor, kind: meta.kind, provenance: meta.provenance }
|
|
131
|
-
|
|
182
|
+
const data = { source_id: id, directory: written.dir, snapshot_sha256: written.sha256, extractor: meta.extractor, kind: meta.kind, provenance: meta.provenance, text_source: meta.text_source, ...(written.altered ? { conversion_altered_numbers: written.altered } : {}) }
|
|
183
|
+
const probe = written.altered ? `; conversion ${written.altered.length} altered${written.altered.length ? ` (${written.altered.join(", ")}): fact add refuses those numbers` : ""}` : ""
|
|
184
|
+
return { json: { command: "source snapshot", status: "pass", exitCode: 0, data }, summary: `source snapshot: ${id} ${written.sha256.slice(0, 12)} (${meta.extractor}, ${meta.text_source})${probe}`, exitCode: 0 }
|
|
132
185
|
}
|
|
133
186
|
|
|
134
187
|
export function runClaims(argv) {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// source-refresh.mjs - `source refresh <S<n>>`: the one explicit repin of a source snapshot.
|
|
2
|
+
//
|
|
3
|
+
// Re-fetches meta.url (or reads the new capture given with the source snapshot input flags),
|
|
4
|
+
// replaces the snapshot, and re-anchors every active byte-located ledger row on that source by its
|
|
5
|
+
// exact quote plus its stored context (raw-locator.mjs reanchor): a row found once gets the new
|
|
6
|
+
// snapshot_sha256 and keeps its old locator, so `fact verify` then reports minor `relocated` with
|
|
7
|
+
// the old and new byte offsets; a row whose quote is gone keeps its old pin, is reported as
|
|
8
|
+
// quote_not_verbatim here, and stays a snapshot_hash_mismatch blocker until it is retracted or
|
|
9
|
+
// re-added. A legacy text.txt row on the source (no byte locator) cannot be re-anchored: it is
|
|
10
|
+
// listed as legacy_not_reanchored and stays a blocker. Exit 0 when every row re-anchored, 1 otherwise. node: builtins and sibling imports only.
|
|
11
|
+
|
|
12
|
+
import { writeFileSync } from "node:fs"
|
|
13
|
+
import { join } from "node:path"
|
|
14
|
+
|
|
15
|
+
import { CliError, parseArgs } from "./cli-support.mjs"
|
|
16
|
+
import { DEFECT_CODES } from "./contracts.mjs"
|
|
17
|
+
import { readLedger, writeLedger } from "./fact-ledger.mjs"
|
|
18
|
+
import { reanchor } from "./raw-locator.mjs"
|
|
19
|
+
import { acquire, sessionDirOf, snapshotOf } from "./source-commands.mjs"
|
|
20
|
+
import { writeSnapshot } from "./source-snapshot.mjs"
|
|
21
|
+
|
|
22
|
+
export const REFRESH_USAGE =
|
|
23
|
+
"usage: source refresh S<n> [--url <u> | --html <file> | --raw <file> [--text <file> --extractor NAME@VERSION] | --text <file> | --command '<argv json>' --cwd DIR] [--charset NAME] --session-dir D (no input flag re-fetches the source's http(s) url)"
|
|
24
|
+
|
|
25
|
+
const INPUTS = ["url", "html", "raw", "text", "command"]
|
|
26
|
+
|
|
27
|
+
const defect = (code, message) => ({ code, severity: DEFECT_CODES[code].severity, integrity: DEFECT_CODES[code].integrity, message })
|
|
28
|
+
|
|
29
|
+
export async function runRefresh(argv) {
|
|
30
|
+
const args = parseArgs(argv)
|
|
31
|
+
const id = args.positionals[0] ?? args.flags.id
|
|
32
|
+
if (!id || id === true) throw new CliError(REFRESH_USAGE)
|
|
33
|
+
const sessionDir = sessionDirOf(args.flags)
|
|
34
|
+
const before = snapshotOf(sessionDir, id)
|
|
35
|
+
const flags = { ...args.flags }
|
|
36
|
+
if (!INPUTS.some((name) => flags[name] !== undefined)) {
|
|
37
|
+
if (!/^https?:\/\//i.test(String(before.meta.url))) throw new CliError(`${id} was not fetched from an http(s) url; pass its new capture. ${REFRESH_USAGE}`)
|
|
38
|
+
flags.url = before.meta.url
|
|
39
|
+
}
|
|
40
|
+
const { receipt, ...input } = await acquire(flags)
|
|
41
|
+
input.kind ??= flags.kind ?? before.meta.kind
|
|
42
|
+
input.provenance = flags.provenance ?? before.meta.provenance
|
|
43
|
+
input.revision = flags.revision ?? before.meta.revision ?? undefined
|
|
44
|
+
let written
|
|
45
|
+
try {
|
|
46
|
+
written = writeSnapshot(join(sessionDir, "sources"), id, input, { replace: true })
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (error instanceof TypeError) throw new CliError(error.message)
|
|
49
|
+
throw error
|
|
50
|
+
}
|
|
51
|
+
if (receipt) writeFileSync(join(written.dir, "command.json"), `${JSON.stringify(receipt, null, 2)}\n`)
|
|
52
|
+
const after = snapshotOf(sessionDir, id)
|
|
53
|
+
const ledger = readLedger(sessionDir)
|
|
54
|
+
const rows = []
|
|
55
|
+
const defects = []
|
|
56
|
+
for (const row of ledger.rows) {
|
|
57
|
+
if (row.source_id !== id || row.status !== "active") continue
|
|
58
|
+
if (row.locator?.unit === undefined) {
|
|
59
|
+
rows.push({ fact_id: row.fact_id, status: "legacy_not_reanchored" })
|
|
60
|
+
defects.push(defect("snapshot_hash_mismatch", `${row.fact_id}: a legacy text.txt row has no byte locator to re-anchor on refreshed ${id}; add it again from the new snapshot or retract it`))
|
|
61
|
+
continue
|
|
62
|
+
}
|
|
63
|
+
if (row.locator.unit !== "bytes") continue
|
|
64
|
+
const anchor = row.locator.artifact === after.view.artifact ? reanchor(after.view, row) : null
|
|
65
|
+
const span = `${row.locator.char_start}:${row.locator.char_end}`
|
|
66
|
+
if (!anchor) {
|
|
67
|
+
rows.push({ fact_id: row.fact_id, status: "not_found", from: span })
|
|
68
|
+
defects.push(defect("quote_not_verbatim", `${row.fact_id}: its quote and context are not found once in refreshed ${id}; retract it or add it again from the new snapshot`))
|
|
69
|
+
continue
|
|
70
|
+
}
|
|
71
|
+
row.snapshot_sha256 = after.sha256
|
|
72
|
+
rows.push({ fact_id: row.fact_id, status: anchor.relocated ? "relocated" : "unchanged", from: span, to: `${anchor.start}:${anchor.end}` })
|
|
73
|
+
if (anchor.relocated) defects.push(defect("relocated", `${row.fact_id}: ${span} -> ${anchor.start}:${anchor.end} (bytes of ${id}/${after.view.artifact})`))
|
|
74
|
+
}
|
|
75
|
+
writeLedger(sessionDir, ledger)
|
|
76
|
+
const failed = rows.filter((row) => row.status === "not_found" || row.status === "legacy_not_reanchored").length
|
|
77
|
+
const exitCode = failed > 0 ? 1 : 0
|
|
78
|
+
const data = { source_id: id, previous_sha256: before.sha256, snapshot_sha256: after.sha256, text_source: after.view.mode, rows }
|
|
79
|
+
const json = { command: "source refresh", status: exitCode === 0 ? "pass" : "fail", exitCode, defects, data }
|
|
80
|
+
const moved = rows.filter((row) => row.status === "relocated").length
|
|
81
|
+
return { json, summary: `source refresh: ${id} ${before.sha256.slice(0, 12)} -> ${after.sha256.slice(0, 12)}; ${rows.length - failed} row(s) re-anchored (${moved} relocated), ${failed} not re-anchored`, exitCode }
|
|
82
|
+
}
|