oh-my-opencode 5.1.46 → 5.1.47
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/.agents/command/publish.md +3 -4
- package/.agents/skills/publish/SKILL.md +3 -4
- package/.opencode/command/publish.md +3 -4
- package/dist/agents/atlas/agent.d.ts +3 -2
- package/dist/agents/sisyphus/index.d.ts +1 -0
- package/dist/agents/sisyphus/kimi-k3-1.d.ts +9 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
- package/dist/agents/sisyphus-junior/agent.d.ts +1 -1
- package/dist/agents/sisyphus-junior/index.d.ts +1 -0
- package/dist/agents/sisyphus-junior/kimi-k3-1.d.ts +6 -0
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/index.js +29 -21
- package/dist/cli/service-auth/keystore.d.ts +8 -3
- package/dist/cli-node/index.js +29 -21
- package/dist/index.js +634 -17
- package/dist/skills/browser/runtime/omowright/manifest.json +1 -1
- package/dist/skills/ulw-research/SKILL.md +1 -1
- package/dist/skills/ulw-research/references/deliverable-phase.md +9 -2
- package/dist/skills/ulw-research/scripts/copy-returns-polish.test.ts +209 -0
- package/dist/skills/ulw-research/scripts/fact-commands-meaning.mjs +7 -22
- package/dist/skills/ulw-research/scripts/fact-commands-polish.mjs +127 -0
- package/dist/skills/ulw-research/scripts/fact-commands-verify.mjs +19 -0
- package/dist/skills/ulw-research/scripts/fact-commands.mjs +4 -2
- package/dist/skills/ulw-research/scripts/fact-pairs.mjs +7 -9
- package/dist/skills/ulw-research/scripts/fact-pairs.test.ts +7 -23
- package/dist/skills/ulw-research/scripts/references-fences.test.ts +25 -0
- package/dist/skills/ulw-research/scripts/report-tools.test.ts +87 -0
- package/dist/skills/ulw-research/scripts/tests/fixtures/fidelity/polish-edits.json +12 -0
- package/dist/tui.js +13 -13
- package/package.json +13 -13
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +1 -2
- 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/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 +1 -1
- 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/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +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/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 +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +1 -1
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +9 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-meaning.mjs +7 -22
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-polish.mjs +127 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-verify.mjs +19 -0
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands.mjs +4 -2
- package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-pairs.mjs +7 -9
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +1 -1
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +4 -5
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/shared-skills/skills/ulw-research/SKILL.md +1 -1
- package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +9 -2
- package/packages/shared-skills/skills/ulw-research/scripts/copy-returns-polish.test.ts +209 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-meaning.mjs +7 -22
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-polish.mjs +127 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-verify.mjs +19 -0
- package/packages/shared-skills/skills/ulw-research/scripts/fact-commands.mjs +4 -2
- package/packages/shared-skills/skills/ulw-research/scripts/fact-pairs.mjs +7 -9
- package/packages/shared-skills/skills/ulw-research/scripts/fact-pairs.test.ts +7 -23
- package/packages/shared-skills/skills/ulw-research/scripts/references-fences.test.ts +25 -0
- package/packages/shared-skills/skills/ulw-research/scripts/report-tools.test.ts +87 -0
- package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/fidelity/polish-edits.json +12 -0
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook post-tool-use-spawn",
|
|
10
10
|
"timeout": 5,
|
|
11
|
-
"statusMessage": "(OmO 5.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.47) Recording Spawn Admission",
|
|
12
12
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook post-tool-use-spawn"
|
|
13
13
|
}
|
|
14
14
|
]
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook pre-tool-use",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Enforcing Unlimited Goal Budget",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook pre-tool-use"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook pre-tool-use-spawn",
|
|
10
10
|
"timeout": 5,
|
|
11
|
-
"statusMessage": "(OmO 5.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.47) Guarding Ulw-Loop Spawns",
|
|
12
12
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook pre-tool-use-spawn"
|
|
13
13
|
}
|
|
14
14
|
]
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/git-bash/dist/cli.js\" hook pre-tool-use",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Recommending Git Bash MCP",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\git-bash\\dist\\cli.js\" hook pre-tool-use"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/scripts/auto-update.mjs\" hook session-start",
|
|
9
9
|
"timeout": 15,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Checking Auto Update",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\scripts\\auto-update.mjs\" hook session-start"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/bootstrap/dist/cli.js\" hook session-start",
|
|
9
9
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1\"",
|
|
10
10
|
"timeout": 30,
|
|
11
|
-
"statusMessage": "(OmO 5.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.47) Checking Bootstrap Provisioning"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/rules/dist/cli.js\" hook session-start",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Loading Project Rules",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\rules\\dist\\cli.js\" hook session-start"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/telemetry/dist/cli.js\" hook session-start",
|
|
9
9
|
"timeout": 15,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Recording Session Telemetry",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\telemetry\\dist\\cli.js\" hook session-start"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/ulw-execute-continuation/dist/cli.js\" hook stop",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Checking Ulw-Execute Continuation",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-execute-continuation\\dist\\cli.js\" hook stop"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook stop",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Checking Ulw-Loop Resume",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook stop"
|
|
12
12
|
}
|
|
13
13
|
]
|
package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/lazycodex-executor-verify/dist/cli.js\" hook subagent-stop",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Verifying LazyCodex Executor Evidence",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\lazycodex-executor-verify\\dist\\cli.js\" hook subagent-stop"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/ultrawork/dist/cli.js\" hook user-prompt-submit",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Checking Ultrawork Trigger",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ultrawork\\dist\\cli.js\" hook user-prompt-submit"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook user-prompt-submit",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Checking Ulw-Loop Steering",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook user-prompt-submit"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/rules/dist/cli.js\" hook user-prompt-submit",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.47) Loading Project Rules",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\rules\\dist\\cli.js\" hook user-prompt-submit"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sisyphuslabs/omo-codex-plugin",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.47",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@sisyphuslabs/omo-codex-plugin",
|
|
9
|
-
"version": "5.1.
|
|
9
|
+
"version": "5.1.47",
|
|
10
10
|
"workspaces": [
|
|
11
11
|
"components/comment-checker",
|
|
12
12
|
"components/git-bash",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
},
|
|
101
101
|
"components/comment-checker": {
|
|
102
102
|
"name": "@code-yeongyu/codex-comment-checker",
|
|
103
|
-
"version": "5.1.
|
|
103
|
+
"version": "5.1.47",
|
|
104
104
|
"license": "MIT",
|
|
105
105
|
"bin": {
|
|
106
106
|
"omo-comment-checker": "dist/cli.js"
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
},
|
|
123
123
|
"components/git-bash": {
|
|
124
124
|
"name": "@sisyphuslabs/codex-git-bash-hook",
|
|
125
|
-
"version": "5.1.
|
|
125
|
+
"version": "5.1.47",
|
|
126
126
|
"bin": {
|
|
127
127
|
"omo-git-bash-hook": "dist/cli.js"
|
|
128
128
|
},
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
},
|
|
137
137
|
"components/lazycodex-executor-verify": {
|
|
138
138
|
"name": "@code-yeongyu/codex-lazycodex-executor-verify",
|
|
139
|
-
"version": "5.1.
|
|
139
|
+
"version": "5.1.47",
|
|
140
140
|
"license": "MIT",
|
|
141
141
|
"bin": {
|
|
142
142
|
"lazycodex-executor-verify": "dist/cli.js"
|
|
@@ -154,7 +154,7 @@
|
|
|
154
154
|
},
|
|
155
155
|
"components/lsp": {
|
|
156
156
|
"name": "@code-yeongyu/codex-lsp",
|
|
157
|
-
"version": "5.1.
|
|
157
|
+
"version": "5.1.47",
|
|
158
158
|
"license": "MIT",
|
|
159
159
|
"dependencies": {
|
|
160
160
|
"@code-yeongyu/lsp-daemon": "file:../../../../lsp-daemon",
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
},
|
|
177
177
|
"components/rules": {
|
|
178
178
|
"name": "@code-yeongyu/codex-rules",
|
|
179
|
-
"version": "5.1.
|
|
179
|
+
"version": "5.1.47",
|
|
180
180
|
"license": "MIT",
|
|
181
181
|
"dependencies": {
|
|
182
182
|
"picomatch": "^4.0.7"
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
},
|
|
200
200
|
"components/teammode": {
|
|
201
201
|
"name": "@sisyphuslabs/codex-teammode",
|
|
202
|
-
"version": "5.1.
|
|
202
|
+
"version": "5.1.47",
|
|
203
203
|
"devDependencies": {
|
|
204
204
|
"@types/node": "^26.6.2",
|
|
205
205
|
"@vitest/coverage-v8": "5.0.1",
|
|
@@ -213,7 +213,7 @@
|
|
|
213
213
|
},
|
|
214
214
|
"components/telemetry": {
|
|
215
215
|
"name": "@code-yeongyu/codex-telemetry",
|
|
216
|
-
"version": "5.1.
|
|
216
|
+
"version": "5.1.47",
|
|
217
217
|
"license": "MIT",
|
|
218
218
|
"bin": {
|
|
219
219
|
"omo-telemetry": "dist/cli.js"
|
|
@@ -232,7 +232,7 @@
|
|
|
232
232
|
},
|
|
233
233
|
"components/ultrawork": {
|
|
234
234
|
"name": "@code-yeongyu/codex-ultrawork",
|
|
235
|
-
"version": "5.1.
|
|
235
|
+
"version": "5.1.47",
|
|
236
236
|
"license": "MIT",
|
|
237
237
|
"bin": {
|
|
238
238
|
"omo-ultrawork": "dist/cli.js"
|
|
@@ -251,7 +251,7 @@
|
|
|
251
251
|
},
|
|
252
252
|
"components/ulw-execute-continuation": {
|
|
253
253
|
"name": "@code-yeongyu/codex-ulw-execute-continuation",
|
|
254
|
-
"version": "5.1.
|
|
254
|
+
"version": "5.1.47",
|
|
255
255
|
"license": "MIT",
|
|
256
256
|
"bin": {
|
|
257
257
|
"omo-ulw-execute-continuation": "dist/cli.js"
|
|
@@ -269,7 +269,7 @@
|
|
|
269
269
|
},
|
|
270
270
|
"components/ulw-loop": {
|
|
271
271
|
"name": "@code-yeongyu/codex-ulw-loop",
|
|
272
|
-
"version": "5.1.
|
|
272
|
+
"version": "5.1.47",
|
|
273
273
|
"license": "MIT",
|
|
274
274
|
"bin": {
|
|
275
275
|
"omo-ulw-loop": "dist/cli.js",
|
|
@@ -175,7 +175,7 @@ prefixes when identity is needed.
|
|
|
175
175
|
// and keeps every tool-based delivery gate (static, fidelity, layout, visual QA). The item is matched by
|
|
176
176
|
// its text right after the Visual QA sentence, not by its list numeral, so adding or removing an earlier
|
|
177
177
|
// delivery gate does not unhook the overlay.
|
|
178
|
-
const ulwResearchProofreadGate = "**Proofread gate: `task(category=\"writing\", ...)`.** Hand the final text to a dedicated `writing` worker whose only job is language: grammar, spelling, punctuation, terminology consistency, and whether the prose reads NATIVELY in the report's own language. It proofreads only and never composes
|
|
178
|
+
const ulwResearchProofreadGate = "**Proofread gate: `task(category=\"writing\", ...)`.** Hand the final text to a dedicated `writing` worker whose only job is language: grammar, spelling, punctuation, terminology consistency, and whether the prose reads NATIVELY in the report's own language. It proofreads only and never composes, and it never edits the file: it returns `$SESSION_DIR/polish-edits.json`, an array of `{\"before\": ..., \"after\": ..., \"reason\": ...}` where `before` is the exact current text of one or more adjacent sentences. Edits change text only; an edit whose before/after would alter any tag, attribute, comment, or script/style content is rejected, and markup changes go through the full fidelity gates instead. Apply it with `node \"$SKILL_DIR/scripts/report-tools.mjs\" fact polish-apply \"$SESSION_DIR/report.html\" --edits \"$SESSION_DIR/polish-edits.json\" --out \"$SESSION_DIR/report.polished.html\" --session-dir \"$SESSION_DIR\"`: each edit is applied alone, and an edit that changes a fact span, a numeral, a link, or a claim id, or drops a hedge or qualifier the source carries, is `polish_edit_rejected` (a `before` not found exactly once is `polish_edit_unlocated`) and leaves its text unchanged. Send the rejected and unlocated edits back to the same worker with their reasons, plus `$SESSION_DIR/polish-defects.json` and the pre-polish `report.html` the backstop compared against, so the worker sees why each edit was refused; it returns either a rewritten sentence or a new edit list, and the repair round re-runs `fact polish-apply` with `\"$SESSION_DIR/report.polished.html\"` as both input and output, within the repair budget. Then run the backstop `fact polish-diff --before \"$SESSION_DIR/report.html\" --after \"$SESSION_DIR/report.polished.html\" --session-dir \"$SESSION_DIR\"` (exit `1` on `polish_diff_fail`), `fact verify` on `report.polished.html`, and `fact pairs \"$SESSION_DIR/report.polished.html\" --changed-since \"$SESSION_DIR/report.html.fill-map.json\" --session-dir \"$SESSION_DIR\"`, which keeps only the quote and claim pairs whose sentence text changed during polish; run the meaning readers above (cheap, then strong on the flagged pairs) on exactly those pairs and `fact meaning-check` before recording `outcome gate fidelity`. A rewording that keeps every number, hedge, qualifier, and link but swaps who did what to whom therefore still reaches a meaning reader on the delivered text. `report.polished.html` is the report that is delivered. Deliver only on a clean pass. This gate runs BEFORE the first delivery, not after the user finds the typo. Edits must not span entities (such as & or <) or markup; narrow the edit to the surrounding words instead, and a rejected edit comes back with the reason to act on.";
|
|
179
179
|
const ulwResearchProofreadGateSource = ulwResearchProofreadGate.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
180
180
|
const ulwResearchProofreadGatePattern = new RegExp(`(inspect the pixels\\.)\\n\\d+\\. ${ulwResearchProofreadGateSource}`);
|
|
181
181
|
|
|
@@ -133,7 +133,12 @@ Nothing reaches the requester until the gates for its QA tier pass, in this orde
|
|
|
133
133
|
node "$SKILL_DIR/scripts/report-tools.mjs" layout-probe --json # .source is one async expression
|
|
134
134
|
```
|
|
135
135
|
4. **Visual QA.** Render the artifact to images (PDF pages to PNG, the HTML in the browser skill's engine at desktop and phone widths) and look at the pixels for what a machine cannot see: composition, hierarchy, page breaks, figure legibility.
|
|
136
|
-
5. **Proofread.** A dedicated writing lane proofreads the final text only (grammar, spelling, punctuation, terminology, native register); it never composes or rewrites content.
|
|
136
|
+
5. **Proofread.** A dedicated writing lane proofreads the final text only (grammar, spelling, punctuation, terminology, native register); it never composes or rewrites content and never edits the file. Edits change text only; an edit whose before/after would alter any tag, attribute, comment, or script/style content is rejected, and markup changes go through the full fidelity gates instead. It returns `polish-edits.json` (`[{before, after, reason}]`), which the orchestrator applies edit by edit; a rejected or unlocated edit goes back to the lane with its reason, within the repair budget. The backstop diff, `fact verify` on the polished file, and the meaning readers on the pairs whose sentences polish changed run before the fidelity gate is recorded again. Edits must not span entities (such as & or <) or markup; narrow the edit to the surrounding words instead, and a rejected edit comes back with the reason to act on.
|
|
137
|
+
```bash
|
|
138
|
+
node "$SKILL_DIR/scripts/report-tools.mjs" fact polish-apply "$SESSION_DIR/report.html" --edits "$SESSION_DIR/polish-edits.json" --out "$SESSION_DIR/report.polished.html" --session-dir "$SESSION_DIR"
|
|
139
|
+
node "$SKILL_DIR/scripts/report-tools.mjs" fact polish-diff --before "$SESSION_DIR/report.html" --after "$SESSION_DIR/report.polished.html" --session-dir "$SESSION_DIR" # writes polish-defects.json
|
|
140
|
+
node "$SKILL_DIR/scripts/report-tools.mjs" fact pairs "$SESSION_DIR/report.polished.html" --changed-since "$SESSION_DIR/report.html.fill-map.json" --session-dir "$SESSION_DIR"
|
|
141
|
+
```
|
|
137
142
|
|
|
138
143
|
**Every reader-facing edition is verified.** The main report, the inline edition (section 9), LaTeX per-section sources, and slide sources are filled by `fact fill` from one placeholder source and each is verified by `fact verify` into its own record; PDF and DOCX are renders of a verified source. A delivered row is recorded with `outcome set <format> delivered --path <file> --verified-by <record>`, where the record's `artifact_sha256` equals the sha256 of the delivered source; a PDF or DOCX adds `--rendered-from <source>` and is matched against that source. In a session with a fact ledger, `outcome verify` refuses a delivered row without a matching record (`edition_unverified`, blocker, integrity). Markdown and LaTeX verification arrive with the Markdown stage; until then `fact verify --format md|tex` exits `2`, and such an edition is recorded `blocked_capability` with that reason rather than delivered unverified.
|
|
139
144
|
|
|
@@ -216,7 +221,9 @@ Invoke every command as `node "$SKILL_DIR/scripts/report-tools.mjs" <command>`.
|
|
|
216
221
|
| `fact export` | `--csv`, `--out <file>`, `--session-dir <dir>` | never |
|
|
217
222
|
| `fact fill <src>` | `--out <file>` or `--view`, `--format html\|md\|tex`, `--inline`, `--replace-failed`, `--session-dir <dir>` | a fill error (nothing is written) |
|
|
218
223
|
| `fact verify <report>` | `--format html\|md` (from the extension by default), `--sources <dir>`, `--claims <claims.json>`, `--fill-map <file>` (a Markdown edition reads `<report>.fill-map.json` by default), `--brief <brief.md>`, `--out <record>`, `--session-dir <dir>` | any blocker or major defect |
|
|
219
|
-
| `fact pairs <report>` | `--format html\|md`, `--ledger <fact-ledger.json>`, `--claims <claims.json>`, `--changed-since <fill-map.json>` (
|
|
224
|
+
| `fact pairs <report>` | `--format html\|md`, `--ledger <fact-ledger.json>`, `--claims <claims.json>`, `--changed-since <fill-map.json>` (keep only the pairs whose sentence text is not in the pre-polish artifact that map names, so the readers re-check exactly what polish rewrote; the map must carry `artifact_sha256` and the artifact must still hash to it, otherwise the command exits `2`), `--brief <brief.md>`, `--out <pairs.json>`, `--session-dir <dir>` | the brief has no locked `## Fidelity` block (with `meaning check: off` it writes `{"skipped": true}` and exits `0`) |
|
|
225
|
+
| `fact polish-apply <report.html>` | `--edits <polish-edits.json>` and `--out <report.polished.html>` (both required; a missing flag or a Markdown edition exits `2`), `--format html`, `--ledger <fact-ledger.json>`, `--session-dir <dir>` | never: it exits `0` whenever it wrote the output. Each rejected (`polish_edit_rejected`) or unlocated (`polish_edit_unlocated`) edit leaves its text unchanged and is printed verbatim, one line per rejection, in the summary and in `data.rejected_reasons`; `data` also carries `applied`, `rejected`, `unlocated`, `applied_indexes`, `input_sha256`, `edits_sha256`, and `out_sha256` |
|
|
226
|
+
| `fact polish-diff` | `--before <pre-polish.html>` and `--after <polished.html>` (both required; a missing flag exits `2`), `--ledger <fact-ledger.json>`, `--out <record>` (default `$SESSION_DIR/polish-defects.json`), `--session-dir <dir>` | a registry blocker in the diff (majors and minors are reported and exit `0`; a defect code the registry does not know refuses with `unknown defect code <code>`). The record is `{command, status, exitCode, before, artifact, artifact_sha256, defects[], counts}`, with `counts` in contract buckets |
|
|
220
227
|
| `fact meaning-check` | `--pairs <pairs.json>` and `--verdicts <file>` (required; repeatable, one per reader tier), `--dispute P<n> --reason <text>`, `--run-id <id>`, `--calibration <file>` (default `fidelity-calibration.jsonl`), `--out <record>` (default `fidelity-meaning-defects.json`), `--session-dir <dir>` | `meaning_drift_confirmed` (stderr carries one JSON line with the defect and dropped-verdict counts) |
|
|
221
228
|
| `fact derive` | `--op <op>` (required) with the operation's operands (section 11), `--unit`, `--to`, `--rationale`, `--disjoint`, `--label`, `--json`, `--session-dir <dir>` | `incompatible_operands` (no row written) |
|
|
222
229
|
| `claims index <claim-graph.md>` | `--out <claims.json>` (required) | never (a malformed claim table exits `2`) |
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// fact-commands-meaning.mjs - `fact pairs` and `fact meaning-check`, the script half of the
|
|
2
2
|
// separate-session meaning verifier. fact pairs writes the (source, report sentence) pairs a
|
|
3
|
-
// reader lane gets and nothing else
|
|
3
|
+
// reader lane gets and nothing else (with --changed-since, only the pairs whose sentence polish
|
|
4
|
+
// rewrote); it honours the brief's `meaning check` field and writes
|
|
4
5
|
// `{ skipped: true }` when it is off. fact meaning-check ingests the readers' verdict files
|
|
5
6
|
// (meaning-check.mjs), writes fidelity-meaning-defects.json (a fidelity record bound to the pairs'
|
|
6
7
|
// artifact_sha256 and report, through writeFidelityRecord), and records the run in
|
|
@@ -14,9 +15,8 @@ import { dirname, join, resolve } from "node:path"
|
|
|
14
15
|
|
|
15
16
|
import { CliError, parseArgs, readJsonFile, sha256Of, writeJsonAtomic, writeTextAtomic } from "./cli-support.mjs"
|
|
16
17
|
import { countDefects } from "./contracts.mjs"
|
|
17
|
-
import { markdownAsHtml, readEdition } from "./fact-commands-verify.mjs"
|
|
18
|
-
import {
|
|
19
|
-
import { validateLedger } from "./fact-ledger-schema.mjs"
|
|
18
|
+
import { ledgerFrom, markdownAsHtml, readEdition, sessionOf } from "./fact-commands-verify.mjs"
|
|
19
|
+
import { pairsChangedSince } from "./fact-commands-polish.mjs"
|
|
20
20
|
import { extractPairs, PAIR_KINDS } from "./fact-pairs.mjs"
|
|
21
21
|
import { FIDELITY_INCOMPLETE, meaningCheckEnabled, requireLockedBrief } from "./fidelity-brief.mjs"
|
|
22
22
|
import { MEANING_RECORD, writeFidelityRecord } from "./fidelity-records.mjs"
|
|
@@ -31,26 +31,11 @@ export const PROMOTION = Object.freeze({ code: "meaning_drift_confirmed", to: "i
|
|
|
31
31
|
/** The command status: fail when any defect blocks delivery under the registry policy. */
|
|
32
32
|
export const meaningStatus = (defects) => (defects.some(blocksDelivery) ? "fail" : "pass")
|
|
33
33
|
|
|
34
|
-
const sessionOf = (flags) => {
|
|
35
|
-
const dir = flags["session-dir"] ?? process.env.SESSION_DIR
|
|
36
|
-
return dir && dir !== true ? resolve(dir) : null
|
|
37
|
-
}
|
|
38
34
|
const inSession = (session, name, flag) => {
|
|
39
35
|
if (session === null) throw new CliError(`${flag} is required without --session-dir (or SESSION_DIR)`)
|
|
40
36
|
return join(session, name)
|
|
41
37
|
}
|
|
42
38
|
|
|
43
|
-
function readLedgerFrom(flags, session) {
|
|
44
|
-
if (flags.ledger === undefined) {
|
|
45
|
-
if (session === null) throw new CliError("--ledger is required without --session-dir (or SESSION_DIR)")
|
|
46
|
-
return readLedger(session)
|
|
47
|
-
}
|
|
48
|
-
const ledger = readJsonFile(flags.ledger)
|
|
49
|
-
const errors = validateLedger(ledger)
|
|
50
|
-
if (errors.length > 0) throw new CliError(`${flags.ledger} is not a valid fact ledger: ${errors[0]}`)
|
|
51
|
-
return ledger
|
|
52
|
-
}
|
|
53
|
-
|
|
54
39
|
function briefState(flags, session) {
|
|
55
40
|
const path = flags.brief ?? inSession(session, "brief.md", "--brief")
|
|
56
41
|
const lock = requireLockedBrief(path)
|
|
@@ -77,10 +62,10 @@ function runPairs(args) {
|
|
|
77
62
|
const edition = readEdition(report, flags)
|
|
78
63
|
const claimsPath = flags.claims ?? (session === null ? null : join(session, "claims.json"))
|
|
79
64
|
const claims = claimsPath !== null && (flags.claims !== undefined || existsSync(claimsPath)) ? readJsonFile(claimsPath) : null
|
|
80
|
-
const
|
|
81
|
-
const ledger = readLedgerFrom(flags, session)
|
|
65
|
+
const ledger = ledgerFrom(flags, session)
|
|
82
66
|
const html = edition.format === "md" ? markdownAsHtml(edition.text, edition.entries, ledger).html : edition.text
|
|
83
|
-
const
|
|
67
|
+
const all = extractPairs(html, ledger, claims)
|
|
68
|
+
const pairs = flags["changed-since"] === undefined ? all : pairsChangedSince(all, flags["changed-since"], ledger, claims)
|
|
84
69
|
const counts = { total: pairs.length, force_strong: pairs.filter((pair) => pair.force_strong).length }
|
|
85
70
|
for (const kind of PAIR_KINDS) counts[kind] = pairs.filter((pair) => pair.kind === kind).length
|
|
86
71
|
const record = { schemaVersion: 1, skipped: false, report: resolve(report), format: edition.format, artifact_sha256: sha256Of(edition.text), pairs_sha256: sha256Of(JSON.stringify(pairs)), counts, verdict_schema: VERDICT_SCHEMA, pairs }
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// fact-commands-polish.mjs - `fact polish-apply` and `fact polish-diff`, the script half of the
|
|
2
|
+
// proofread gate, plus the --changed-since filter of `fact pairs`.
|
|
3
|
+
//
|
|
4
|
+
// The writing lane returns polish-edits.json ([{before, after, reason}]) and never edits the
|
|
5
|
+
// report. polish-apply applies each edit through polish-apply.mjs and writes the result; a
|
|
6
|
+
// rejected (major) or unlocated (minor) edit leaves its region unchanged and is listed with its
|
|
7
|
+
// index and reason so the orchestrator can re-send it; every rejection reason is printed verbatim, one
|
|
8
|
+
// line per rejected edit (index and the first 60 characters of its before), in the summary and in
|
|
9
|
+
// data.rejected_reasons. It exits 0 whenever it wrote the output.
|
|
10
|
+
// polish-diff is the whole-document backstop (polish-diff.mjs) between the pre-polish artifact
|
|
11
|
+
// and any later copy; it exits 1 on a blocker. pairsChangedSince keeps only the pairs whose
|
|
12
|
+
// sentence text (normalized) is not in the pre-polish artifact that a fill map names, so the
|
|
13
|
+
// meaning readers re-check exactly what polish rewrote. No model, no network.
|
|
14
|
+
|
|
15
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
16
|
+
import { join, resolve } from "node:path"
|
|
17
|
+
|
|
18
|
+
import { CliError, parseArgs, readJsonFile, sha256Of, writeJsonAtomic, writeTextAtomic } from "./cli-support.mjs"
|
|
19
|
+
import { countDefects, DEFECT_CODES } from "./contracts.mjs"
|
|
20
|
+
import { editionFormatOf, ledgerFrom, markdownAsHtml, sessionOf } from "./fact-commands-verify.mjs"
|
|
21
|
+
import { extractPairs } from "./fact-pairs.mjs"
|
|
22
|
+
import { applyEdits, POLISH_EDIT_FIELDS, validatePolishEdits } from "./polish-apply.mjs"
|
|
23
|
+
import { diffPolish } from "./polish-diff.mjs"
|
|
24
|
+
import { normalizeText } from "./text-normalize.mjs"
|
|
25
|
+
|
|
26
|
+
export { ledgerFrom, POLISH_EDIT_FIELDS, validatePolishEdits }
|
|
27
|
+
|
|
28
|
+
export const POLISH_RECORD = "polish-defects.json"
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The polish-diff exit policy: only a registry blocker fails the command; majors are reported.
|
|
32
|
+
* Fail-closed like the delivery barrier: a code the registry does not know refuses outright,
|
|
33
|
+
* because a caller-claimed severity may not demote it.
|
|
34
|
+
*/
|
|
35
|
+
export const polishDiffFails = (defects) =>
|
|
36
|
+
defects.some((defect) => {
|
|
37
|
+
if (!Object.hasOwn(DEFECT_CODES, defect?.code)) throw new CliError(`unknown defect code ${defect?.code}`)
|
|
38
|
+
return DEFECT_CODES[defect.code].severity === "blocker"
|
|
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
|
+
const withSeverity = (entry) => ({ ...entry, severity: DEFECT_CODES[entry.code].severity, hint: DEFECT_CODES[entry.code].hint })
|
|
50
|
+
|
|
51
|
+
/** The first 60 characters of an edit's before, on one line. */
|
|
52
|
+
const beforePreview = (before) => (typeof before === "string" ? before : "").replace(/\s+/gu, " ").slice(0, 60)
|
|
53
|
+
|
|
54
|
+
/** One line per rejected edit: its index, the start of its before, and its reason verbatim. */
|
|
55
|
+
const rejectionLine = (entry, edit) => ` rejected edit ${entry.index} ("${beforePreview(edit?.before)}"): ${entry.reason}`
|
|
56
|
+
|
|
57
|
+
function runPolishApply(args) {
|
|
58
|
+
const [report] = args.positionals
|
|
59
|
+
const { flags } = args
|
|
60
|
+
if (!report || flags.edits === undefined || flags.out === undefined) throw new CliError("usage: fact polish-apply <report.html> --edits polish-edits.json --out <report.polished.html> [--ledger F] [--session-dir D]")
|
|
61
|
+
if (editionFormatOf(report, flags.format) === "md") throw new CliError("fact polish-apply takes the filled HTML edition; polish a Markdown edition through its HTML source")
|
|
62
|
+
const html = readText(report)
|
|
63
|
+
const editsText = readText(flags.edits)
|
|
64
|
+
const edits = readJsonFile(flags.edits)
|
|
65
|
+
try {
|
|
66
|
+
validatePolishEdits(edits)
|
|
67
|
+
} catch (error) {
|
|
68
|
+
throw new CliError(`${flags.edits} must be an array of {${Object.keys(POLISH_EDIT_FIELDS).join(", ")}} objects: ${error.message}`)
|
|
69
|
+
}
|
|
70
|
+
const result = applyEdits(html, edits, ledgerFrom(flags))
|
|
71
|
+
writeTextAtomic(flags.out, result.out)
|
|
72
|
+
const defects = [...result.rejected, ...result.unlocated].sort((a, b) => a.index - b.index).map(withSeverity)
|
|
73
|
+
const counts = { applied: result.applied.length, rejected: result.rejected.length, unlocated: result.unlocated.length }
|
|
74
|
+
const data = { out: resolve(flags.out), ...counts, applied_indexes: result.applied, input_sha256: sha256Of(html), edits_sha256: sha256Of(editsText), out_sha256: sha256Of(result.out) }
|
|
75
|
+
const rejected_reasons = result.rejected.map((entry) => rejectionLine(entry, edits[entry.index]))
|
|
76
|
+
const summary = [`fact polish-apply: ${counts.applied} applied, ${counts.rejected} rejected, ${counts.unlocated} unlocated of ${edits.length} edit(s)`, ...rejected_reasons].join("\n")
|
|
77
|
+
return { json: { command: "fact polish-apply", status: "pass", exitCode: 0, defects, data: { ...data, rejected_reasons } }, summary, exitCode: 0 }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function runPolishDiff(args) {
|
|
81
|
+
const { flags } = args
|
|
82
|
+
if (flags.before === undefined || flags.after === undefined) throw new CliError("usage: fact polish-diff --before <pre-polish.html> --after <polished.html> [--ledger F] [--out polish-defects.json] [--session-dir D]")
|
|
83
|
+
const after = readText(flags.after)
|
|
84
|
+
const defects = diffPolish(readText(flags.before), after, ledgerFrom(flags)).map((defect) => ({ ...defect, hint: DEFECT_CODES[defect.code]?.hint ?? null }))
|
|
85
|
+
const counts = countDefects(defects)
|
|
86
|
+
const status = polishDiffFails(defects) ? "fail" : "pass"
|
|
87
|
+
const exitCode = status === "fail" ? 1 : 0
|
|
88
|
+
const record = { command: "fact polish-diff", status, exitCode, before: resolve(flags.before), artifact: resolve(flags.after), artifact_sha256: sha256Of(after), defects, counts }
|
|
89
|
+
const session = sessionOf(flags)
|
|
90
|
+
const out = flags.out ?? (session === null ? null : join(session, POLISH_RECORD))
|
|
91
|
+
if (out !== null) writeJsonAtomic(resolve(out), record)
|
|
92
|
+
const summary = `fact polish-diff: ${status.toUpperCase()} - ${counts.blocker} blocker, ${counts.major} major, ${counts.minor} minor`
|
|
93
|
+
return { json: { ...record, out: out === null ? null : resolve(out) }, summary, exitCode }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const pairKey = (pair) => [pair.kind, pair.sentence_key, pair.claim_id ?? "", normalizeText(pair.sentence)].join("\u0000")
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The pairs whose sentence text changed since the pre-polish artifact a fill map names: a pair is
|
|
100
|
+
* kept unless the same (kind, sentence key, normalized sentence) occurs in that artifact. The map
|
|
101
|
+
* must carry the artifact's `artifact_sha256` and the bytes must still match it, so the filter is
|
|
102
|
+
* fail-closed on a hand-made or stale map.
|
|
103
|
+
* @param {object[]} pairs extractPairs output on the polished edition
|
|
104
|
+
* @param {string} mapPath the pre-polish fill map (fact fill's `<out>.fill-map.json`)
|
|
105
|
+
*/
|
|
106
|
+
export function pairsChangedSince(pairs, mapPath, ledger, claims) {
|
|
107
|
+
const map = readJsonFile(mapPath)
|
|
108
|
+
if (typeof map.artifact !== "string" || !existsSync(map.artifact)) throw new CliError(`${mapPath} names no readable pre-polish artifact`)
|
|
109
|
+
const text = readText(map.artifact)
|
|
110
|
+
if (typeof map.artifact_sha256 !== "string") throw new CliError(`${mapPath} fill map has no artifact_sha256; --changed-since needs the pre-polish hash`)
|
|
111
|
+
if (sha256Of(text) !== map.artifact_sha256) throw new CliError(`${map.artifact} changed after fill; --changed-since needs the pre-polish bytes`)
|
|
112
|
+
const html = map.format === "md" ? markdownAsHtml(text, map.entries, ledger).html : text
|
|
113
|
+
const before = new Map()
|
|
114
|
+
for (const pair of extractPairs(html, ledger, claims)) before.set(pairKey(pair), (before.get(pairKey(pair)) ?? 0) + 1)
|
|
115
|
+
return pairs.filter((pair) => {
|
|
116
|
+
const left = before.get(pairKey(pair)) ?? 0
|
|
117
|
+
if (left === 0) return true
|
|
118
|
+
before.set(pairKey(pair), left - 1)
|
|
119
|
+
return false
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** @param {string[]} argv the arguments after `fact polish-apply` or `fact polish-diff` */
|
|
124
|
+
export function runFactPolish(sub, argv) {
|
|
125
|
+
const args = parseArgs(argv)
|
|
126
|
+
return sub === "polish-apply" ? runPolishApply(args) : runPolishDiff(args)
|
|
127
|
+
}
|
|
@@ -18,6 +18,7 @@ import { CliError, readJsonFile, sha256Of } from "./cli-support.mjs"
|
|
|
18
18
|
import { countDefects } from "./contracts.mjs"
|
|
19
19
|
import { recompute } from "./fact-derive.mjs"
|
|
20
20
|
import { readLedger } from "./fact-ledger.mjs"
|
|
21
|
+
import { validateLedger } from "./fact-ledger-schema.mjs"
|
|
21
22
|
import { FIDELITY_RECORD, writeFidelityRecord } from "./fidelity-records.mjs"
|
|
22
23
|
import { blocksDelivery, checkFidelity } from "./gates-fidelity.mjs"
|
|
23
24
|
import { parseMarkdown } from "./md-lite.mjs"
|
|
@@ -120,6 +121,24 @@ export function markdownAsHtml(text, entries, ledger) {
|
|
|
120
121
|
return { html: `${html}${open ? MD_HTML_BLOCK_RULES[open].group[1] : ""}</body></html>\n`, stale: [...stale] }
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
/** The session dir from --session-dir or SESSION_DIR, or null; a bare flag names no session. */
|
|
125
|
+
export const sessionOf = (flags) => {
|
|
126
|
+
const dir = flags["session-dir"] ?? process.env.SESSION_DIR
|
|
127
|
+
return dir && dir !== true ? resolve(dir) : null
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** The ledger from --ledger (validated) or from the session dir; every fact command loads it here. */
|
|
131
|
+
export function ledgerFrom(flags, session = sessionOf(flags)) {
|
|
132
|
+
if (flags.ledger === undefined) {
|
|
133
|
+
if (session === null) throw new CliError("--ledger is required without --session-dir (or SESSION_DIR)")
|
|
134
|
+
return readLedger(session)
|
|
135
|
+
}
|
|
136
|
+
const ledger = readJsonFile(flags.ledger)
|
|
137
|
+
const errors = validateLedger(ledger)
|
|
138
|
+
if (errors.length > 0) throw new CliError(`${flags.ledger} is not a valid fact ledger: ${errors[0]}`)
|
|
139
|
+
return ledger
|
|
140
|
+
}
|
|
141
|
+
|
|
123
142
|
const MARKDOWN_EXTENSION = /\.(md|markdown)$/iu
|
|
124
143
|
/** The edition format: the explicit flag, else md for a .md or .markdown path (any case), else html. */
|
|
125
144
|
export const editionFormatOf = (path, flag) => flag ?? (MARKDOWN_EXTENSION.test(path) ? "md" : "html")
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// fact-commands.mjs - the `fact` subcommands of report-tools: add, quote, retract, export, fill,
|
|
2
|
-
// derive, verify (fact-commands-verify.mjs), pairs and meaning-check (fact-commands-meaning.mjs)
|
|
2
|
+
// derive, verify (fact-commands-verify.mjs), pairs and meaning-check (fact-commands-meaning.mjs), polish-apply and
|
|
3
|
+
// polish-diff (fact-commands-polish.mjs). Every value reaches the ledger from a source
|
|
3
4
|
// snapshot through a deterministic locator or from a declared derivation; nothing here accepts a
|
|
4
5
|
// typed value. add and quote print the row with 60 chars of source context on each side (JSON
|
|
5
6
|
// with --json). Exit 0 ok, 1 semantic failure (fact_not_located, fill errors, a refused
|
|
@@ -217,6 +218,7 @@ function runDerive(args) {
|
|
|
217
218
|
export async function runFact(argv) {
|
|
218
219
|
const [sub, ...rest] = argv
|
|
219
220
|
if (sub === "pairs" || sub === "meaning-check") return (await import("./fact-commands-meaning.mjs")).runFactMeaning(sub, rest)
|
|
221
|
+
if (sub === "polish-apply" || sub === "polish-diff") return (await import("./fact-commands-polish.mjs")).runFactPolish(sub, rest)
|
|
220
222
|
const args = parseArgs(rest, { booleans: BOOLEANS })
|
|
221
223
|
switch (sub) {
|
|
222
224
|
case "add":
|
|
@@ -234,6 +236,6 @@ export async function runFact(argv) {
|
|
|
234
236
|
case "verify":
|
|
235
237
|
return (await import("./fact-commands-verify.mjs")).runFactVerify(args)
|
|
236
238
|
default:
|
|
237
|
-
throw new CliError("usage: fact <add|quote|retract|export|fill|verify|derive|pairs|meaning-check> ...")
|
|
239
|
+
throw new CliError("usage: fact <add|quote|retract|export|fill|verify|derive|pairs|meaning-check|polish-apply|polish-diff> ...")
|
|
238
240
|
}
|
|
239
241
|
}
|
|
@@ -96,11 +96,11 @@ function lexiconRouted(group, sentence) {
|
|
|
96
96
|
return lexiconChecks(probes).forceStrong.length > 0
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
function quotePairs(sentence, rows,
|
|
99
|
+
function quotePairs(sentence, rows, slug, reportLang) {
|
|
100
100
|
const groups = new Map()
|
|
101
101
|
for (const fact of sentence.facts) {
|
|
102
102
|
const row = rows.get(fact.id)
|
|
103
|
-
if (!row?.quote
|
|
103
|
+
if (!row?.quote) continue
|
|
104
104
|
const group = groups.get(row.quote) ?? { quote: row.quote, row, rows, facts: [], ids: [] }
|
|
105
105
|
group.facts.push(fact)
|
|
106
106
|
if (!group.ids.includes(fact.id)) group.ids.push(fact.id)
|
|
@@ -136,11 +136,11 @@ function claimPairs(ctx, block, sentence, byClaim, slug, reportLang) {
|
|
|
136
136
|
}))
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
function translationPair(node, rows,
|
|
139
|
+
function translationPair(node, rows, slug, reportLang) {
|
|
140
140
|
const id = node.attrs["data-translates"]
|
|
141
141
|
const row = rows.get(id)
|
|
142
142
|
const text = proseText(node)
|
|
143
|
-
if (!row?.quote || text === ""
|
|
143
|
+
if (!row?.quote || text === "") return null
|
|
144
144
|
return {
|
|
145
145
|
kind: "translation",
|
|
146
146
|
sentence_key: sentenceKey(slug, [id]),
|
|
@@ -157,13 +157,11 @@ function translationPair(node, rows, filled, slug, reportLang) {
|
|
|
157
157
|
* @param {string} html the filled report
|
|
158
158
|
* @param {{ rows: object[] }} ledger
|
|
159
159
|
* @param {{ claims: object[] } | object[] | null} claims indexClaims(...) output or its claims array
|
|
160
|
-
* @param {{ fact_id: string }[]} [fillMap] fact fill's map; when given, only facts it filled are paired
|
|
161
160
|
* @returns {object[]} pairs with pair_id P1, P2, ... in document order
|
|
162
161
|
*/
|
|
163
|
-
export function extractPairs(html, ledger, claims
|
|
162
|
+
export function extractPairs(html, ledger, claims) {
|
|
164
163
|
const ctx = buildContext(parseHtml(html), {})
|
|
165
164
|
const rows = new Map((ledger?.rows ?? []).map((row) => [row.fact_id, row]))
|
|
166
|
-
const filled = Array.isArray(fillMap) ? new Set(fillMap.map((entry) => entry.fact_id)) : null
|
|
167
165
|
const byClaim = claimMap(claims)
|
|
168
166
|
const htmlLang = ctx.all.find((node) => node.tag === "html")?.attrs.lang
|
|
169
167
|
const reportLang = htmlLang ? htmlLang.toLowerCase().split("-")[0] : null
|
|
@@ -174,12 +172,12 @@ export function extractPairs(html, ledger, claims, fillMap) {
|
|
|
174
172
|
if (!findings) continue
|
|
175
173
|
const slug = slugOf(block.scope)
|
|
176
174
|
for (const sentence of block.sentences) {
|
|
177
|
-
out.push(...quotePairs(sentence, rows,
|
|
175
|
+
out.push(...quotePairs(sentence, rows, slug, reportLang), ...claimPairs(ctx, block, sentence, byClaim, slug, reportLang))
|
|
178
176
|
}
|
|
179
177
|
for (const node of ctx.util.descendants(block.owner)) {
|
|
180
178
|
if (node.attrs?.["data-translates"] === undefined || seenSpans.has(node)) continue
|
|
181
179
|
seenSpans.add(node)
|
|
182
|
-
const pair = translationPair(node, rows,
|
|
180
|
+
const pair = translationPair(node, rows, slug, reportLang)
|
|
183
181
|
if (pair) out.push(pair)
|
|
184
182
|
}
|
|
185
183
|
}
|