oh-my-opencode 5.1.47 → 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 -259
- package/dist/skills/ulw-research/references/deliverable-phase.md +68 -24
- 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 +14 -6
- 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 +16 -15
- package/dist/skills/ulw-research/scripts/contracts.test.ts +6 -109
- 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-fidelity-policy.test.ts +156 -0
- package/dist/skills/ulw-research/scripts/copy-returns-polish.test.ts +10 -9
- 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 +96 -0
- package/dist/skills/ulw-research/scripts/fact-commands-meaning.mjs +26 -30
- package/dist/skills/ulw-research/scripts/fact-commands-polish.mjs +46 -19
- package/dist/skills/ulw-research/scripts/fact-commands-verify.mjs +37 -6
- package/dist/skills/ulw-research/scripts/fact-commands.mjs +40 -62
- 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 +9 -6
- 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 +183 -0
- 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 +6 -560
- package/dist/skills/ulw-research/scripts/snapshot-readability.test.ts +116 -0
- package/dist/skills/ulw-research/scripts/source-commands.mjs +87 -29
- 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 -259
- package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +68 -24
- 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 +14 -6
- 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 +16 -15
- 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 +96 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-meaning.mjs +26 -30
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-polish.mjs +46 -19
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-verify.mjs +37 -6
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands.mjs +40 -62
- 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 +9 -6
- 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 +183 -0
- 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 +87 -29
- 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 -259
- package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +68 -24
- 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 +14 -6
- 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 +16 -15
- package/packages/shared-skills/skills/ulw-research/scripts/contracts.test.ts +6 -109
- 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-fidelity-policy.test.ts +156 -0
- package/packages/shared-skills/skills/ulw-research/scripts/copy-returns-polish.test.ts +10 -9
- 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 +96 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-meaning.mjs +26 -30
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-polish.mjs +46 -19
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-verify.mjs +37 -6
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands.mjs +40 -62
- 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 +9 -6
- 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 +183 -0
- 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 +6 -560
- 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 +87 -29
- 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
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// conversion-probe.mjs - numeric multiset differences after source conversion.
|
|
2
|
+
// Inline markup may split one number; superscripts must not merge into it. Numbers are read with the
|
|
3
|
+
// one grouped-number grammar (number-grammar.mjs). A cell, row, list-item, block or line break is a
|
|
4
|
+
// hard boundary: a space never groups digits across it. A sign counts when no Latin, Greek or
|
|
5
|
+
// Cyrillic letter, digit or underscore touches it (an en dash before a digit is a minus too), and a
|
|
6
|
+
// "-" or U+2212 counts after ONE such letter ("\u0394\u22125") or after an exponent ("1e-5"); a run of
|
|
7
|
+
// two or more ("cite_note-7", "AB-12", "UTF-8", "2019-2023") is an identifier or range and carries no
|
|
8
|
+
// negative. Markdown markup a converter writes beside a sign never decides it: the closer run before it
|
|
9
|
+
// (read with the CommonMark inline grammar in markdown-closers.mjs: emphasis, code, strike, titled and
|
|
10
|
+
// parenthesised link and image targets, reference endings, backslash-escaped closers) is skipped to
|
|
11
|
+
// the first character it closes ("**2019**-2023" and '[1990](/wiki/1990 "1990")-2000' are ranges), and
|
|
12
|
+
// an opener run between the sign and its digits ("-**5**") keeps the sign. A raw-side character
|
|
13
|
+
// reference (`−`, ` `) is decoded on BOTH sides with the one entities.mjs table, so a
|
|
14
|
+
// verbatim copy probes clean. Raw inline HTML a converter leaves in the Markdown (pandoc's gfm writer
|
|
15
|
+
// emits `<sup>`, `<sub>`, `<img ... width=320>`, `<span>`, `<br>`) is read with the html-lite tag
|
|
16
|
+
// reader: sup, sub and break tags are boundaries, as on the raw side, and any other tag or comment is
|
|
17
|
+
// dropped with its attributes, so it is a closer or opener like Markdown markup. Digits a converter
|
|
18
|
+
// writes out from a link target, an image source, alt text, or a title cover a converted number only
|
|
19
|
+
// inside Markdown link or image syntax (`](...)` with any title and balanced parentheses,
|
|
20
|
+
// ``, `<https://...>`, `[ref]: url "title"` with the title on the same or the next line),
|
|
21
|
+
// never in prose; a footnote
|
|
22
|
+
// definition's text ("[^1]: ...") is prose. Converter syntax is not a number: a line-start list marker
|
|
23
|
+
// ("1. ", "2) ", "(3) ", indented or after "> ") is exempt only while the source has an <ol> item with
|
|
24
|
+
// that number and the markers so far do not outnumber the <ol> items (so lazy "1. 1. 1." numbering
|
|
25
|
+
// over three items passes), a numeric reference label ("[x][1]" with its "[1]: url") only while both
|
|
26
|
+
// halves are present, and a footnote definition label ("[^1]:") only while its "[^1]" is used;
|
|
27
|
+
// otherwise each is a candidate. A converter's hard wrap may split a space-grouped number over one line
|
|
28
|
+
// break; the two halves read as one number only when the raw side holds that number and not both
|
|
29
|
+
// halves, so raw "12 345 and 12 and 345" wrapped inside "12 345" reports both halves (it fails safe).
|
|
30
|
+
// The built-in snapshot writes no attribute text, syntax, wraps or tags, and its text is already
|
|
31
|
+
// decoded, so it gets none of these allowances. Constructs outside this grammar are declared out of
|
|
32
|
+
// scope in references/fact-ledger.md: they report as altered (the safe direction).
|
|
33
|
+
|
|
34
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
35
|
+
import { join } from "node:path"
|
|
36
|
+
|
|
37
|
+
import { CliError } from "./cli-support.mjs"
|
|
38
|
+
import { decodeEntities, parseHtml, PROSE_BREAKS, readTag } from "./html-lite.mjs"
|
|
39
|
+
import { escapedAt, inlineLinkSpans, stripClosers } from "./markdown-closers.mjs"
|
|
40
|
+
import { NUMBER_SOURCE, plainDecimal } from "./number-grammar.mjs"
|
|
41
|
+
|
|
42
|
+
const LETTER = "\\p{Script=Latin}\\p{Script=Greek}\\p{Script=Cyrillic}"
|
|
43
|
+
const WORD = new RegExp(`[${LETTER}\\p{N}_]`, "u")
|
|
44
|
+
const ALPHA = new RegExp(`[${LETTER}]`, "u")
|
|
45
|
+
const EXPONENT = new RegExp(`(?<![${LETTER}\\p{N}_.,])\\d+(?:[.,]\\d+)?[eE]$`, "u")
|
|
46
|
+
/** A dash, then any Markdown opener run, then a number; signed() decides whether the dash is a minus. */
|
|
47
|
+
const NUMBERS = new RegExp(`(?:([-\\u2212\\u2013])([*_~\`[]*))?(${NUMBER_SOURCE})`, "gu")
|
|
48
|
+
/** Sup, sub, datetime chunks and every break join no neighbour: neither a digit, a separator, nor whitespace. */
|
|
49
|
+
const BOUNDARY = "\u0001"
|
|
50
|
+
const CARRIED = ["href", "src", "alt", "title"]
|
|
51
|
+
const LIST_MARKER = /(?:^|\u0001)(?: ?>)* ?(?:\d+[.)]|\(\d+\)) /gu
|
|
52
|
+
const REF_USE = /\]\[(\d+)\]/gu
|
|
53
|
+
const REF_DEF = /(?:^|\u0001)(?: ?>)* ?\[(\d+)\]:/gu
|
|
54
|
+
const NOTE_USE = /\[\^(\d+)\](?!:)/gu
|
|
55
|
+
const NOTE_DEF = /(?:^|\u0001)(?: ?>)* ?\[\^(\d+)\]:/gu
|
|
56
|
+
const TITLE = `(?:"[^"\u0001]*"|'[^'\u0001]*'|\\([^)\u0001]*\\))`
|
|
57
|
+
/** A reference definition's title may sit alone on the next line (only whitespace after it). */
|
|
58
|
+
const REF_DEFINITION = `(?:^|\u0001) ?\\[(?!\\^)[^\\]\u0001]+\\]: ?[^\\s\u0001]*(?: ${TITLE}| ?\u0001 ?${TITLE}(?= ?(?:\u0001|$)))?`
|
|
59
|
+
const LINK_SYNTAX = new RegExp(`!\\[[^\\]\u0001]*\\](?:\\([^)\u0001]*\\))?|\\]\\([^)\u0001]*\\)|<https?:\\/\\/[^>\\s\u0001]+>|${REF_DEFINITION}`, "gu")
|
|
60
|
+
const TAG_NAME = /^[a-z][a-z0-9-]*$/u
|
|
61
|
+
/** What a tag leaves in the numeric text on either side: sup, sub and every break join no neighbour. */
|
|
62
|
+
const edgeOf = (tag) => (tag === "sup" || tag === "sub" || PROSE_BREAKS.has(tag) ? BOUNDARY : "")
|
|
63
|
+
|
|
64
|
+
/** Prose text, attribute text and <ol> item numbers of an HTML document; a non-HTML document is prose only. */
|
|
65
|
+
function numericText(source, html) {
|
|
66
|
+
if (!html) return { prose: decodeEntities(source), carried: "", listed: [] }
|
|
67
|
+
const chunks = []
|
|
68
|
+
const carried = []
|
|
69
|
+
const listed = []
|
|
70
|
+
const walk = (node) => {
|
|
71
|
+
if (node.tag === "#text") { chunks.push(node.text.replace(/\s+/gu, " ")); return }
|
|
72
|
+
for (const name of CARRIED) if (node.attrs?.[name] !== undefined) carried.push(node.attrs[name])
|
|
73
|
+
if (node.tag === "ol") {
|
|
74
|
+
const start = /^\s*\d+\s*$/u.test(node.attrs.start ?? "") ? Number(node.attrs.start) : 1
|
|
75
|
+
node.children.filter((child) => child.tag === "li").forEach((_, index) => listed.push(String(start + index)))
|
|
76
|
+
}
|
|
77
|
+
const edge = edgeOf(node.tag)
|
|
78
|
+
chunks.push(edge)
|
|
79
|
+
if (node.tag === "time" && node.attrs.datetime !== undefined) chunks.push(`${BOUNDARY}${node.attrs.datetime}${BOUNDARY}`)
|
|
80
|
+
for (const child of node.children) walk(child)
|
|
81
|
+
chunks.push(edge)
|
|
82
|
+
}
|
|
83
|
+
walk(parseHtml(source))
|
|
84
|
+
return { prose: chunks.join(""), carried: carried.join(BOUNDARY), listed }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Raw inline HTML in converted Markdown: sup, sub and break tags become boundaries, other tags and comments go. */
|
|
88
|
+
function inlineHtml(text) {
|
|
89
|
+
let out = ""
|
|
90
|
+
let kept = 0
|
|
91
|
+
for (let lt = text.indexOf("<"); lt !== -1; lt = text.indexOf("<", Math.max(lt + 1, kept))) {
|
|
92
|
+
const comment = text.startsWith("<!--", lt)
|
|
93
|
+
const name = lt + (text[lt + 1] === "/" ? 2 : 1)
|
|
94
|
+
if (escapedAt(text, lt) || (!comment && !/[a-z]/iu.test(text[name] ?? ""))) continue
|
|
95
|
+
const tag = comment ? null : readTag(text, name)
|
|
96
|
+
const end = comment ? text.indexOf("-->", lt + 4) + 3 : tag.end
|
|
97
|
+
if (end <= lt || (tag && !(TAG_NAME.test(tag.name) && text[end - 1] === ">")) || /\n[ \t\r]*\n/u.test(text.slice(lt, end))) continue
|
|
98
|
+
out += text.slice(kept, lt) + (tag ? edgeOf(tag.name) : "")
|
|
99
|
+
kept = end
|
|
100
|
+
}
|
|
101
|
+
return out + text.slice(kept)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Start offsets of numeric reference labels whose use ("][1]") and definition ("[1]:") are both present,
|
|
106
|
+
* and of footnote definition labels ("[^1]:") whose "[^1]" is used (the use itself mirrors the source).
|
|
107
|
+
*/
|
|
108
|
+
function referenceLabels(flat) {
|
|
109
|
+
const uses = [...flat.matchAll(REF_USE)]
|
|
110
|
+
const defs = [...flat.matchAll(REF_DEF)]
|
|
111
|
+
const used = new Set(uses.map((match) => match[1]))
|
|
112
|
+
const defined = new Set(defs.map((match) => match[1]))
|
|
113
|
+
const paired = [...uses.filter((match) => defined.has(match[1])), ...defs.filter((match) => used.has(match[1]))]
|
|
114
|
+
const noted = new Set([...flat.matchAll(NOTE_USE)].map((match) => match[1]))
|
|
115
|
+
const notes = [...flat.matchAll(NOTE_DEF)].filter((match) => noted.has(match[1]))
|
|
116
|
+
return new Set([...paired, ...notes].map((match) => match.index + match[0].search(/\d/u)))
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Whether the dash at `at` is a minus: Markdown closers (and a backslash escaping the dash) before it are skipped, as is an opener run before a lone letter. */
|
|
120
|
+
function signed(flat, at, dash) {
|
|
121
|
+
const before = stripClosers(flat.slice(Math.max(0, at - 512), escapedAt(flat, at) ? at - 1 : at))
|
|
122
|
+
const last = before.at(-1) ?? ""
|
|
123
|
+
if (!WORD.test(last)) return true
|
|
124
|
+
if (dash === "\u2013") return false
|
|
125
|
+
if (EXPONENT.test(before)) return true
|
|
126
|
+
return ALPHA.test(last) && !WORD.test(before.slice(0, -1).replace(/[*_~`[]+$/u, "").at(-1) ?? "")
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Line breaks become boundaries, then whitespace runs one space; `linked` marks tokens inside link
|
|
131
|
+
* syntax, `marker` a line-start list marker, `label` a paired reference label, `gap` the text since
|
|
132
|
+
* the previous number.
|
|
133
|
+
*/
|
|
134
|
+
function tokensOf(text, { links = false } = {}) {
|
|
135
|
+
const flat = text.replace(/\r\n?|\n|\f/gu, BOUNDARY).replace(/\s+/gu, " ")
|
|
136
|
+
const spans = links ? [...[...flat.matchAll(LINK_SYNTAX)].map((match) => [match.index, match.index + match[0].length]), ...inlineLinkSpans(flat)] : []
|
|
137
|
+
const markers = new Set([...flat.matchAll(LIST_MARKER)].map((match) => match.index + match[0].search(/\d/u)))
|
|
138
|
+
const labels = referenceLabels(flat)
|
|
139
|
+
let previousEnd = 0
|
|
140
|
+
return [...flat.matchAll(NUMBERS)].map((match, n) => {
|
|
141
|
+
const sign = match[1] !== undefined && signed(flat, match.index, match[1])
|
|
142
|
+
const at = sign ? match.index : match.index + match[0].length - match[3].length
|
|
143
|
+
const gap = flat.slice(previousEnd, at)
|
|
144
|
+
previousEnd = match.index + match[0].length
|
|
145
|
+
return {
|
|
146
|
+
n,
|
|
147
|
+
gap,
|
|
148
|
+
text: sign ? match[0] : match[3],
|
|
149
|
+
key: `${sign ? "-" : ""}${plainDecimal(match[3])}`,
|
|
150
|
+
linked: spans.some(([start, end]) => at >= start && at < end),
|
|
151
|
+
marker: markers.has(at),
|
|
152
|
+
label: labels.has(at),
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** The comparison key of one number token, so other tools can match a converted number against a probe record. */
|
|
158
|
+
export const numberKey = (token) => tokensOf(String(token))[0]?.key ?? null
|
|
159
|
+
|
|
160
|
+
/** The numbers in `texts` that the source's conversion probe recorded as altered (sources/<id>/conversion.json). */
|
|
161
|
+
export function alteredIn(sourceDir, texts) {
|
|
162
|
+
const record = join(sourceDir, "conversion.json")
|
|
163
|
+
let altered = []
|
|
164
|
+
if (existsSync(record)) {
|
|
165
|
+
try {
|
|
166
|
+
altered = JSON.parse(readFileSync(record, "utf8")).conversion_altered_numbers ?? []
|
|
167
|
+
} catch (error) {
|
|
168
|
+
throw new CliError(`${record} is not a readable conversion record (${error.message}); snapshot the source again`)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const keys = new Set(altered.map(numberKey))
|
|
172
|
+
return texts.flatMap((text) => tokensOf(String(text ?? ""))).filter((token) => keys.has(token.key)).map((token) => token.text)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Rejoin a grouped number a hard wrap split over one line break, when only the joined reading is in the raw counts. */
|
|
176
|
+
function joinWrapped(tokens, raw) {
|
|
177
|
+
const out = []
|
|
178
|
+
for (const token of tokens) {
|
|
179
|
+
const prev = out.at(-1)
|
|
180
|
+
const wrapped = prev?.n === token.n - 1 && /^ ?\u0001 ?$/u.test(token.gap) && !prev.linked && !token.linked
|
|
181
|
+
const [joined, ...more] = wrapped ? tokensOf(`${prev.text} ${token.text}`) : []
|
|
182
|
+
if (joined && more.length === 0 && raw.has(joined.key) && !(raw.has(prev.key) && raw.has(token.key))) {
|
|
183
|
+
out[out.length - 1] = { ...joined, n: token.n, text: `${prev.text}\n${token.text}` }
|
|
184
|
+
continue
|
|
185
|
+
}
|
|
186
|
+
out.push(token)
|
|
187
|
+
}
|
|
188
|
+
return out
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const countOf = (tokens) => tokens.reduce((counts, token) => counts.set(token.key, (counts.get(token.key) ?? 0) + 1), new Map())
|
|
192
|
+
|
|
193
|
+
/** The tokens `counts` cannot cover; each covered token uses up one count. */
|
|
194
|
+
function uncovered(tokens, counts) {
|
|
195
|
+
return tokens.filter((token) => {
|
|
196
|
+
const remaining = counts.get(token.key) ?? 0
|
|
197
|
+
if (remaining === 0) return true
|
|
198
|
+
counts.set(token.key, remaining - 1)
|
|
199
|
+
return false
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Preserve token spelling in diagnostics; the raw side is read as HTML, the converted side as Markdown
|
|
205
|
+
* with raw inline tags, both decoded with one entity table. `attributes: false`
|
|
206
|
+
* (the built-in snapshot) gives attribute digits no cover, converter syntax no exemption and no wrap rejoin. An exempt
|
|
207
|
+
* marker or label is not a converted number at all: it neither covers a raw number nor counts as altered.
|
|
208
|
+
*/
|
|
209
|
+
export function probeConversion(raw, converted, { attributes = true } = {}) {
|
|
210
|
+
const source = numericText(raw, /<[a-z!/]/i.test(raw))
|
|
211
|
+
const before = tokensOf(source.prose)
|
|
212
|
+
const listed = new Set(source.listed)
|
|
213
|
+
let items = attributes ? source.listed.length : 0
|
|
214
|
+
const syntax = tokensOf(attributes ? decodeEntities(inlineHtml(converted)) : converted, { links: attributes })
|
|
215
|
+
.filter((token) => !(attributes && token.label) && !(token.marker && listed.has(token.key) && items-- > 0))
|
|
216
|
+
const after = attributes ? joinWrapped(syntax, countOf(before)) : syntax
|
|
217
|
+
const counts = countOf(before)
|
|
218
|
+
const extra = new Set(uncovered(after.filter((token) => !token.linked), counts))
|
|
219
|
+
for (const token of tokensOf(source.carried)) counts.set(token.key, (counts.get(token.key) ?? 0) + 1)
|
|
220
|
+
for (const token of uncovered(after.filter((token) => token.linked), counts)) extra.add(token)
|
|
221
|
+
const lost = uncovered(before, countOf(after)).map((token) => token.text)
|
|
222
|
+
return { altered: after.filter((token) => extra.has(token)).map((token) => token.text), lost, raw_count: before.length, converted_count: after.length }
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function runConversionProbe(argv) {
|
|
226
|
+
if (argv.length !== 2) throw new CliError("usage: source probe-conversion <raw-file> <converted-file>")
|
|
227
|
+
const result = probeConversion(readFileSync(argv[0], "utf8"), readFileSync(argv[1], "utf8"))
|
|
228
|
+
return { json: result, summary: `source probe-conversion: ${result.altered.length} altered, ${result.lost.length} lost`, exitCode: result.altered.length === 0 ? 0 : 1 }
|
|
229
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// css-hiding.mjs - whether CSS hides an element of a page from every reader, from its inline style and
|
|
2
|
+
// the page's own <style> rules (external stylesheets and scripts are not evaluated).
|
|
3
|
+
//
|
|
4
|
+
// Text counts as reader-visible when it is visible under at least one condition. So a rule can hide
|
|
5
|
+
// only when it certainly applies: it sits outside every at-rule except @layer (and @media all), its
|
|
6
|
+
// <style> element applies everywhere (no media other than all, CSS type, not in <noscript>), and its
|
|
7
|
+
// selector is one tag (case-insensitive), one .class or one #id (case-sensitive). A rule that only
|
|
8
|
+
// might apply (inside @media, @supports, @container, @scope, @starting-style, @document, @keyframes,
|
|
9
|
+
// nested in another style rule, or with a compound, combinator, attribute or pseudo-class selector)
|
|
10
|
+
// never hides, but it can make text visible when its subject could match and it outranks the hiding
|
|
11
|
+
// declaration in the cascade (origin and importance, inline style, layer order, specificity, order).
|
|
12
|
+
// Hiding properties: display:none and content-visibility:hidden remove the subtree;
|
|
13
|
+
// visibility:hidden|collapse is inherited and a descendant's visibility:visible shows it again.
|
|
14
|
+
// The hidden attribute (except hidden="until-found") and a closed <dialog> are the user-agent
|
|
15
|
+
// display:none, which any author display declaration overrides. opacity, clip, zero size, font-size,
|
|
16
|
+
// off-screen positions and colors do not hide: the text still renders or is read aloud.
|
|
17
|
+
// Plain Node ESM, sibling imports only.
|
|
18
|
+
|
|
19
|
+
import { scanRules } from "./css-lite.mjs"
|
|
20
|
+
|
|
21
|
+
const PROPS = new Set(["display", "visibility", "content-visibility"])
|
|
22
|
+
const INHERITED = new Set(["inherit", "unset", "revert", "revert-layer"])
|
|
23
|
+
const IMPORTANT = /!\s*important\s*$/i
|
|
24
|
+
const SIMPLE = /^(?:[.#][^\s.#:[\]>+~,()*"'\\]+|[a-z][a-z0-9-]*)$/iu
|
|
25
|
+
const PSEUDO_ELEMENT = /::|:(?:before|after|first-line|first-letter)\b/i
|
|
26
|
+
const NAME = "[^\\s.#:[\\]>+~,()*\"'\\\\]+"
|
|
27
|
+
const STYLE_IN_SVG = /<style\b[^>]*>([\s\S]*?)<\/style\s*>/gi
|
|
28
|
+
|
|
29
|
+
/** [tier (0 user agent, 1 author, 2 author !important), inline, layer, specificity, order]: higher wins. */
|
|
30
|
+
const outranks = (a, b) => {
|
|
31
|
+
for (let k = 0; k < a.length; k++) if (a[k] !== b[k]) return a[k] > b[k]
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function specificity(selector) {
|
|
36
|
+
const core = selector.replace(/\[[^\]]*\]/g, " [] ")
|
|
37
|
+
const ids = core.match(new RegExp(`#${NAME}`, "gu"))?.length ?? 0
|
|
38
|
+
const classes = (core.match(new RegExp(`\\.${NAME}`, "gu"))?.length ?? 0) + (core.match(/\[\]|:(?!:)[\w-]+/g)?.length ?? 0)
|
|
39
|
+
const tags = core.match(/(?:^|[\s>+~(])[a-z][\w-]*/gi)?.length ?? 0
|
|
40
|
+
return ids * 10000 + classes * 100 + tags
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The subject compound of a selector: its tag, classes and ids (attribute and pseudo-class parts dropped). */
|
|
44
|
+
function subject(selector) {
|
|
45
|
+
const compound = selector.trim().match(/(?:[^\s>+~[\]()]|\[[^\]]*\]|\([^)]*\))+$/)?.[0] ?? ""
|
|
46
|
+
const core = compound.replace(/\([^)]*\)/g, "").replace(/\[[^\]]*\]/g, "").replace(/:+[\w-]+/g, "")
|
|
47
|
+
const tag = core.match(/^[a-z][a-z0-9-]*/i)?.[0].toLowerCase() ?? null
|
|
48
|
+
const classes = [...core.matchAll(new RegExp(`\\.(${NAME})`, "gu"))].map((match) => match[1])
|
|
49
|
+
const ids = [...core.matchAll(new RegExp(`#(${NAME})`, "gu"))].map((match) => match[1])
|
|
50
|
+
return { tag, classes, ids, key: ids[0] ? `#${ids[0]}` : classes[0] ? `.${classes[0]}` : tag ?? "*" }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const classList = (node) => String(node.attrs?.class ?? "").split(/[ \t\n\f\r]+/).filter(Boolean)
|
|
54
|
+
|
|
55
|
+
function matches(sub, node) {
|
|
56
|
+
if (sub.tag !== null && sub.tag !== node.tag) return false
|
|
57
|
+
const names = classList(node)
|
|
58
|
+
return sub.classes.every((name) => names.includes(name)) && sub.ids.every((id) => id === node.attrs?.id)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Whether every enclosing at-rule leaves the rule unconditional (@layer, @media all), its layer name, and keyframe steps. */
|
|
62
|
+
function context(atRule) {
|
|
63
|
+
const entries = atRule ? atRule.split(/\s(?=@)/) : []
|
|
64
|
+
const layers = entries.filter((entry) => /^@layer\b/i.test(entry)).map((entry) => entry.slice(6).trim())
|
|
65
|
+
const conditional = entries.some((entry) => !/^@layer\b/i.test(entry) && !/^@media(?:\s+all)?\s*$/i.test(entry))
|
|
66
|
+
return { conditional, layer: layers.length ? layers.join(".") : null, keyframe: entries.some((entry) => /^@(?:-[a-z]+-)?keyframes\b/i.test(entry)) }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const declaration = (value) => ({ value: value.replace(IMPORTANT, "").trim().toLowerCase(), important: IMPORTANT.test(value) })
|
|
70
|
+
|
|
71
|
+
/** Every <style> text that applies to the page, with whether it applies only under a condition. */
|
|
72
|
+
function sheets(root) {
|
|
73
|
+
const found = []
|
|
74
|
+
const visit = (node, conditional) => {
|
|
75
|
+
if (node.tag === "template") return
|
|
76
|
+
const inner = conditional || node.tag === "noscript"
|
|
77
|
+
if (node.tag === "style") {
|
|
78
|
+
const type = String(node.attrs?.type ?? "").trim().toLowerCase()
|
|
79
|
+
const media = String(node.attrs?.media ?? "").trim().toLowerCase()
|
|
80
|
+
if (type === "" || type === "text/css") found.push({ css: String(node.raw ?? ""), conditional: inner || (media !== "" && media !== "all") })
|
|
81
|
+
}
|
|
82
|
+
if (node.tag === "svg") for (const match of String(node.raw ?? "").matchAll(STYLE_IN_SVG)) found.push({ css: match[1], conditional: inner })
|
|
83
|
+
for (const child of node.children ?? []) visit(child, inner)
|
|
84
|
+
}
|
|
85
|
+
visit(root, false)
|
|
86
|
+
return found
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Index every rule declaring display, visibility or content-visibility by its subject key. */
|
|
90
|
+
function indexRules(root) {
|
|
91
|
+
const index = new Map()
|
|
92
|
+
const layers = []
|
|
93
|
+
const layerRank = (name, important) => {
|
|
94
|
+
if (name === null) return important ? -1 : 1e6
|
|
95
|
+
if (!layers.includes(name)) layers.push(name)
|
|
96
|
+
return important ? 1e6 - layers.indexOf(name) : layers.indexOf(name)
|
|
97
|
+
}
|
|
98
|
+
let order = 0
|
|
99
|
+
for (const sheet of sheets(root)) {
|
|
100
|
+
const css = sheet.css.replace(/<!--|-->/g, " ")
|
|
101
|
+
for (const match of css.replace(/\/\*[\s\S]*?(?:\*\/|$)/g, "").matchAll(/@layer\s+([^{;]*)[{;]/gi)) {
|
|
102
|
+
for (const name of match[1].split(",").map((part) => part.trim())) if (name && !layers.includes(name)) layers.push(name)
|
|
103
|
+
}
|
|
104
|
+
for (const rule of scanRules(css)) {
|
|
105
|
+
const decls = rule.declarations.filter((entry) => PROPS.has(entry.prop))
|
|
106
|
+
if (!decls.length || rule.selector.startsWith("@")) continue
|
|
107
|
+
const { conditional, layer, keyframe } = context(rule.atRule)
|
|
108
|
+
if (keyframe) continue
|
|
109
|
+
for (const selector of rule.selector.split(/,(?![^()[\]]*[)\]])/).map((part) => part.trim())) {
|
|
110
|
+
if (!selector || PSEUDO_ELEMENT.test(selector)) continue
|
|
111
|
+
const sub = subject(selector)
|
|
112
|
+
const certain = !sheet.conditional && !conditional && !rule.nested && SIMPLE.test(selector)
|
|
113
|
+
const spec = specificity(selector)
|
|
114
|
+
for (const entry of decls) {
|
|
115
|
+
const { value, important } = declaration(entry.value)
|
|
116
|
+
const rank = [important ? 2 : 1, 0, layerRank(layer, important), spec, order++]
|
|
117
|
+
if (!index.has(sub.key)) index.set(sub.key, [])
|
|
118
|
+
index.get(sub.key).push({ sub, prop: entry.prop, value, rank, certain })
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return index
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** The values a property can take on the element: the certain winner, plus every possible rule that outranks it. */
|
|
127
|
+
function possible(candidates, prop) {
|
|
128
|
+
let top = null
|
|
129
|
+
for (const entry of candidates) if (entry.prop === prop && entry.certain && (top === null || outranks(entry.rank, top.rank))) top = entry
|
|
130
|
+
const values = [top === null ? "unset" : top.value]
|
|
131
|
+
for (const entry of candidates) if (entry.prop === prop && !entry.certain && (top === null || outranks(entry.rank, top.rank))) values.push(entry.value)
|
|
132
|
+
return values
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* cssVisibility(root) -> (node, parentShown) => null when CSS removes the element and its subtree from every
|
|
137
|
+
* rendering, else whether its own text can be seen (visibility, inherited from parentShown).
|
|
138
|
+
*/
|
|
139
|
+
export function cssVisibility(root) {
|
|
140
|
+
const index = indexRules(root)
|
|
141
|
+
return (node, parentShown) => {
|
|
142
|
+
const attrs = node.attrs ?? {}
|
|
143
|
+
const keys = ["*", node.tag, ...classList(node).map((name) => `.${name}`), attrs.id === undefined ? null : `#${attrs.id}`]
|
|
144
|
+
const candidates = []
|
|
145
|
+
for (const key of new Set(keys)) for (const entry of index.get(key) ?? []) if (matches(entry.sub, node)) candidates.push(entry)
|
|
146
|
+
const hiddenAttr = attrs.hidden !== undefined && String(attrs.hidden).trim().toLowerCase() !== "until-found"
|
|
147
|
+
if (hiddenAttr || (node.tag === "dialog" && attrs.open === undefined)) candidates.push({ prop: "display", value: "none", rank: [0, 0, 0, 0, -1], certain: true })
|
|
148
|
+
const inline = attrs.style ? (scanRules(`x{${attrs.style}}`)[0]?.declarations ?? []) : []
|
|
149
|
+
inline.forEach((entry, at) => {
|
|
150
|
+
if (!PROPS.has(entry.prop)) return
|
|
151
|
+
const { value, important } = declaration(entry.value)
|
|
152
|
+
candidates.push({ prop: entry.prop, value, rank: [important ? 2 : 1, 1, 0, 0, at], certain: true })
|
|
153
|
+
})
|
|
154
|
+
if (possible(candidates, "display").every((value) => value === "none")) return null
|
|
155
|
+
if (possible(candidates, "content-visibility").every((value) => value === "hidden")) return null
|
|
156
|
+
return possible(candidates, "visibility").some((value) => (INHERITED.has(value) ? parentShown : value !== "hidden" && value !== "collapse"))
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -57,8 +57,9 @@ function parseDeclarations(text) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
* @returns {{ selector: string, declarations: { prop: string, value: string }[], atRule?: string }[]}
|
|
61
|
-
* atRule is the chain of enclosing grouping at-rule preludes joined by a space
|
|
60
|
+
* @returns {{ selector: string, declarations: { prop: string, value: string }[], atRule?: string, nested?: true }[]}
|
|
61
|
+
* atRule is the chain of enclosing grouping at-rule preludes joined by a space; nested is true for a
|
|
62
|
+
* rule written inside another style rule (CSS nesting).
|
|
62
63
|
*/
|
|
63
64
|
export function scanRules(css) {
|
|
64
65
|
if (typeof css !== "string") return []
|
|
@@ -88,6 +89,7 @@ export function scanRules(css) {
|
|
|
88
89
|
const atChain = stack.filter((entry) => entry.group).map((entry) => entry.prelude)
|
|
89
90
|
const rule = { selector: frame.prelude, declarations: parseDeclarations(frame.body + buffer) }
|
|
90
91
|
if (atChain.length) rule.atRule = atChain.join(" ")
|
|
92
|
+
if (stack.some((entry) => !entry.group)) rule.nested = true
|
|
91
93
|
slots[frame.slot] = rule
|
|
92
94
|
}
|
|
93
95
|
buffer = ""
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
// entities.mjs - HTML character reference decoding for html-lite.mjs.
|
|
2
2
|
//
|
|
3
|
-
// Supports a fixed set of named entities plus decimal and hex numeric references.
|
|
4
|
-
// malformed references stay verbatim. Single indexOf scan; plain Node ESM, no dependencies.
|
|
3
|
+
// Supports a fixed set of named entities (NAMED_ENTITIES) plus decimal and hex numeric references.
|
|
4
|
+
// Unknown or malformed references stay verbatim. Single indexOf scan; plain Node ESM, no dependencies.
|
|
5
5
|
|
|
6
|
+
// Beyond the common set, every named reference whose character a number reader treats specially is
|
|
7
|
+
// listed (signs, dashes, the space separators that group digits, and Markdown punctuation), so the
|
|
8
|
+
// conversion probe reads `−5` and `1 234` as a converter does.
|
|
6
9
|
const NAMED_ENTITIES = {
|
|
7
10
|
amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: "\u00a0", mdash: "\u2014", ndash: "\u2013",
|
|
8
11
|
hellip: "\u2026", copy: "\u00a9", reg: "\u00ae", times: "\u00d7", middot: "\u00b7",
|
|
12
|
+
minus: "\u2212", hyphen: "\u2010", dash: "\u2010", NonBreakingSpace: "\u00a0", thinsp: "\u2009",
|
|
13
|
+
ThinSpace: "\u2009", numsp: "\u2007", puncsp: "\u2008", hairsp: "\u200a", VeryThinSpace: "\u200a",
|
|
14
|
+
ensp: "\u2002", emsp: "\u2003", emsp13: "\u2004", emsp14: "\u2005", MediumSpace: "\u205f",
|
|
15
|
+
comma: ",", period: ".", plus: "+", lowbar: "_", UnderBar: "_", ast: "*", midast: "*", grave: "`",
|
|
16
|
+
DiacriticalGrave: "`", lpar: "(", rpar: ")", lsqb: "[", lbrack: "[", rsqb: "]", rbrack: "]",
|
|
9
17
|
}
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
/** One reference body (between `&` and `;`), or null when unsupported. */
|
|
20
|
+
export function decodeOne(body) {
|
|
12
21
|
if (Object.hasOwn(NAMED_ENTITIES, body)) return NAMED_ENTITIES[body]
|
|
13
22
|
if (body[0] !== "#") return null
|
|
14
23
|
const hex = body[1] === "x" || body[1] === "X"
|
|
@@ -26,7 +35,7 @@ export function decodeEntities(text) {
|
|
|
26
35
|
let at = source.indexOf("&")
|
|
27
36
|
while (at !== -1) {
|
|
28
37
|
const semi = source.indexOf(";", at + 1)
|
|
29
|
-
const decoded = semi !== -1 && semi - at <=
|
|
38
|
+
const decoded = semi !== -1 && semi - at <= 32 ? decodeOne(source.slice(at + 1, semi)) : null
|
|
30
39
|
if (decoded !== null) {
|
|
31
40
|
out += source.slice(last, at) + decoded
|
|
32
41
|
last = semi + 1
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// fact-commands-fill.mjs - `fact fill`, the reader-facing fill of a placeholder source.
|
|
2
|
+
//
|
|
3
|
+
// It refuses an unlocked brief (fidelity_interview_incomplete) and applies the locked `## Fidelity`
|
|
4
|
+
// fields: `derived numbers: none` and the source floor refuse rows (derived_not_allowed,
|
|
5
|
+
// source_outside_floor, evaluated at every fill), `languages` decides whether a translation after a
|
|
6
|
+
// quote binds to it, and `fallback` picks the block quote or omission for --replace-failed. Any
|
|
7
|
+
// error writes no edition, fill map, or state; the one write that survives a refusal is the
|
|
8
|
+
// ledger's cached outside_floor per row (skipped under --view). The fill map records brief_sha256,
|
|
9
|
+
// the locked block fact verify checks it against. node: builtins and sibling imports only.
|
|
10
|
+
|
|
11
|
+
import { readFileSync, writeFileSync } from "node:fs"
|
|
12
|
+
import { dirname, extname, resolve } from "node:path"
|
|
13
|
+
|
|
14
|
+
import { CliError, sha256Of, writeJsonAtomic } from "./cli-support.mjs"
|
|
15
|
+
import { DEFECT_CODES } from "./contracts.mjs"
|
|
16
|
+
import { markdownAsHtml } from "./fact-commands-verify.mjs"
|
|
17
|
+
import { FILL_FORMATS, fill } from "./fact-fill.mjs"
|
|
18
|
+
import { readLedger, writeLedger } from "./fact-ledger.mjs"
|
|
19
|
+
import { briefHashOf, fillPolicy, lockedBrief, policyErrors } from "./fidelity-policy.mjs"
|
|
20
|
+
import { readState, writeState } from "./fidelity-state.mjs"
|
|
21
|
+
import { withBoundUnits } from "./fidelity-value-unit.mjs"
|
|
22
|
+
import { parseMarkdown } from "./md-lite.mjs"
|
|
23
|
+
import { findPlaceholders } from "./placeholder.mjs"
|
|
24
|
+
import { sessionDirOf } from "./source-commands.mjs"
|
|
25
|
+
|
|
26
|
+
/** The CLI's input vocabulary: fill's output formats plus aliases (tex is filled as md), and the extension defaults. */
|
|
27
|
+
export const FILL_INPUT_FORMAT_RULES = Object.freeze({
|
|
28
|
+
aliases: Object.freeze({ tex: "md" }),
|
|
29
|
+
extensions: Object.freeze({ ".md": "md", ".tex": "tex" }),
|
|
30
|
+
})
|
|
31
|
+
export const FILL_INPUT_FORMATS = Object.freeze([...FILL_FORMATS, ...Object.keys(FILL_INPUT_FORMAT_RULES.aliases)])
|
|
32
|
+
const fillFormatOf = (format) => FILL_INPUT_FORMAT_RULES.aliases[format] ?? format
|
|
33
|
+
|
|
34
|
+
/** Value-mode entries carry the unit fill saw bound to them (unit_bound), read off the edition verify will check. */
|
|
35
|
+
function boundUnits(out, entries, ledger, format) {
|
|
36
|
+
if (!entries.some((entry) => entry.mode === "value")) return entries
|
|
37
|
+
const html = fillFormatOf(format) === "html" ? out : parseMarkdown(out).problems.length === 0 ? markdownAsHtml(out, entries, ledger).html : null
|
|
38
|
+
return html === null ? entries : withBoundUnits(html, entries, new Map(ledger.rows.map((row) => [row.fact_id, row])))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function readText(path) {
|
|
42
|
+
try {
|
|
43
|
+
return readFileSync(path, "utf8")
|
|
44
|
+
} catch (error) {
|
|
45
|
+
throw new CliError(`cannot read ${path}: ${error.code ?? error.message}`)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The inline edition: local stylesheets and scripts inlined, relative image paths made absolute. */
|
|
50
|
+
function inlineAssets(html, baseDir) {
|
|
51
|
+
const local = (ref) => !/^[a-z][a-z0-9+.-]*:|^\/\//i.test(ref)
|
|
52
|
+
return html
|
|
53
|
+
.replace(/<link\b[^>]*\brel=["']stylesheet["'][^>]*>/gi, (tag) => {
|
|
54
|
+
const href = /\bhref=["']([^"']+)["']/i.exec(tag)?.[1]
|
|
55
|
+
return href && local(href) ? `<style>${readText(resolve(baseDir, href))}</style>` : tag
|
|
56
|
+
})
|
|
57
|
+
.replace(/<script\b([^>]*)\bsrc=["']([^"']+)["']([^>]*)><\/script>/gi, (tag, pre, src, post) => (local(src) ? `<script${pre}${post}>${readText(resolve(baseDir, src))}</script>` : tag))
|
|
58
|
+
.replace(/(<img\b[^>]*\bsrc=["'])([^"']+)(["'])/gi, (tag, pre, src, post) => (local(src) && !src.startsWith("/") ? `${pre}${resolve(baseDir, src)}${post}` : tag))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** @param {{ positionals: string[], flags: Record<string, any> }} args parsed by runFact */
|
|
62
|
+
export function runFactFill(args) {
|
|
63
|
+
const [source] = args.positionals
|
|
64
|
+
const { flags } = args
|
|
65
|
+
if (!source || (flags.out === undefined && !flags.view)) throw new CliError("usage: fact fill <src> (--out <path> | --view) [--format html|md|tex] [--inline] [--replace-failed] [--brief brief.md]")
|
|
66
|
+
const format = flags.format ?? FILL_INPUT_FORMAT_RULES.extensions[extname(source).toLowerCase()] ?? "html"
|
|
67
|
+
if (!FILL_INPUT_FORMATS.includes(format)) throw new CliError(`--format must be ${FILL_INPUT_FORMATS.slice(0, -1).join(", ")}, or ${FILL_INPUT_FORMATS.at(-1)}`)
|
|
68
|
+
if (flags.inline && format !== "html") throw new CliError("--inline applies to the html edition only")
|
|
69
|
+
const sessionDir = sessionDirOf(flags)
|
|
70
|
+
const { parsed, refusal } = lockedBrief("fact fill", flags)
|
|
71
|
+
if (refusal) return refusal
|
|
72
|
+
const policy = fillPolicy(parsed)
|
|
73
|
+
const text = readText(source)
|
|
74
|
+
const ledger = readLedger(sessionDir)
|
|
75
|
+
const refused = policyErrors(text, findPlaceholders(text), ledger, sessionDir, policy)
|
|
76
|
+
if (refused.cacheChanged && !flags.view) writeLedger(sessionDir, ledger)
|
|
77
|
+
const state = flags["replace-failed"] ? readState(sessionDir) : null
|
|
78
|
+
const result = fill(text, ledger, { format: fillFormatOf(format), view: flags.view === true, fallback: policy.fallback, ...(state ? { replaceFailed: state } : {}) })
|
|
79
|
+
const warnings = result.warnings
|
|
80
|
+
if (result.out === null || refused.errors.length > 0) {
|
|
81
|
+
const filled = result.errors.map((error) => ({ ...error, severity: DEFECT_CODES[error.code]?.severity ?? "blocker", hint: DEFECT_CODES[error.code]?.hint ?? null }))
|
|
82
|
+
const defects = [...refused.errors, ...filled]
|
|
83
|
+
return { json: { command: "fact fill", status: "fail", exitCode: 1, defects, warnings }, summary: `fact fill: FAIL - ${defects.length} error(s), nothing written`, exitCode: 1 }
|
|
84
|
+
}
|
|
85
|
+
const entries = policy.translations ? result.fillMap : result.fillMap.filter((entry) => entry.translates === undefined)
|
|
86
|
+
const out = flags.inline ? inlineAssets(result.out, dirname(resolve(source))) : result.out
|
|
87
|
+
if (flags.view) return { text: out, summary: `fact fill --view: ${entries.length} pointer(s), ${warnings.length} warning(s)`, exitCode: 0 }
|
|
88
|
+
writeFileSync(flags.out, out)
|
|
89
|
+
if (state) writeState(sessionDir, state)
|
|
90
|
+
const artifact = sha256Of(out)
|
|
91
|
+
const map = `${resolve(flags.out)}.fill-map.json`
|
|
92
|
+
const brief = briefHashOf(parsed)
|
|
93
|
+
writeJsonAtomic(map, { schemaVersion: 1, format, artifact: resolve(flags.out), artifact_sha256: artifact, brief_sha256: brief, entries: boundUnits(out, entries, ledger, format) })
|
|
94
|
+
const data = { out: resolve(flags.out), map, artifact_sha256: artifact, brief_sha256: brief, occurrences: entries.length, warnings }
|
|
95
|
+
return { json: { command: "fact fill", status: "pass", exitCode: 0, defects: [], data }, summary: `fact fill: wrote ${flags.out} (${entries.length} pointer(s))`, exitCode: 0 }
|
|
96
|
+
}
|