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
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// markdown-closers.mjs - the Markdown closer runs a converter writes after a piece of text, read with
|
|
2
|
+
// the CommonMark inline grammar instead of a hand-written pattern. A closer run is any sequence of:
|
|
3
|
+
// an inline link ending `](dest "title")` (the destination either in <...> or bare with balanced
|
|
4
|
+
// parentheses, the optional title in "...", '...' or (...), backslash escapes inside both), a full or
|
|
5
|
+
// collapsed reference ending `][ref]` / `][]`, a whole image `` or `![alt][ref]` (its alt
|
|
6
|
+
// text is not context), the `[` that opened a link whose text is all markup (`[](/p)`),
|
|
7
|
+
// an emphasis, strike or code delimiter, a bare `)`, `]` or `>`, and a backslash-escaped closer
|
|
8
|
+
// (`\*`, `\_`, `\]`, `\)`, `\~`, a backtick), which stands for the raw character and is skipped like
|
|
9
|
+
// it. An escaped opener (`\[`, `\(`) is a real character and ends the run. Shared by the conversion
|
|
10
|
+
// probe's sign reading and its link-syntax spans. Pure; no imports.
|
|
11
|
+
|
|
12
|
+
const SIMPLE = new Set(["*", "_", "~", "`", ")", "]", ">"])
|
|
13
|
+
const BREAK = "\u0001"
|
|
14
|
+
|
|
15
|
+
/** Whether the character at `index` is backslash-escaped (an odd run of backslashes before it). */
|
|
16
|
+
export function escapedAt(text, index) {
|
|
17
|
+
let count = 0
|
|
18
|
+
for (let i = index - 1; i >= 0 && text[i] === "\\"; i--) count++
|
|
19
|
+
return count % 2 === 1
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The end (exclusive) of an inline link target `dest "title")` that starts right after its "(", or -1. */
|
|
23
|
+
export function inlineTargetEnd(text, from) {
|
|
24
|
+
let i = from
|
|
25
|
+
const space = () => {
|
|
26
|
+
while (text[i] === " " || text[i] === "\t") i++
|
|
27
|
+
}
|
|
28
|
+
space()
|
|
29
|
+
if (text[i] === "<") {
|
|
30
|
+
for (i++; i < text.length && text[i] !== ">"; i++) {
|
|
31
|
+
if (text[i] === "\\") i++
|
|
32
|
+
else if (text[i] === "<" || text[i] === BREAK) return -1
|
|
33
|
+
}
|
|
34
|
+
if (text[i++] !== ">") return -1
|
|
35
|
+
} else {
|
|
36
|
+
let depth = 0
|
|
37
|
+
for (; i < text.length; i++) {
|
|
38
|
+
const ch = text[i]
|
|
39
|
+
if (ch === "\\") i++
|
|
40
|
+
else if (ch === "(") depth++
|
|
41
|
+
else if (ch === ")" && depth === 0) break
|
|
42
|
+
else if (ch === ")") depth--
|
|
43
|
+
else if (ch === " " || ch === "\t" || ch === BREAK) break
|
|
44
|
+
}
|
|
45
|
+
if (depth !== 0) return -1
|
|
46
|
+
}
|
|
47
|
+
const destEnd = i
|
|
48
|
+
space()
|
|
49
|
+
const open = text[i]
|
|
50
|
+
if (i > destEnd && (open === '"' || open === "'" || open === "(")) {
|
|
51
|
+
const close = open === "(" ? ")" : open
|
|
52
|
+
for (i++; i < text.length && text[i] !== close; i++) {
|
|
53
|
+
if (text[i] === "\\") i++
|
|
54
|
+
else if (text[i] === BREAK || (open === "(" && text[i] === "(")) return -1
|
|
55
|
+
}
|
|
56
|
+
if (text[i++] !== close) return -1
|
|
57
|
+
space()
|
|
58
|
+
}
|
|
59
|
+
return text[i] === ")" ? i + 1 : -1
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The unescaped "[" that the unescaped "]" at `close` closes (brackets balance), or -1. */
|
|
63
|
+
function openerOf(text, close) {
|
|
64
|
+
let depth = 0
|
|
65
|
+
for (let i = close; i >= 0 && text[i] !== BREAK; i--) {
|
|
66
|
+
if ((text[i] !== "[" && text[i] !== "]") || escapedAt(text, i)) continue
|
|
67
|
+
depth += text[i] === "]" ? 1 : -1
|
|
68
|
+
if (depth === 0) return i
|
|
69
|
+
}
|
|
70
|
+
return -1
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** The "](" positions whose inline target ends exactly at `end`, leftmost first (so a title holding "](" is not cut). */
|
|
74
|
+
function inlineLinkClose(text, end) {
|
|
75
|
+
const from = Math.max(0, text.lastIndexOf(BREAK, end - 1))
|
|
76
|
+
for (let k = text.indexOf("](", from); k !== -1 && k < end; k = text.indexOf("](", k + 1)) {
|
|
77
|
+
if (!escapedAt(text, k) && inlineTargetEnd(text, k + 2) === end) return k
|
|
78
|
+
}
|
|
79
|
+
return -1
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Where the link or image tail ending at `end` starts, and whether its "[" is still open; null when none ends there. */
|
|
83
|
+
function linkTail(text, end) {
|
|
84
|
+
let close = -1
|
|
85
|
+
if (text[end - 1] === ")") close = inlineLinkClose(text, end)
|
|
86
|
+
else if (text[end - 1] === "]" && !escapedAt(text, end - 1)) {
|
|
87
|
+
const ref = openerOf(text, end - 1)
|
|
88
|
+
if (ref > 0 && text[ref - 1] === "]" && !escapedAt(text, ref - 1)) close = ref - 1
|
|
89
|
+
}
|
|
90
|
+
if (close === -1) return null
|
|
91
|
+
const open = openerOf(text, close)
|
|
92
|
+
if (open > 0 && text[open - 1] === "!" && !escapedAt(text, open - 1)) return { start: open - 1, opened: 0 }
|
|
93
|
+
return { start: close, opened: open === -1 ? 0 : 1 }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** `text` without the Markdown closer run it ends with. */
|
|
97
|
+
export function stripClosers(text) {
|
|
98
|
+
let end = text.length
|
|
99
|
+
let owed = 0
|
|
100
|
+
for (;;) {
|
|
101
|
+
const tail = linkTail(text, end)
|
|
102
|
+
if (tail) {
|
|
103
|
+
end = tail.start
|
|
104
|
+
owed += tail.opened
|
|
105
|
+
continue
|
|
106
|
+
}
|
|
107
|
+
const ch = text[end - 1]
|
|
108
|
+
if (SIMPLE.has(ch)) end -= escapedAt(text, end - 1) ? 2 : 1
|
|
109
|
+
else if (ch === "[" && owed > 0 && !escapedAt(text, end - 1)) {
|
|
110
|
+
end--
|
|
111
|
+
owed--
|
|
112
|
+
} else return text.slice(0, end)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** [start, end) spans of every inline link or image with its target (an image from its "!"), for link-syntax cover. */
|
|
117
|
+
export function inlineLinkSpans(text) {
|
|
118
|
+
const spans = []
|
|
119
|
+
for (let k = text.indexOf("]("); k !== -1; k = text.indexOf("](", k + 1)) {
|
|
120
|
+
const end = escapedAt(text, k) ? -1 : inlineTargetEnd(text, k + 2)
|
|
121
|
+
if (end === -1) continue
|
|
122
|
+
const open = openerOf(text, k)
|
|
123
|
+
spans.push([open > 0 && text[open - 1] === "!" ? open - 1 : k, end])
|
|
124
|
+
}
|
|
125
|
+
return spans
|
|
126
|
+
}
|
|
@@ -113,7 +113,7 @@ export function parseMarkdown(text) {
|
|
|
113
113
|
const codeStart = Math.min(line.next, source.length)
|
|
114
114
|
let close = lines.length
|
|
115
115
|
for (let k = i + 1; k < lines.length; k++) {
|
|
116
|
-
const candidate = lines[k].raw.
|
|
116
|
+
const candidate = lines[k].raw.replace(/^ {0,3}/, "").trimEnd()
|
|
117
117
|
if (candidate.startsWith(open[0].repeat(open.length)) && /^(`+|~+)$/.test(candidate)) {
|
|
118
118
|
close = k
|
|
119
119
|
break
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// number-grammar.mjs - the one grouped-number grammar. A grouped number is a 1-3 digit leading
|
|
2
|
+
// group, then one or more 3-digit groups joined by ONE separator type, with no digit right after the
|
|
3
|
+
// last group, then an optional decimal part. "12,3451" is therefore not "12,345" plus "1". A period
|
|
4
|
+
// groups only when the reading is unambiguous: two or more period groups ("1.234.567") or one group
|
|
5
|
+
// before a decimal comma ("1.234,5"); a lone "1.234" is a decimal, as numerals.mjs reads it. Shared by
|
|
6
|
+
// numerals.mjs (comma grouping), the conversion probe (every separator), the value-mode unit check,
|
|
7
|
+
// and the converted-half display check. Pure; no imports.
|
|
8
|
+
|
|
9
|
+
/** Separators a thousands group may use: comma, period, space, NBSP, narrow NBSP, thin space, figure space. */
|
|
10
|
+
export const GROUP_SEPARATORS = Object.freeze([",", ".", " ", "\u00A0", "\u202F", "\u2009", "\u2007"])
|
|
11
|
+
|
|
12
|
+
const literal = (sep) => (sep === "." ? "\\." : sep === " " ? " " : sep === "," ? "," : `\\u${sep.charCodeAt(0).toString(16).padStart(4, "0")}`)
|
|
13
|
+
const decimalAfter = (sep) => (sep === "," ? "\\." : sep === "." ? "," : "[.,]")
|
|
14
|
+
|
|
15
|
+
/** Regex source of one grouped number using any of `separators` (one type per number); no flags needed. */
|
|
16
|
+
export function groupedNumberSource(separators = GROUP_SEPARATORS) {
|
|
17
|
+
const one = (sep) => sep === "."
|
|
18
|
+
? "\\d{1,3}(?:(?:\\.\\d{3}(?!\\d)){2,}(?:,\\d+)?|\\.\\d{3}(?!\\d),\\d+)"
|
|
19
|
+
: `\\d{1,3}(?:${literal(sep)}\\d{3}(?!\\d))+(?:${decimalAfter(sep)}\\d+)?`
|
|
20
|
+
return `(?<!\\d)(?:${separators.map(one).join("|")})`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** A grouped number or a plain one ("4.22", "12,3451" read as 12.3451), as regex source. */
|
|
24
|
+
export const NUMBER_SOURCE = `(?:${groupedNumberSource()}|(?<!\\d)\\d+(?:[.,]\\d+)?)`
|
|
25
|
+
|
|
26
|
+
const WHOLE = new Map(GROUP_SEPARATORS.map((sep) => [sep, new RegExp(`^${groupedNumberSource([sep])}$`)]))
|
|
27
|
+
|
|
28
|
+
/** The plain decimal a number token spells: group separators dropped, a decimal comma read as a point. */
|
|
29
|
+
export function plainDecimal(token) {
|
|
30
|
+
const sep = GROUP_SEPARATORS.find((candidate) => WHOLE.get(candidate).test(token))
|
|
31
|
+
const ungrouped = sep === undefined ? token : token.split(sep).join("")
|
|
32
|
+
return ungrouped.replace(",", ".")
|
|
33
|
+
}
|
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
// English number words one to twelve, an adjacent currency symbol or unit, and an adjacent bounding
|
|
7
7
|
// qualifier. No numeral is ever passed through Number(). Plain Node ESM, sibling imports only.
|
|
8
8
|
|
|
9
|
+
import { groupedNumberSource } from "./number-grammar.mjs"
|
|
9
10
|
import { add, fromDecimal, mul, toDecimal } from "./rational.mjs"
|
|
10
11
|
import { normalizeUnit } from "./units.mjs"
|
|
11
12
|
|
|
13
|
+
/** European digit grouping ("1.234.567"): two or more dot groups of three digits, never a version. */
|
|
14
|
+
export const DOT_GROUPED = "\\d{1,3}(?:\\.\\d{3}){2,}"
|
|
12
15
|
const MONTH = "(?:jan|feb|mar|apr|may|jun|jul|aug|sep|sept|oct|nov|dec)[a-z]*\\.?"
|
|
13
16
|
/** Stripped before claim detection: dates, versions, figure refs, times, bare years. */
|
|
14
17
|
export const NOT_CLAIMS = [
|
|
@@ -19,7 +22,7 @@ export const NOT_CLAIMS = [
|
|
|
19
22
|
/(?:19|20)\d{2}\s*\uB144/g,
|
|
20
23
|
new RegExp(`\\b${MONTH}\\s+\\d{1,2}(?:st|nd|rd|th)?(?:,?\\s+\\d{4})?`, "gi"),
|
|
21
24
|
new RegExp(`\\b\\d{1,2}(?:st|nd|rd|th)?\\s+${MONTH}(?:\\s+\\d{4})?`, "gi"),
|
|
22
|
-
|
|
25
|
+
new RegExp(`\\bv\\d+(?:\\.\\d+)*\\b|\\b(?!${DOT_GROUPED}(?![\\d,]|\\.\\d))\\d+(?:\\.\\d+){2,}\\b`, "gi"),
|
|
23
26
|
/\b(?:version|ver\.?|release)\s*\d+(?:\.\d+)*/gi,
|
|
24
27
|
/\b(?:fig(?:ure)?\.?|table|chart|section|step|phase|wave|part)\s*\d+(?:\.\d+)*/gi,
|
|
25
28
|
/(?:\uADF8\uB9BC|\uB3C4\uD45C|\uD45C|\uBC84\uC804)\s*\d+(?:\.\d+)*/g,
|
|
@@ -45,8 +48,8 @@ const BIG = new Map([["\uB9CC", 10000n], ["\uC5B5", 100000000n], ["\uC870", 1000
|
|
|
45
48
|
/** A scale word that starts a longer word is not a scale: jogak (pieces), mankeum (as much as). */
|
|
46
49
|
const KO_GROUP = /^(\s?)(?:(\uCC9C)?([\uB9CC\uC5B5\uC870])|(\uCC9C))(?![\uAC01\uD07C])/
|
|
47
50
|
const KO_NEXT = new RegExp(`^\\s?(${NUM})(\uCC9C)?([\uB9CC\uC5B5\uC870])?`, "u")
|
|
48
|
-
const LATIN_SCALE = /^(?:(k|K|M|bn|B)|\s(thousand|million|billion|trillion|bn))(?![\p{L}\d])/u
|
|
49
|
-
const LATIN_FACTOR = { k: 1000n, K: 1000n, M: 1000000n, bn: 1000000000n, B: 1000000000n, thousand: 1000n, million: 1000000n, billion: 1000000000n, trillion: 1000000000000n }
|
|
51
|
+
const LATIN_SCALE = /^(?:(k|K|M|mn|bn|B)|\s(thousand|million|billion|trillion|mn|bn))(?![\p{L}\d])/u
|
|
52
|
+
const LATIN_FACTOR = { k: 1000n, K: 1000n, M: 1000000n, mn: 1000000n, bn: 1000000000n, B: 1000000000n, thousand: 1000n, million: 1000000n, billion: 1000000000n, trillion: 1000000000000n }
|
|
50
53
|
const CURRENCY = "$\u20AC\u00A3\u00A5\u20A9"
|
|
51
54
|
const SYMBOL_UNIT = /^\s?(%p|%|\u2030|\u00D7|\u00B0C|\u00B0F|\u2103|\u2109)/
|
|
52
55
|
const LATIN_UNIT = /^\s?([A-Za-z]+)(?![\p{L}\d])/u
|
|
@@ -60,15 +63,23 @@ const RANGE_SEP = /^(?:\s?[-\u2013~]\s?|\sto\s)/
|
|
|
60
63
|
const SIGN = "-\u2212"
|
|
61
64
|
/** Bounding qualifiers: before the value (Korean and English) and right after it (Korean). */
|
|
62
65
|
const QUALIFIERS_BEFORE = ["up to", "at least", "at most", "more than", "less than", "about", "approximately", "nearly", "over", "under", "\uCD5C\uB300", "\uCD5C\uC18C", "\uC57D"]
|
|
63
|
-
|
|
66
|
+
/** Korean bounding qualifiers written right after a value (isang, iha, miman, chogwa, naeoe, kkaji). */
|
|
67
|
+
export const QUALIFIERS_AFTER = Object.freeze(["\uC774\uC0C1", "\uC774\uD558", "\uBBF8\uB9CC", "\uCD08\uACFC", "\uB0B4\uC678", "\uAE4C\uC9C0"])
|
|
68
|
+
const QUALIFIER_AFTER = new RegExp(`^\\s?(${QUALIFIERS_AFTER.join("|")})`)
|
|
64
69
|
|
|
65
|
-
/**
|
|
70
|
+
/** Comma grouping from the one grouped-number grammar (number-grammar.mjs). */
|
|
71
|
+
const COMMA_GROUPED = new RegExp(`^${groupedNumberSource([","])}$`)
|
|
72
|
+
|
|
73
|
+
/** "1,237" -> "1237"; a malformed group ("1,23", "12,3451") keeps only the leading plain number. */
|
|
66
74
|
function cleanDigits(raw) {
|
|
67
|
-
if (
|
|
75
|
+
if (COMMA_GROUPED.test(raw)) return { digits: raw.replace(/,/g, ""), length: raw.length }
|
|
68
76
|
const plain = /^\d+(?:\.\d+)?/.exec(raw)[0]
|
|
69
77
|
return { digits: plain, length: plain.length }
|
|
70
78
|
}
|
|
71
79
|
|
|
80
|
+
/** A numeral's digits, reading a European period grouping ("1.234.567") as one integer. */
|
|
81
|
+
const digitsOf = (raw) => (new RegExp(`^${DOT_GROUPED}$`).test(raw) ? { digits: raw.replace(/\./g, ""), length: raw.length } : cleanDigits(raw))
|
|
82
|
+
|
|
72
83
|
/** The bare-year and four-digit-date patterns: a numeral they cover can still be a value. */
|
|
73
84
|
const YEAR_SHAPED = new Set([NOT_CLAIMS[0], NOT_CLAIMS[12]])
|
|
74
85
|
|
|
@@ -95,7 +106,7 @@ function findStart(text, from, ranges) {
|
|
|
95
106
|
let digit = null
|
|
96
107
|
for (const match of text.slice(from).matchAll(new RegExp(NUM, "gu"))) {
|
|
97
108
|
const at = from + match.index
|
|
98
|
-
const candidate = { at, ...
|
|
109
|
+
const candidate = { at, ...digitsOf(match[0]) }
|
|
99
110
|
const end = at + candidate.length
|
|
100
111
|
const cover = covering(at)
|
|
101
112
|
const lifted = cover.every(([s, e, yearShaped]) => yearShaped && s === at && e <= end)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// outcome-start.mjs - the run clock (outcome.json startedAt). `outcome init` is its one writer and
|
|
2
|
+
// records it once: --started-at from the orchestrator, else the startedAt of a valid manifest an
|
|
3
|
+
// earlier init wrote (a re-init keeps the clock), else terminal-state.json.started_at when a
|
|
4
|
+
// supervisor wrote one, else the YYYYMMDD-HHMMSS session dir name. A recorded value must be a real
|
|
5
|
+
// ISO time with Z or an offset, not after `now`, and within a day of a stamped dir name; otherwise
|
|
6
|
+
// init refuses instead of falling back. Never the interview's as-of date. No clock reads.
|
|
7
|
+
import { readFileSync } from "node:fs"
|
|
8
|
+
import { basename, join, resolve } from "node:path"
|
|
9
|
+
|
|
10
|
+
const ISO = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-](\d{2}):(\d{2}))$/
|
|
11
|
+
const SESSION_STAMP = /^(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})(\d{2})$/
|
|
12
|
+
const DAY_MS = 86_400_000
|
|
13
|
+
|
|
14
|
+
/** A real calendar time (no 2026-02-30, no T24:00), or null. */
|
|
15
|
+
function strictIso(value) {
|
|
16
|
+
const match = typeof value === "string" ? ISO.exec(value) : null
|
|
17
|
+
if (!match) return null
|
|
18
|
+
const [y, mo, d, h, mi, s, oh = 0, om = 0] = match.slice(1).map((part) => Number(part ?? 0))
|
|
19
|
+
const day = new Date(Date.UTC(y, mo - 1, d))
|
|
20
|
+
if (day.getUTCMonth() !== mo - 1 || day.getUTCDate() !== d || h > 23 || mi > 59 || s > 59 || oh > 23 || om > 59) return null
|
|
21
|
+
const date = new Date(value)
|
|
22
|
+
return Number.isNaN(date.getTime()) ? null : date
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Local start time from a YYYYMMDD-HHMMSS dir name, null when the name is not a stamp. */
|
|
26
|
+
function dirStamp(sessionDir, fail) {
|
|
27
|
+
const match = SESSION_STAMP.exec(basename(sessionDir))
|
|
28
|
+
if (!match) return null
|
|
29
|
+
const [y, mo, d, h, mi, s] = match.slice(1).map(Number)
|
|
30
|
+
const date = new Date(y, mo - 1, d, h, mi, s)
|
|
31
|
+
if (date.getMonth() !== mo - 1 || date.getDate() !== d || date.getHours() !== h) fail(`session dir basename is not a real local time: ${sessionDir}`)
|
|
32
|
+
return date
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function readJson(sessionDir, file) {
|
|
36
|
+
try {
|
|
37
|
+
return { data: JSON.parse(readFileSync(join(sessionDir, file), "utf8")) }
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (error.code === "ENOENT" || error.code === "ENOTDIR") return null
|
|
40
|
+
if (error instanceof SyntaxError) return { corrupt: `${join(sessionDir, file)} is not valid JSON (${error.message})` }
|
|
41
|
+
throw error
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {{ sessionDir: string, startedAt?: string, now?: Date, validManifest: (data: unknown) => boolean, fail: (message: string) => never }} input
|
|
47
|
+
* @returns {Date}
|
|
48
|
+
*/
|
|
49
|
+
export function runStart({ sessionDir, startedAt, now, validManifest, fail }) {
|
|
50
|
+
const dir = dirStamp(sessionDir, fail)
|
|
51
|
+
const check = (value, location) => {
|
|
52
|
+
const date = strictIso(value)
|
|
53
|
+
if (!date) fail(`invalid run timestamp in ${location}: ${JSON.stringify(value)} is not a real ISO time with Z or an offset`)
|
|
54
|
+
if (now && date > now) fail(`run timestamp in ${location} (${value}) is after now (${now.toISOString()})`)
|
|
55
|
+
if (dir && Math.abs(date - dir) > DAY_MS) fail(`run timestamp in ${location} (${value}) is not within a day of the session dir name ${basename(sessionDir)}: a copied or stale value`)
|
|
56
|
+
return date
|
|
57
|
+
}
|
|
58
|
+
if (startedAt !== undefined) return check(startedAt, "--started-at")
|
|
59
|
+
const manifest = readJson(sessionDir, "outcome.json")
|
|
60
|
+
if (manifest?.data && validManifest(manifest.data) && resolve(String(manifest.data.sessionDir)) === resolve(sessionDir)) return check(manifest.data.startedAt, "outcome.json.startedAt")
|
|
61
|
+
const terminal = readJson(sessionDir, "terminal-state.json")
|
|
62
|
+
if (terminal?.corrupt) fail(terminal.corrupt)
|
|
63
|
+
if (terminal?.data?.started_at !== undefined) return check(terminal.data.started_at, "terminal-state.json.started_at")
|
|
64
|
+
if (dir) return dir
|
|
65
|
+
return fail(`missing run timestamp: pass --started-at <ISO>, record terminal-state.json.started_at, or name the session dir YYYYMMDD-HHMMSS (${sessionDir})`)
|
|
66
|
+
}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
// outcome.mjs - the per-run outcome manifest (`outcome.json`) and the closing briefing. Manifest functions are pure (they return a new manifest).
|
|
2
2
|
// The briefing reads only the manifest, the sources-ledger text, and an injected `now`. node: builtins only.
|
|
3
|
-
|
|
4
3
|
import * as nodeFs from "node:fs"
|
|
5
4
|
import { basename, dirname, join } from "node:path"
|
|
6
5
|
|
|
7
6
|
import { DELIVERABLE_FORMATS, DELIVERABLE_STATUSES, GATE_NAMES, GATE_STATUSES, LANES, MANIFEST_CODES, normalizeManifest, SCHEMA_VERSION, validateOutcomeManifest } from "./contracts.mjs"
|
|
7
|
+
import { runStart } from "./outcome-start.mjs"
|
|
8
8
|
|
|
9
9
|
export const MANIFEST_FILENAME = "outcome.json"
|
|
10
10
|
const MISSING = MANIFEST_CODES[0]
|
|
11
|
-
const SESSION_STAMP = /^(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})(\d{2})$/
|
|
12
11
|
const SOURCE_LINE = /^\[(S|Source )\d+\]/
|
|
13
12
|
const URL_PATTERN = /https?:\/\/[^\s)<>\]"'`]+/g
|
|
14
13
|
const DRAFT_MARKER = "STATUS: draft"
|
|
@@ -33,26 +32,20 @@ function assertOneOf(code, label, value, allowed) {
|
|
|
33
32
|
|
|
34
33
|
const clone = (manifest) => structuredClone(manifest)
|
|
35
34
|
const isMissing = (error) => error?.code === "ENOENT" || error?.code === "ENOTDIR"
|
|
36
|
-
|
|
37
35
|
function stamp(now) {
|
|
38
36
|
return (now ?? new Date()).toISOString()
|
|
39
37
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!match) throw new OutcomeError("invalid_session_dir", `session dir basename must be YYYYMMDD-HHMMSS: ${sessionDir}`)
|
|
45
|
-
const [y, mo, d, h, mi, s] = match.slice(1).map(Number)
|
|
46
|
-
const date = new Date(y, mo - 1, d, h, mi, s)
|
|
47
|
-
if (date.getMonth() !== mo - 1 || date.getDate() !== d || date.getHours() !== h) {
|
|
48
|
-
throw new OutcomeError("invalid_session_dir", `session dir basename is not a real local time: ${sessionDir}`)
|
|
38
|
+
/** The run clock outcome init records (outcome-start.mjs owns the contract). */
|
|
39
|
+
export function parseSessionStart(sessionDir, { startedAt, now } = {}) {
|
|
40
|
+
const fail = (message) => {
|
|
41
|
+
throw new OutcomeError("invalid_session_dir", message)
|
|
49
42
|
}
|
|
50
|
-
return
|
|
43
|
+
return runStart({ sessionDir, startedAt, now, validManifest: (data) => validateOutcomeManifest(normalizeManifest(data)).ok, fail })
|
|
51
44
|
}
|
|
52
45
|
|
|
53
|
-
/** @param {{ sessionDir: string, promised: string[], lane: string|null, interview?: object|null, now?: Date }} input */
|
|
54
|
-
export function initManifest({ sessionDir, promised, lane, interview = null, now }) {
|
|
55
|
-
const startedAt = parseSessionStart(sessionDir).toISOString()
|
|
46
|
+
/** @param {{ sessionDir: string, promised: string[], lane: string|null, interview?: object|null, now?: Date, startedAt?: string }} input */
|
|
47
|
+
export function initManifest({ sessionDir, promised, lane, interview = null, now, startedAt: recorded }) {
|
|
48
|
+
const startedAt = parseSessionStart(sessionDir, { startedAt: recorded, now }).toISOString()
|
|
56
49
|
if (lane !== null && lane !== undefined) assertOneOf("unknown_lane", "lane", lane, LANES)
|
|
57
50
|
const formats = [...new Set(promised)]
|
|
58
51
|
for (const format of formats) assertOneOf("unknown_format", "deliverable format", format, DELIVERABLE_FORMATS)
|
|
@@ -74,9 +67,7 @@ export function initManifest({ sessionDir, promised, lane, interview = null, now
|
|
|
74
67
|
}
|
|
75
68
|
}
|
|
76
69
|
|
|
77
|
-
/**
|
|
78
|
-
* Set one format's row; every other row is kept as is. An unpromised format gets a new
|
|
79
|
-
* row with promised=false. The row's detail fields are replaced by the ones given.
|
|
70
|
+
/** Set one format's row, keeping other rows. New formats have promised=false.
|
|
80
71
|
* @param {{ path?: string, reason?: string, pages?: number, bytes?: number, now?: Date }} [detail]
|
|
81
72
|
*/
|
|
82
73
|
export function setDeliverable(manifest, format, status, detail = {}) {
|
|
@@ -143,9 +134,7 @@ export function verifyManifest(manifest, fs = nodeFs) {
|
|
|
143
134
|
return { ok: problems.length === 0, problems }
|
|
144
135
|
}
|
|
145
136
|
|
|
146
|
-
/**
|
|
147
|
-
* none = missing or empty file; partial = `STATUS: draft` in the first 5 lines, or the
|
|
148
|
-
* manifest (given, else a sibling outcome.json) still has a pending row; else complete.
|
|
137
|
+
/** Missing/empty = none; draft marker or pending manifest = partial; else complete.
|
|
149
138
|
* @returns {"none"|"partial"|"complete"}
|
|
150
139
|
*/
|
|
151
140
|
export function deliverableState(deliverablePath, manifestOrNull) {
|