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
|
@@ -7,12 +7,16 @@
|
|
|
7
7
|
// No model, no network.
|
|
8
8
|
|
|
9
9
|
import { existsSync, readFileSync } from "node:fs"
|
|
10
|
-
import {
|
|
10
|
+
import { resolve, sep } from "node:path"
|
|
11
11
|
|
|
12
|
-
import { sha256Of } from "./cli-support.mjs"
|
|
13
12
|
import { sameValue, unitKey } from "./fidelity-binding.mjs"
|
|
13
|
+
import { readCsv } from "./fidelity-csv.mjs"
|
|
14
14
|
import { claimChecks } from "./fidelity-claims.mjs"
|
|
15
|
+
import { sourceChecks } from "./fidelity-sources.mjs"
|
|
16
|
+
import { convertedHalfFits, followsOriginal, isDerivedRow, originalProblem, renderLocator, staleRender, textAfter } from "./fidelity-originals.mjs"
|
|
17
|
+
import { snapshotCause, unreadableSnapshots } from "./fidelity-snapshot-readability.mjs"
|
|
15
18
|
import { STRUCTURAL, clip, traceChecks } from "./fidelity-trace.mjs"
|
|
19
|
+
import { fillEntriesByNode, valueUnitProblem } from "./fidelity-value-unit.mjs"
|
|
16
20
|
import { parseHtml, proseText } from "./html-lite.mjs"
|
|
17
21
|
import { parseNumeral } from "./numerals.mjs"
|
|
18
22
|
import { div, fromDecimal, sub } from "./rational.mjs"
|
|
@@ -45,11 +49,14 @@ function quoteProblem(row, shown, selector) {
|
|
|
45
49
|
return bare(shown) === bare(want) ? null : ["quote_not_verbatim", `"${clip(shown)}" is not the ${selector} selection of ${row.fact_id}: "${clip(want)}"`]
|
|
46
50
|
}
|
|
47
51
|
|
|
48
|
-
function factProblem(row, shown, attrs = {}) {
|
|
52
|
+
function factProblem(row, shown, attrs = {}, rows = new Map()) {
|
|
53
|
+
const original = originalProblem(row, shown, rows, attrs["data-fact-mode"] === "value")
|
|
54
|
+
if (original) return original
|
|
49
55
|
if (attrs["data-unit"] !== undefined && unitKey(attrs["data-unit"]) !== unitKey(row.unit)) return ["unit_mismatch", `data-unit "${attrs["data-unit"]}" but ${row.fact_id} is in "${row.unit}"`]
|
|
50
56
|
if (attrs.value !== undefined && !sameValue(attrs.value, row.value)) return ["value_mismatch", `value="${attrs.value}" but ${row.fact_id} is ${row.value}`]
|
|
57
|
+
if (convertedHalfFits(row, shown)) return null
|
|
51
58
|
const text = normalizeText(shown)
|
|
52
|
-
const forms = [row.raw, row.render, row.value, row.unit && `${row.value} ${row.unit}`].filter(Boolean).map(normalizeText)
|
|
59
|
+
const forms = [...(["converted", "derived"].includes(row.kind) ? [] : [row.raw, row.render]), row.value, row.unit && `${row.value} ${row.unit}`].filter(Boolean).map(normalizeText)
|
|
53
60
|
if (forms.some((form) => text === form || (text.endsWith(` ${form}`) && !/\d/.test(text.slice(0, -form.length))))) return null
|
|
54
61
|
const parsed = parseNumeral(text)
|
|
55
62
|
if (!parsed) return unitKey(text) === unitKey(row.unit) ? null : ["value_mismatch", `"${clip(shown)}" shows no value of ${row.fact_id} (${row.value})`]
|
|
@@ -73,16 +80,6 @@ export function exportRows(ledger) {
|
|
|
73
80
|
return (ledger?.rows ?? []).filter((row) => row.status === "active" && row.kind !== "quote" && row.value !== null).map((row) => ({ fact_id: row.fact_id, label: row.label, plot_value: row.value, unit: row.unit ?? "" }))
|
|
74
81
|
}
|
|
75
82
|
|
|
76
|
-
function readCsv(path) {
|
|
77
|
-
if (!existsSync(path)) return null
|
|
78
|
-
const lines = readFileSync(path, "utf8").split(/\r?\n/).filter((line) => line.trim() !== "")
|
|
79
|
-
const cells = (line) => line.split(",").map((cell) => cell.trim().replace(/^"(.*)"$/, "$1"))
|
|
80
|
-
const head = cells(lines[0] ?? "")
|
|
81
|
-
const [id, value, unit] = ["fact_id", "plot_value", "unit"].map((name) => head.indexOf(name))
|
|
82
|
-
if (id < 0 || value < 0 || unit < 0 || lines.length < 2) return null
|
|
83
|
-
return lines.slice(1).map((line) => cells(line)).map((c) => ({ fact_id: c[id], plot_value: c[value], unit: c[unit] ?? "" }))
|
|
84
|
-
}
|
|
85
|
-
|
|
86
83
|
const walk = (node) => node.children.filter((child) => child.tag !== "#text").flatMap((child) => [child, ...walk(child)])
|
|
87
84
|
|
|
88
85
|
/** SVG text nodes of a chart: data labels, or ticks with their declared grid. */
|
|
@@ -140,46 +137,57 @@ function chartProblem(ctx, fig, labels, ledger) {
|
|
|
140
137
|
* @param {object} ctx buildContext(...) from gates-static.mjs
|
|
141
138
|
* @param {{ rows: object[] }} ledger
|
|
142
139
|
* @param {{ fact_id: string, rendered: string, selector?: string }[] | null} fillMap Markdown fill map, or null
|
|
143
|
-
* @param {string | null} sourcesDir directory of <S-id>/
|
|
140
|
+
* @param {string | null} sourcesDir directory of <S-id>/ snapshots (source-view.mjs reads them)
|
|
144
141
|
* @param {{ recompute?: (ledger: object, row: object) => { ok: boolean }, asOf?: string | null }} options
|
|
145
142
|
*/
|
|
146
143
|
export function valueChecks(ctx, ledger, fillMap, sourcesDir, options = {}) {
|
|
147
144
|
const out = []
|
|
148
|
-
const flag = (code, node, message) => out.push(ctx.defect(code, node, message))
|
|
145
|
+
const flag = (code, node, message, extra = {}) => out.push({ ...ctx.defect(code, node, message), ...extra })
|
|
149
146
|
const rows = new Map((ledger?.rows ?? []).map((row) => [row.fact_id, row]))
|
|
150
147
|
const cited = new Map()
|
|
148
|
+
const fills = (fillMap ?? []).map((entry) => entry.rendered)
|
|
151
149
|
const check = (id, node, problemOf) => {
|
|
152
150
|
const row = rows.get(id)
|
|
153
151
|
if (!row) return flag("unresolved_placeholder", node, `${id} names no ledger row`)
|
|
154
152
|
if (!cited.has(id)) cited.set(id, node)
|
|
155
153
|
const problem = problemOf(row)
|
|
156
|
-
if (problem)
|
|
154
|
+
if (problem) out.push({ ...ctx.defect(problem[0], node, problem[1]), ...(problem[2] ? { part: problem[2] } : {}) })
|
|
157
155
|
}
|
|
158
156
|
for (const node of ctx.all.filter((cur) => cur.attrs["data-fact"] !== undefined)) {
|
|
159
157
|
const selector = node.attrs["data-quote-sel"] ?? "full"
|
|
160
|
-
|
|
158
|
+
const glued = (row) => isDerivedRow(row) && node.attrs["data-fact-mode"] !== "value" && followsOriginal(row, rows, fills)(textAfter(node)) ? ["value_mismatch", `another original follows ${row.fact_id}: "${clip(textAfter(node))}"`, "original"] : null
|
|
159
|
+
check(node.attrs["data-fact"], node, (row) => (row.kind === "quote" ? quoteProblem(row, withoutFooter(node), selector) : (factProblem(row, proseText(node), node.attrs, rows) ?? glued(row))))
|
|
161
160
|
}
|
|
162
161
|
const docText = bare(proseText(ctx.body))
|
|
163
162
|
for (const entry of fillMap ?? []) {
|
|
164
163
|
check(entry.fact_id, ctx.body, (row) => {
|
|
165
|
-
const problem = row.kind === "quote" ? quoteProblem(row, entry.rendered, entry.selector ?? "full") : factProblem(row, entry.rendered)
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
const problem = row.kind === "quote" ? quoteProblem(row, entry.rendered, entry.selector ?? "full") : factProblem(row, entry.rendered, { "data-fact-mode": entry.mode }, rows)
|
|
165
|
+
const stale = isDerivedRow(row) ? staleRender(row, entry.rendered, proseText(ctx.body), followsOriginal(row, rows, fills)) : docText.includes(bare(entry.rendered)) ? null : "gone"
|
|
166
|
+
if (problem || stale === null) return problem
|
|
167
|
+
return [row.kind === "quote" ? "quote_not_verbatim" : "value_mismatch", `filled text "${clip(entry.rendered)}" of ${row.fact_id} is no longer in the report${stale === "original" ? " (its original was edited)" : ""}`, ...(stale === "original" ? ["original"] : [])]
|
|
168
168
|
})
|
|
169
169
|
}
|
|
170
170
|
rowChecks(ctx, ledger, rows, cited, options, flag)
|
|
171
|
+
// options.fillEntries: the edition's fill-map entries whose element is in the checked HTML (value mode, fill's unit_bound).
|
|
172
|
+
const facts = ctx.all.filter((cur) => cur.attrs["data-fact"] !== undefined)
|
|
173
|
+
const entries = fillEntriesByNode(facts, options.fillEntries)
|
|
174
|
+
for (const node of facts) {
|
|
175
|
+
const row = rows.get(node.attrs["data-fact"])
|
|
176
|
+
const problem = row && row.kind !== "quote" && !factProblem(row, proseText(node), node.attrs, rows) && valueUnitProblem(node, row, entries.get(node))
|
|
177
|
+
if (problem) flag(problem[0], node, problem[1])
|
|
178
|
+
}
|
|
171
179
|
for (const tr of ctx.all.filter((node) => node.tag === "tr" && node.attrs["data-row-kind"] !== "comparison")) {
|
|
172
180
|
const groups = new Set(ctx.util.descendants(tr).map((node) => rows.get(node.attrs["data-fact"])?.observation_id).filter(Boolean))
|
|
173
181
|
if (groups.size > 1) flag("join_integrity_fail", tr, `one table row joins observations ${[...groups].join(", ")}`)
|
|
174
182
|
}
|
|
175
|
-
const meta = sourceChecks(ctx, rows, cited, sourcesDir, flag)
|
|
183
|
+
const meta = sourceChecks(ctx, rows, cited, sourcesDir, flag, unreadableSnapshots(ctx, rows, cited, sourcesDir, out))
|
|
176
184
|
claimChecks(ctx, rows, (row) => provenance(sourcesDir, meta, row), flag)
|
|
177
185
|
const charts = chartFigures(ctx)
|
|
178
186
|
for (const { node, scope } of ctx.elements) {
|
|
179
187
|
const kind = ctx.kindOf(scope)
|
|
180
188
|
if ((node.tag === "q" || node.tag === "blockquote") && node.attrs["data-fact"] === undefined && kind !== "sources" && kind !== "toc") flag("quote_unbound", node, `<${node.tag}> with no Q row: "${clip(proseText(node))}"`)
|
|
181
189
|
}
|
|
182
|
-
traceChecks(ctx, charts, fillMap, flag, fillSiteFits(rows))
|
|
190
|
+
traceChecks(ctx, charts, fillMap, flag, fillSiteFits(rows), renderLocator(rows, fillMap))
|
|
183
191
|
for (const [fig, labels] of charts) {
|
|
184
192
|
const problem = chartProblem(ctx, fig, labels, ledger)
|
|
185
193
|
if (problem) flag("chart_value_untraceable", fig, problem)
|
|
@@ -190,16 +198,23 @@ export function valueChecks(ctx, ledger, fillMap, sourcesDir, options = {}) {
|
|
|
190
198
|
function rowChecks(ctx, ledger, rows, cited, options, flag) {
|
|
191
199
|
// An as-of of "latest ..." or "... per snapshot" names no fixed revision, so quote_stale_version is skipped.
|
|
192
200
|
const asOf = options.asOf && !/^latest\b|per snapshot/i.test(options.asOf) ? options.asOf : null
|
|
201
|
+
// A sentence-final period ("release v1.2.") is punctuation, not part of the revision token.
|
|
202
|
+
const target = asOf?.replace(/\.(?=\s|$)/gu, "")
|
|
193
203
|
for (const [id, node] of cited) {
|
|
194
204
|
const row = rows.get(id)
|
|
195
205
|
if (row.fuzzy === true) flag("quote_fuzzy_match", node, `${id} was registered from a similarity match on an OCR-noisy snapshot`)
|
|
196
206
|
const revision = typeof row.revision === "string" ? row.revision : (row.revision?.id ?? row.revision?.tag ?? null)
|
|
197
|
-
|
|
207
|
+
const revisionPattern = revision && new RegExp(`(?<![\\w.-])${revision.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w.-])`, "u")
|
|
208
|
+
if (asOf && revisionPattern && !revisionPattern.test(target)) flag("quote_stale_version", node, `${id} is from revision ${revision}; the brief targets "${asOf}"`)
|
|
198
209
|
if ((row.kind === "derived" || row.kind === "converted") && options.recompute?.(ledger, row)?.ok === false) flag("value_mismatch", node, `${id} does not recompute from its operands`)
|
|
199
210
|
const window = row.snapshot_window
|
|
200
211
|
if (window && typeof window === "object" && window.start && window.end) {
|
|
201
212
|
const [start, end] = [Date.parse(window.start), Date.parse(window.end)]
|
|
202
|
-
const
|
|
213
|
+
const [absent, present] = [(row.operands ?? []).filter((op) => !rows.has(op)), (row.operands ?? []).filter((op) => rows.has(op))]
|
|
214
|
+
for (const op of absent) flag("operand_missing", node, `operand ${op} of ${id} is not in the fact ledger`)
|
|
215
|
+
const missing = present.filter((op) => !rows.get(op).observed_at)
|
|
216
|
+
for (const op of missing) flag("operand_timestamp_missing", node, `operand ${op} of ${id} has no observed_at timestamp`)
|
|
217
|
+
const outside = present.find((op) => !missing.includes(op) && !(Date.parse(rows.get(op).observed_at) >= start && Date.parse(rows.get(op).observed_at) < end))
|
|
203
218
|
if (outside) flag("snapshot_mismatch", node, `operand ${outside} of ${id} was observed outside ${window.start} to ${window.end}`)
|
|
204
219
|
}
|
|
205
220
|
}
|
|
@@ -213,17 +228,3 @@ function provenance(sourcesDir, meta, row) {
|
|
|
213
228
|
const path = resolve(dir, artifact)
|
|
214
229
|
return path.startsWith(`${dir}${sep}`) && existsSync(path) ? meta.get(row.source_id)?.kind : undefined
|
|
215
230
|
}
|
|
216
|
-
|
|
217
|
-
function sourceChecks(ctx, rows, cited, sourcesDir, flag) {
|
|
218
|
-
const ids = new Set([...cited.keys()].map((id) => rows.get(id)?.source_id).filter(Boolean))
|
|
219
|
-
for (const match of proseText(ctx.body).matchAll(/\[S(\d+)\]/g)) ids.add(`S${match[1]}`)
|
|
220
|
-
const meta = new Map()
|
|
221
|
-
for (const id of sourcesDir ? ids : []) {
|
|
222
|
-
const [metaPath, textPath] = [join(sourcesDir, id, "meta.json"), join(sourcesDir, id, "text.txt")]
|
|
223
|
-
if (!existsSync(metaPath) || !existsSync(textPath)) continue
|
|
224
|
-
meta.set(id, JSON.parse(readFileSync(metaPath, "utf8")))
|
|
225
|
-
const actual = sha256Of(readFileSync(textPath))
|
|
226
|
-
if (meta.get(id).sha256 !== actual) flag("snapshot_hash_mismatch", ctx.body, `${id}/text.txt changed after its snapshot was pinned`)
|
|
227
|
-
}
|
|
228
|
-
return meta
|
|
229
|
-
}
|
|
@@ -1,36 +1,15 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
1
2
|
import { describe, expect, test } from "bun:test"
|
|
2
|
-
import { cpSync, mkdtempSync,
|
|
3
|
+
import { cpSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"
|
|
3
4
|
import { tmpdir } from "node:os"
|
|
4
5
|
import { join } from "node:path"
|
|
5
6
|
|
|
6
|
-
import { exportRows
|
|
7
|
-
import { buildContext } from "./gates-static.mjs"
|
|
8
|
-
import { parseHtml } from "./html-lite.mjs"
|
|
7
|
+
import { exportRows } from "./fidelity-values.mjs"
|
|
9
8
|
import { similarity } from "./text-similarity.mjs"
|
|
9
|
+
import { LEDGER, SOURCES, ledgerWith, run, type Defect, type Row } from "./tests/fidelity-values-support"
|
|
10
10
|
|
|
11
|
-
type Defect = { code: string; severity: string; selector: string; line: number; message: string; hint: string }
|
|
12
|
-
type Row = Record<string, unknown> & { fact_id: string }
|
|
13
|
-
type Ledger = { schemaVersion: number; rows: Row[]; events: unknown[] }
|
|
14
|
-
type Options = { ledger?: Ledger; fillMap?: unknown[] | null; sourcesDir?: string | null; baseDir?: string; recompute?: (ledger: Ledger, row: Row) => { ok: boolean }; asOf?: string }
|
|
15
|
-
|
|
16
|
-
const FIX = join(import.meta.dir, "tests", "fixtures", "fidelity")
|
|
17
|
-
const SOURCES = join(FIX, "sources")
|
|
18
|
-
const LEDGER: Ledger = JSON.parse(readFileSync(join(FIX, "ledger-verify.json"), "utf8"))
|
|
19
11
|
const FULL = "we estimate completion no earlier than 2027"
|
|
20
12
|
|
|
21
|
-
function ledgerWith(id: string, patch: Record<string, unknown>): Ledger {
|
|
22
|
-
const copy = structuredClone(LEDGER)
|
|
23
|
-
copy.rows = copy.rows.map((row) => (row.fact_id === id ? { ...row, ...patch } : row))
|
|
24
|
-
return copy
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function run(body: string, options: Options = {}): Defect[] {
|
|
28
|
-
const html = /<h2/.test(body) ? body : `<h2>Findings</h2>\n${body}`
|
|
29
|
-
const ctx = buildContext(parseHtml(html), { baseDir: options.baseDir ?? FIX })
|
|
30
|
-
const sourcesDir = options.sourcesDir === undefined ? SOURCES : options.sourcesDir
|
|
31
|
-
return valueChecks(ctx, options.ledger ?? LEDGER, options.fillMap ?? null, sourcesDir, options) as Defect[]
|
|
32
|
-
}
|
|
33
|
-
|
|
34
13
|
const codes = (defects: Defect[]) => defects.map((defect) => defect.code)
|
|
35
14
|
const fact = (id: string, text: string, unit = "") => `<data class="fact" data-fact="${id}"${unit ? ` data-unit="${unit}"` : ""}>${text}</data>`
|
|
36
15
|
const quote = (sel: string, text: string) => `<p>They wrote <q data-fact="Q1" data-quote-sel="${sel}">${text}</q> [S4].</p>`
|
|
@@ -53,8 +32,8 @@ describe("untraceable numbers", () => {
|
|
|
53
32
|
expect(codes(run("<h2>Appendix</h2><p>Revenue grew 12% [S4].</p>"))).toEqual(["untraceable_number"])
|
|
54
33
|
})
|
|
55
34
|
|
|
56
|
-
test("#given the same sentence under Sources #when checked #then
|
|
57
|
-
expect(run("<h2>Sources</h2><p>Revenue grew 12% [S4].</p>")).toEqual([])
|
|
35
|
+
test("#given the same sentence under Sources #when checked #then prose still needs a ledger row", () => {
|
|
36
|
+
expect(codes(run("<h2>Sources</h2><p>Revenue grew 12% [S4].</p>"))).toEqual(["untraceable_number"])
|
|
58
37
|
})
|
|
59
38
|
|
|
60
39
|
test("#given a date in prose #when checked #then dates are in scope", () => {
|
|
@@ -218,14 +197,14 @@ describe("verification claims are structural (data-claim-kind)", () => {
|
|
|
218
197
|
`<p>The bridge, which ran across the river, spans ${fact("F1", "up to 320 m", "m")} [S4].</p>`,
|
|
219
198
|
`<p>The span is ${fact("F1", "up to 320 m", "m")}, as confirmed with the annual inspection report [S4].</p>`,
|
|
220
199
|
`<p>Clinical tests confirmed the span of ${fact("F1", "up to 320 m", "m")} [S4].</p>`,
|
|
221
|
-
`<p
|
|
200
|
+
`<p>\uD655\uC778\uB41C \uAE38\uC774\uB294 ${fact("F1", "\uCD5C\uB300 320 m", "m")} [S4].</p>`,
|
|
222
201
|
]
|
|
223
202
|
for (const body of quiet) {
|
|
224
203
|
test(`#given findings prose ${JSON.stringify(body.replace(/<[^>]+>/g, ""))} #when checked #then no warning and no major`, () => expect(run(body)).toEqual([]))
|
|
225
204
|
}
|
|
226
205
|
|
|
227
206
|
test("#given an UNMARKED Korean run-and-check sentence #when checked #then verification_claim_unmarked minor only", () => {
|
|
228
|
-
expect(severities(run(`<p
|
|
207
|
+
expect(severities(run(`<p>\uC6B0\uB9AC\uAC00 \uC2E4\uD589\uD574 \uD655\uC778\uD55C \uAE38\uC774\uB294 ${fact("F1", "\uCD5C\uB300 320 m", "m")} [S4].</p>`))).toEqual(["verification_claim_unmarked:minor"])
|
|
229
208
|
})
|
|
230
209
|
|
|
231
210
|
test("#given the same run-and-check sentence MARKED verified on a command row #when checked #then no warning", () => {
|
|
@@ -20,11 +20,13 @@ import { parseHtml } from "./html-lite.mjs"
|
|
|
20
20
|
|
|
21
21
|
/** Every code this gate can raise. */
|
|
22
22
|
export const FIDELITY_GATE_CODES = Object.freeze([
|
|
23
|
+
"unit_unbound",
|
|
23
24
|
"fidelity_interview_incomplete", "unresolved_placeholder", "value_mismatch", "unit_mismatch", "quote_not_verbatim",
|
|
24
25
|
"quote_unbound", "claim_status_invalid", "snapshot_hash_mismatch", "chart_value_untraceable", "untraceable_number",
|
|
25
26
|
"unsupported_verification", "conflicting_readings", "hedge_dropped", "direction_flipped", "causality_added",
|
|
26
|
-
"qualifier_dropped", "unbound_sentence", "snapshot_mismatch", "join_integrity_fail", "quote_stale_version",
|
|
27
|
+
"qualifier_dropped", "unbound_sentence", "snapshot_mismatch", "operand_timestamp_missing", "operand_missing", "join_integrity_fail", "quote_stale_version",
|
|
27
28
|
"quote_fuzzy_match", "name_outside_quote", "scope_widened_warn", "claim_kind_mismatch", "verification_claim_unmarked",
|
|
29
|
+
"snapshot_not_raw", "relocated", "quote_converted_only",
|
|
28
30
|
])
|
|
29
31
|
const RANK = { blocker: 0, major: 1, minor: 2 }
|
|
30
32
|
|
|
@@ -40,8 +42,8 @@ export function deliveryBlockReason(defect) {
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
function withIntegrity(defect) {
|
|
43
|
-
const { code, severity, selector, line, message, hint } = defect
|
|
44
|
-
return { code, severity, integrity: DEFECT_CODES[code].integrity, selector, line, message, hint }
|
|
45
|
+
const { code, severity, selector, line, message, hint, part, fact_id } = defect
|
|
46
|
+
return { code, severity, integrity: DEFECT_CODES[code].integrity, selector, line, message, hint, ...(part ? { part } : {}), ...(fact_id ? { fact_id } : {}) }
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
function compareDefects(a, b) {
|
|
@@ -93,17 +95,17 @@ function incomplete(parsed) {
|
|
|
93
95
|
|
|
94
96
|
/**
|
|
95
97
|
* @param {string} html the filled report
|
|
96
|
-
* @param {{ ledger: { rows: object[] }, sourcesDir?: string | null, claims?: object | null, fillMap?: object[] | null,
|
|
98
|
+
* @param {{ ledger: { rows: object[] }, sourcesDir?: string | null, claims?: object | null, fillMap?: object[] | null, fillEntries?: object[] | null,
|
|
97
99
|
* brief: string | object, baseDir?: string, recompute?: (ledger: object, row: object) => { ok: boolean } }} options
|
|
98
100
|
* `brief` is the brief.md text or parseFidelityBlock output; `baseDir` resolves data-chart-source paths.
|
|
99
101
|
* @returns {{ defects: object[], gatesRun: string[] }}
|
|
100
102
|
*/
|
|
101
|
-
export function checkFidelity(html, { ledger, sourcesDir = null, claims = null, fillMap = null, brief, baseDir, recompute } = {}) {
|
|
103
|
+
export function checkFidelity(html, { ledger, sourcesDir = null, claims = null, fillMap = null, fillEntries = null, brief, baseDir, recompute } = {}) {
|
|
102
104
|
const parsed = brief && typeof brief === "object" ? brief : parseFidelityBlock(String(brief ?? ""))
|
|
103
105
|
if (!isLocked(parsed)) return { defects: [incomplete(parsed)], gatesRun: ["fidelity_interview_incomplete"] }
|
|
104
106
|
const ctx = buildContext(parseHtml(html), { baseDir })
|
|
105
107
|
const defects = [
|
|
106
|
-
...valueChecks(ctx, ledger, fillMap, sourcesDir, { recompute, asOf: parsed.fields["as of"] }),
|
|
108
|
+
...valueChecks(ctx, ledger, fillMap, sourcesDir, { recompute, asOf: parsed.fields["as of"], fillEntries }),
|
|
107
109
|
...bindingChecks(ctx, claims, ledger),
|
|
108
110
|
]
|
|
109
111
|
const pairs = fidelityPairs(ctx, ledger, sourcesDir)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test"
|
|
2
|
+
|
|
3
|
+
import { buildContext, checkStatic } from "./gates-static.mjs"
|
|
4
|
+
import { parseHtml } from "./html-lite.mjs"
|
|
5
|
+
|
|
6
|
+
describe("HTML exact Closing headings", () => {
|
|
7
|
+
test.each([
|
|
8
|
+
["Closing", "closing", false],
|
|
9
|
+
["Closing the gap: GPU prices", null, true],
|
|
10
|
+
] as const)("#given %s as an HTML heading #when checked #then closing scope matches the whole heading", (heading: string, kind: string | null, missing: boolean) => {
|
|
11
|
+
const root = parseHtml(`<h2>${heading}</h2><p>Prices fell 8%.</p>`)
|
|
12
|
+
expect(buildContext(root, {}).sections.map((section: { kind: string | null }) => section.kind)).toEqual([kind])
|
|
13
|
+
const { defects } = checkStatic(root, {})
|
|
14
|
+
expect(defects.some((defect) => "code" in defect && defect.code === "missing_closing_section")).toBe(missing)
|
|
15
|
+
expect(defects.some((defect) => "code" in defect && defect.code === "unsourced_number")).toBe(missing)
|
|
16
|
+
})
|
|
17
|
+
})
|
|
@@ -14,6 +14,7 @@ import { figureGates } from "./gates-figures.mjs"
|
|
|
14
14
|
import { structureGates } from "./gates-structure.mjs"
|
|
15
15
|
import { textGates } from "./gates-text.mjs"
|
|
16
16
|
import { PROSE_TAGS, proseText, selectorPath } from "./html-lite.mjs"
|
|
17
|
+
import { sourcesClaims } from "./sources-citation.mjs"
|
|
17
18
|
|
|
18
19
|
const CITATION_MARKER = /\[S\d+\]|\[Source\s*\d+\]|\[\uCD9C\uCC98[^\]]*\]|\[\^\d+\]/i
|
|
19
20
|
const ANCHOR_HREF = /^#(?:s|src|source|ref|fn)/i
|
|
@@ -65,6 +66,11 @@ function hasCitation(node) {
|
|
|
65
66
|
return CITATION_MARKER.test(proseText(node)) || descendants(node).some(isCitationAnchor)
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
function proseScope(scope, owner) {
|
|
70
|
+
if (scope.section?.kind !== "sources" || !owner || sourcesClaims(owner).length === 0) return scope
|
|
71
|
+
return { ...scope, section: { ...scope.section, kind: null } }
|
|
72
|
+
}
|
|
73
|
+
|
|
68
74
|
function toRegExp(pattern) {
|
|
69
75
|
const re = pattern instanceof RegExp ? pattern : new RegExp(String(pattern), "i")
|
|
70
76
|
return new RegExp(re.source, re.flags.replace(/[gy]/g, ""))
|
|
@@ -181,7 +187,10 @@ export function checkStatic(doc, options = {}) {
|
|
|
181
187
|
continue
|
|
182
188
|
}
|
|
183
189
|
gatesRun.push(...gate.codes)
|
|
184
|
-
|
|
190
|
+
const context = gate.codes.includes("unsourced_number")
|
|
191
|
+
? { ...ctx, elements: ctx.elements.map(({ node, scope }) => ({ node, scope: proseScope(scope, node) })) }
|
|
192
|
+
: ctx
|
|
193
|
+
defects.push(...gate.run(context))
|
|
185
194
|
}
|
|
186
195
|
return { defects, gatesRun, gatesSkipped }
|
|
187
196
|
}
|
|
@@ -23,7 +23,7 @@ const PROSE_SKIP = new Set(["code", "pre", "kbd", "samp", "script", "style", "sv
|
|
|
23
23
|
const SAFE_ID = /^[A-Za-z_][\w-]*$/
|
|
24
24
|
|
|
25
25
|
export const PROSE_TAGS = new Set(["p", "li", ...HEADINGS, "td", "th", "figcaption", "blockquote", "dd", "dt"])
|
|
26
|
-
const PROSE_BREAKS = new Set([...P_CLOSERS, ...PROSE_TAGS, "br", "tr"])
|
|
26
|
+
export const PROSE_BREAKS = new Set([...P_CLOSERS, ...PROSE_TAGS, "br", "tr"])
|
|
27
27
|
|
|
28
28
|
function makeNode(tag, attrs, parent, line) {
|
|
29
29
|
return { tag, attrs, children: [], parent, line, text: "", raw: null }
|
|
@@ -130,6 +130,8 @@ export function parseHtml(source) {
|
|
|
130
130
|
const flushText = (to) => {
|
|
131
131
|
if (to > textStart) {
|
|
132
132
|
const node = makeNode("#text", {}, top(), lineAt(starts, textStart))
|
|
133
|
+
node.source_start = textStart
|
|
134
|
+
node.source_end = to
|
|
133
135
|
node.text = decodeEntities(src.slice(textStart, to))
|
|
134
136
|
top().children.push(node)
|
|
135
137
|
}
|
|
@@ -157,7 +159,7 @@ export function parseHtml(source) {
|
|
|
157
159
|
const tag = readTag(src, lt + 2)
|
|
158
160
|
if (tag.name !== "body" && tag.name !== "html") {
|
|
159
161
|
for (let k = stack.length - 1; k > 0; k--) {
|
|
160
|
-
if (stack[k].tag === tag.name) { stack.length = k; break }
|
|
162
|
+
if (stack[k].tag === tag.name) { stack[k].source_end = lt; stack.length = k; break }
|
|
161
163
|
}
|
|
162
164
|
}
|
|
163
165
|
at = textStart = tag.end
|
|
@@ -169,6 +171,8 @@ export function parseHtml(source) {
|
|
|
169
171
|
if (P_CLOSERS.has(tag.name)) closeWithin("p", P_SCOPE)
|
|
170
172
|
if (tag.name === "li") closeWithin("li", LI_SCOPE)
|
|
171
173
|
const node = makeNode(tag.name, tag.attrs, top(), lineAt(starts, lt))
|
|
174
|
+
node.source_start = tag.end
|
|
175
|
+
node.source_end = src.length
|
|
172
176
|
top().children.push(node)
|
|
173
177
|
if (tag.name === "body") sawBody = true
|
|
174
178
|
if (tag.attrs.id) root.ids.set(tag.attrs.id, (root.ids.get(tag.attrs.id) ?? 0) + 1)
|
|
@@ -61,10 +61,10 @@ function scriptEnd(src, from) {
|
|
|
61
61
|
function closeOf(src, from, name) {
|
|
62
62
|
if (name === "script") return scriptEnd(src, from)
|
|
63
63
|
if (RAW.has(name)) {
|
|
64
|
-
const close = new RegExp(`</${name}(?=[\\s/>])
|
|
64
|
+
const close = new RegExp(`</${name}(?=[\\s/>])`, "gi")
|
|
65
65
|
close.lastIndex = from
|
|
66
66
|
const match = close.exec(src)
|
|
67
|
-
return match ? match.index +
|
|
67
|
+
return match ? readTag(src, match.index + 2).end : src.length
|
|
68
68
|
}
|
|
69
69
|
let depth = 0
|
|
70
70
|
let stop = src.length
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// html-text-map.mjs - the reader-visible text of a page, with a source map back into the markup.
|
|
2
|
+
//
|
|
3
|
+
// extractHtml(html) returns { root, text, blocks, starts, ends }: `text` is one line per block
|
|
4
|
+
// (prose blocks and table cells; whitespace collapsed, entities decoded) and text unit k came from
|
|
5
|
+
// html.slice(starts[k], ends[k]). Only text nodes are read: attribute values, CSS, scripts, and
|
|
6
|
+
// anything a reader never sees (head, script, style, svg, noscript, template, code-like elements,
|
|
7
|
+
// aria-hidden="true" and their descendants, and what the page's CSS hides: css-hiding.mjs)
|
|
8
|
+
// contribute nothing, so a locator over `text` can never land in markup. A synthetic separator
|
|
9
|
+
// (collapsed break, line feed) maps to an empty range at the previous character's end.
|
|
10
|
+
// Plain Node ESM, sibling imports only.
|
|
11
|
+
|
|
12
|
+
import { cssVisibility } from "./css-hiding.mjs"
|
|
13
|
+
import { decodeOne } from "./entities.mjs"
|
|
14
|
+
import { parseHtml, PROSE_BREAKS, PROSE_TAGS } from "./html-lite.mjs"
|
|
15
|
+
|
|
16
|
+
const SKIP = new Set(["head", "script", "style", "svg", "code", "pre", "kbd", "samp", "template", "noscript"])
|
|
17
|
+
const INLINE = new Set([
|
|
18
|
+
"a", "abbr", "b", "bdi", "bdo", "cite", "data", "del", "dfn", "em", "font", "i", "ins", "label", "mark", "q", "s",
|
|
19
|
+
"small", "span", "strong", "sub", "sup", "time", "u", "var",
|
|
20
|
+
])
|
|
21
|
+
const SPACE = /\s/
|
|
22
|
+
|
|
23
|
+
/** null when a reader never sees the element or anything inside it, else whether its own text shows (css: cssVisibility). */
|
|
24
|
+
function shownState(node, css, parentShown) {
|
|
25
|
+
if (SKIP.has(node.tag) || String(node.attrs?.["aria-hidden"] ?? "").trim().toLowerCase() === "true") return null
|
|
26
|
+
return css(node, parentShown)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function newLine() {
|
|
30
|
+
return { node: null, text: "", starts: [], ends: [], space: null }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function put(line, unit, start, end) {
|
|
34
|
+
if (SPACE.test(unit)) {
|
|
35
|
+
if (line.text !== "" && line.space === null) line.space = [start, end]
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
if (line.space !== null) {
|
|
39
|
+
line.text += " "
|
|
40
|
+
line.starts.push(line.space[0])
|
|
41
|
+
line.ends.push(line.space[1])
|
|
42
|
+
line.space = null
|
|
43
|
+
}
|
|
44
|
+
line.text += unit
|
|
45
|
+
line.starts.push(start)
|
|
46
|
+
line.ends.push(end)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** A collapsible break with no source character of its own. */
|
|
50
|
+
function softBreak(line) {
|
|
51
|
+
if (line.text !== "" && line.space === null) {
|
|
52
|
+
const at = line.ends[line.ends.length - 1]
|
|
53
|
+
line.space = [at, at]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Append a text node's source range, decoding entities exactly as decodeEntities does. */
|
|
58
|
+
function putText(line, src, from, to) {
|
|
59
|
+
for (let at = from; at < to; ) {
|
|
60
|
+
if (src[at] === "&") {
|
|
61
|
+
const semi = src.indexOf(";", at + 1)
|
|
62
|
+
const decoded = semi !== -1 && semi < to && semi - at <= 12 ? decodeOne(src.slice(at + 1, semi)) : null
|
|
63
|
+
if (decoded !== null) {
|
|
64
|
+
for (let k = 0; k < decoded.length; k++) put(line, decoded[k], at, semi + 1)
|
|
65
|
+
at = semi + 1
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
put(line, src[at], at, at + 1)
|
|
70
|
+
at++
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function putProse(line, src, node, css, shown) {
|
|
75
|
+
for (const child of node.children) {
|
|
76
|
+
if (child.tag === "#text") {
|
|
77
|
+
if (shown) putText(line, src, child.source_start, child.source_end)
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
const state = shownState(child, css, shown)
|
|
81
|
+
if (state === null) continue
|
|
82
|
+
const breaks = PROSE_BREAKS.has(child.tag)
|
|
83
|
+
if (breaks) softBreak(line)
|
|
84
|
+
putProse(line, src, child, css, state)
|
|
85
|
+
if (breaks) softBreak(line)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** See the file comment. blocks: [{ node, start, end }] with text.slice(start, end) one block line. */
|
|
90
|
+
export function extractHtml(html) {
|
|
91
|
+
const src = String(html)
|
|
92
|
+
const root = parseHtml(src)
|
|
93
|
+
const css = cssVisibility(root)
|
|
94
|
+
const lines = []
|
|
95
|
+
let line = newLine()
|
|
96
|
+
const flush = (node) => {
|
|
97
|
+
if (line.text !== "") lines.push({ ...line, node })
|
|
98
|
+
line = newLine()
|
|
99
|
+
}
|
|
100
|
+
const walk = (node, shown) => {
|
|
101
|
+
for (const child of node.children) {
|
|
102
|
+
if (child.tag === "#text") {
|
|
103
|
+
if (shown) putText(line, src, child.source_start, child.source_end)
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
const state = shownState(child, css, shown)
|
|
107
|
+
if (state === null) continue
|
|
108
|
+
if (child.tag === "br") flush(node)
|
|
109
|
+
else if (INLINE.has(child.tag)) walk(child, state)
|
|
110
|
+
else if (PROSE_TAGS.has(child.tag)) {
|
|
111
|
+
flush(node)
|
|
112
|
+
putProse(line, src, child, css, state)
|
|
113
|
+
flush(child)
|
|
114
|
+
} else {
|
|
115
|
+
flush(node)
|
|
116
|
+
walk(child, state)
|
|
117
|
+
flush(child)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
walk(root, true)
|
|
122
|
+
flush(root)
|
|
123
|
+
const blocks = []
|
|
124
|
+
const starts = []
|
|
125
|
+
const ends = []
|
|
126
|
+
let text = ""
|
|
127
|
+
for (const entry of lines) {
|
|
128
|
+
if (text !== "") {
|
|
129
|
+
const at = ends[ends.length - 1]
|
|
130
|
+
text += "\n"
|
|
131
|
+
starts.push(at)
|
|
132
|
+
ends.push(at)
|
|
133
|
+
}
|
|
134
|
+
blocks.push({ node: entry.node, start: text.length, end: text.length + entry.text.length })
|
|
135
|
+
text += entry.text
|
|
136
|
+
starts.push(...entry.starts)
|
|
137
|
+
ends.push(...entry.ends)
|
|
138
|
+
}
|
|
139
|
+
return { root, text, blocks, starts, ends }
|
|
140
|
+
}
|