oh-my-opencode 4.19.0 → 4.19.1
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/omomomo.md +1 -1
- package/.agents/skills/omomomo/SKILL.md +1 -1
- package/.opencode/command/omomomo.md +1 -1
- package/README.ja.md +6 -6
- package/README.ko.md +6 -6
- package/README.md +6 -6
- package/README.ru.md +6 -6
- package/README.zh-cn.md +6 -6
- package/dist/agents/atlas/agent.d.ts +1 -1
- package/dist/agents/gpt-prompt-identity.d.ts +3 -0
- package/dist/agents/sisyphus/gpt-5-5.d.ts +1 -1
- package/dist/agents/sisyphus/gpt-task-system-guide.d.ts +1 -0
- package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
- package/dist/cli/index.js +148 -94
- package/dist/cli-node/index.js +148 -94
- package/dist/config/schema/agent-overrides.d.ts +48 -48
- package/dist/config/schema/categories.d.ts +6 -6
- package/dist/config/schema/codegraph.d.ts +2 -0
- package/dist/config/schema/fallback-models.d.ts +5 -5
- package/dist/config/schema/oh-my-opencode-config.d.ts +50 -48
- package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
- package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
- package/dist/hooks/start-work/notepad-scaffold.d.ts +10 -0
- package/dist/index.js +2612 -1473
- package/dist/oh-my-opencode.schema.json +11 -0
- package/dist/shared/omo-process-sweep.d.ts +18 -0
- package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
- package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
- package/dist/skills/ulw-plan/SKILL.md +20 -1
- package/dist/testing/create-plugin-module.d.ts +1 -0
- package/dist/tui.js +66 -56
- package/package.json +13 -13
- package/packages/git-bash-mcp/dist/cli.js +54 -8
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +60 -0
- package/packages/lsp-core/src/lsp/client.ts +14 -1
- package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +2 -2
- package/packages/lsp-core/src/mcp.ts +9 -0
- package/packages/lsp-daemon/dist/cli.js +319 -51
- package/packages/lsp-daemon/dist/client.js +136 -48
- package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -10
- package/packages/lsp-daemon/dist/daemon-client.js +4 -34
- package/packages/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
- package/packages/lsp-daemon/dist/daemon-failure-result.js +38 -0
- package/packages/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
- package/packages/lsp-daemon/dist/daemon-request-error.js +26 -0
- package/packages/lsp-daemon/dist/daemon-server.js +5 -1
- package/packages/lsp-daemon/dist/index.js +137 -48
- package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
- package/packages/lsp-daemon/dist/proxy.js +1 -0
- package/packages/lsp-daemon/dist/version-reap.d.ts +26 -0
- package/packages/lsp-daemon/dist/version-reap.js +182 -0
- package/packages/lsp-tools-mcp/dist/cli.js +61 -10
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -1
- package/packages/lsp-tools-mcp/dist/mcp.js +61 -10
- package/packages/lsp-tools-mcp/dist/tools.js +6 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +64 -8
- 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/bootstrap/src/setup.ts +22 -2
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +555 -251
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +178 -89
- package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +3 -1
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +98 -32
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +5 -0
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +15 -6
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +6 -2
- package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +148 -0
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +31 -2
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +65 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -7
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +57 -3
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +41 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +109 -8
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +2 -2
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +43 -0
- 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 +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +80 -40
- 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/dist/cli.js +11 -0
- 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/rules/src/post-compact-budget.ts +11 -0
- package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +60 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/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/agents/lazycodex-clone-fidelity-reviewer.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +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/ultrawork/skills/ulw-plan/SKILL.md +20 -1
- package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +42 -0
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +6 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.d.ts +21 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +64 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +15 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +85 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -33
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +998 -593
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +10 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +84 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +81 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +7 -59
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +12 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.d.ts +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.js +122 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +8 -6
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +84 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +13 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +49 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +13 -45
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +4 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +20 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +125 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +59 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +6 -58
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +12 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/validation-batch.ts +122 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +76 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +111 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +67 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +57 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +152 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +29 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch-checkpoint.test.ts +147 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch.test.ts +73 -0
- 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-codegraph-init-guidance.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/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 +2 -2
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -2
- 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 +2 -2
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-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-checking-start-work-continuation.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 +41 -41
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +43 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +20 -1
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +9 -9
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +26 -0
- package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +41 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +49 -5
- package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +20 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook session-start",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 4.19.
|
|
10
|
+
"statusMessage": "(OmO 4.19.1) Loading Project Rules"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"type": "command",
|
|
20
20
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit",
|
|
21
21
|
"timeout": 10,
|
|
22
|
-
"statusMessage": "(OmO 4.19.
|
|
22
|
+
"statusMessage": "(OmO 4.19.1) Loading Project Rules"
|
|
23
23
|
}
|
|
24
24
|
]
|
|
25
25
|
}
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"type": "command",
|
|
33
33
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
|
|
34
34
|
"timeout": 10,
|
|
35
|
-
"statusMessage": "(OmO 4.19.
|
|
35
|
+
"statusMessage": "(OmO 4.19.1) Matching Project Rules"
|
|
36
36
|
}
|
|
37
37
|
]
|
|
38
38
|
}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"type": "command",
|
|
46
46
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
47
47
|
"timeout": 10,
|
|
48
|
-
"statusMessage": "(OmO 4.19.
|
|
48
|
+
"statusMessage": "(OmO 4.19.1) Resetting Project Rule Cache"
|
|
49
49
|
}
|
|
50
50
|
]
|
|
51
51
|
}
|
|
@@ -21,6 +21,17 @@ const POST_COMPACT_MIN_RESERVED_TOKENS = 8_000;
|
|
|
21
21
|
const POST_COMPACT_MIN_GUIDE_CHARS = 500;
|
|
22
22
|
const FALLBACK_CONTEXT_WINDOW_TOKENS = 200_000;
|
|
23
23
|
const MODEL_CONTEXT_BUDGETS: readonly ModelContextBudget[] = [
|
|
24
|
+
{ slug: "gpt-5.6-sol", contextWindowTokens: 372_000, effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT },
|
|
25
|
+
{
|
|
26
|
+
slug: "gpt-5.6-terra",
|
|
27
|
+
contextWindowTokens: 372_000,
|
|
28
|
+
effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
slug: "gpt-5.6-luna",
|
|
32
|
+
contextWindowTokens: 372_000,
|
|
33
|
+
effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT,
|
|
34
|
+
},
|
|
24
35
|
{ slug: "gpt-5.5", contextWindowTokens: 272_000, effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT },
|
|
25
36
|
{ slug: "gpt-5.4-mini", contextWindowTokens: 272_000, effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT },
|
|
26
37
|
{
|
|
@@ -76,6 +76,66 @@ describe("post-compact context budget", () => {
|
|
|
76
76
|
expect(budget.maxRuleChars).toBeLessThanOrEqual(budget.maxResultChars);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
+
it("#given gpt-5.6-sol within its 372k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
|
|
80
|
+
// given
|
|
81
|
+
const transcriptPath = writeCompactedTranscript("A".repeat(541_500));
|
|
82
|
+
|
|
83
|
+
// when
|
|
84
|
+
const budget = withPostCompactBudget(CONFIG, { model: "gpt-5.6-sol", transcriptPath });
|
|
85
|
+
|
|
86
|
+
// then
|
|
87
|
+
expect(budget.maxRuleChars).toBe(CONFIG.postCompactMaxRuleChars);
|
|
88
|
+
expect(budget.maxResultChars).toBe(CONFIG.postCompactMaxResultChars);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("#given gpt-5.6-terra within its 372k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
|
|
92
|
+
// given
|
|
93
|
+
const transcriptPath = writeCompactedTranscript("A".repeat(541_500));
|
|
94
|
+
|
|
95
|
+
// when
|
|
96
|
+
const budget = withPostCompactBudget(CONFIG, { model: "gpt-5.6-terra", transcriptPath });
|
|
97
|
+
|
|
98
|
+
// then
|
|
99
|
+
expect(budget.maxRuleChars).toBe(CONFIG.postCompactMaxRuleChars);
|
|
100
|
+
expect(budget.maxResultChars).toBe(CONFIG.postCompactMaxResultChars);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("#given gpt-5.6-luna within its 372k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
|
|
104
|
+
// given
|
|
105
|
+
const transcriptPath = writeCompactedTranscript("A".repeat(541_500));
|
|
106
|
+
|
|
107
|
+
// when
|
|
108
|
+
const budget = withPostCompactBudget(CONFIG, { model: "gpt-5.6-luna", transcriptPath });
|
|
109
|
+
|
|
110
|
+
// then
|
|
111
|
+
expect(budget.maxRuleChars).toBe(CONFIG.postCompactMaxRuleChars);
|
|
112
|
+
expect(budget.maxResultChars).toBe(CONFIG.postCompactMaxResultChars);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("#given provider-prefixed gpt-5.6 variant within its 372k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
|
|
116
|
+
// given
|
|
117
|
+
const transcriptPath = writeCompactedTranscript("A".repeat(541_500));
|
|
118
|
+
|
|
119
|
+
// when
|
|
120
|
+
const budget = withPostCompactBudget(CONFIG, { model: "openai/gpt-5.6-sol", transcriptPath });
|
|
121
|
+
|
|
122
|
+
// then
|
|
123
|
+
expect(budget.maxRuleChars).toBe(CONFIG.postCompactMaxRuleChars);
|
|
124
|
+
expect(budget.maxResultChars).toBe(CONFIG.postCompactMaxResultChars);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("#given unknown model with the same transcript #when resolving post-compact budget #then keeps the 200k fallback floor", () => {
|
|
128
|
+
// given
|
|
129
|
+
const transcriptPath = writeCompactedTranscript("A".repeat(541_500));
|
|
130
|
+
|
|
131
|
+
// when
|
|
132
|
+
const budget = withPostCompactBudget(CONFIG, { model: "unknown-model", transcriptPath });
|
|
133
|
+
|
|
134
|
+
// then
|
|
135
|
+
expect(budget.maxResultChars).toBe(500);
|
|
136
|
+
expect(budget.maxRuleChars).toBe(500);
|
|
137
|
+
});
|
|
138
|
+
|
|
79
139
|
it("#given context pressure marker after compaction #when resolving post-compact budget #then shrinks projected rule injection", () => {
|
|
80
140
|
// given
|
|
81
141
|
const transcriptPath = writeCompactedPressureTranscript("small compacted summary");
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/start-work-continuation/dist/cli.js\" hook stop",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 4.19.
|
|
10
|
+
"statusMessage": "(OmO 4.19.1) Checking Start-Work Continuation"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"type": "command",
|
|
20
20
|
"command": "node \"${PLUGIN_ROOT}/components/start-work-continuation/dist/cli.js\" hook subagent-stop",
|
|
21
21
|
"timeout": 10,
|
|
22
|
-
"statusMessage": "(OmO 4.19.
|
|
22
|
+
"statusMessage": "(OmO 4.19.1) Checking Start-Work Continuation"
|
|
23
23
|
}
|
|
24
24
|
]
|
|
25
25
|
}
|
package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
name = "lazycodex-clone-fidelity-reviewer"
|
|
2
2
|
description = "Read-only LazyCodex clone / design-system fidelity reviewer. Verifies clone and design-port work is a rigorous, token-driven design system, not a pasted screenshot or hardcoded fake."
|
|
3
3
|
nickname_candidates = ["Clone Fidelity Reviewer"]
|
|
4
|
-
model = "gpt-5.6-
|
|
5
|
-
model_reasoning_effort = "
|
|
4
|
+
model = "gpt-5.6-terra"
|
|
5
|
+
model_reasoning_effort = "high"
|
|
6
6
|
|
|
7
7
|
developer_instructions = """
|
|
8
8
|
Role: clone / design-system fidelity reviewer. Read-only.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
name = "lazycodex-code-reviewer"
|
|
2
2
|
description = "Read-only LazyCodex code-quality reviewer. Audits diffs, tests, and risk with strict artifact-backed findings."
|
|
3
3
|
nickname_candidates = ["Code Reviewer"]
|
|
4
|
-
model = "gpt-5.6-
|
|
5
|
-
model_reasoning_effort = "
|
|
4
|
+
model = "gpt-5.6-terra"
|
|
5
|
+
model_reasoning_effort = "medium"
|
|
6
6
|
|
|
7
7
|
developer_instructions = """
|
|
8
8
|
Role: code quality reviewer. Read-only.
|
|
@@ -2,7 +2,7 @@ name = "lazycodex-gate-reviewer"
|
|
|
2
2
|
description = "Read-only LazyCodex gate reviewer. Re-audits executor, code review, and QA artifacts before final approval."
|
|
3
3
|
nickname_candidates = ["Gate Reviewer"]
|
|
4
4
|
model = "gpt-5.6-sol"
|
|
5
|
-
model_reasoning_effort = "
|
|
5
|
+
model_reasoning_effort = "low"
|
|
6
6
|
|
|
7
7
|
developer_instructions = """
|
|
8
8
|
Role: final gate reviewer. Read-only.
|
|
@@ -2,7 +2,7 @@ name = "lazycodex-worker-high"
|
|
|
2
2
|
description = "LazyCodex high-difficulty implementation worker, sized for LARGE changes: a new module or abstraction, a cross-module refactor, concurrency/security/migration work, or any real, complex, big problem that has ONE clear goal. Owns the smallest correct change and records evidence before claiming completion."
|
|
3
3
|
nickname_candidates = ["High Worker"]
|
|
4
4
|
model = "gpt-5.6-sol"
|
|
5
|
-
model_reasoning_effort = "
|
|
5
|
+
model_reasoning_effort = "medium"
|
|
6
6
|
|
|
7
7
|
developer_instructions = """
|
|
8
8
|
Role: implementation executor. You own the task end to end.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
name = "lazycodex-worker-medium"
|
|
2
2
|
description = "LazyCodex medium-difficulty implementation worker, sized for MID-SIZED changes: a standard feature inside existing layers, touching a few files along established patterns. Owns the smallest correct change and records evidence before claiming completion."
|
|
3
3
|
nickname_candidates = ["Medium Worker"]
|
|
4
|
-
model = "gpt-5.6-
|
|
5
|
-
model_reasoning_effort = "
|
|
4
|
+
model = "gpt-5.6-terra"
|
|
5
|
+
model_reasoning_effort = "high"
|
|
6
6
|
|
|
7
7
|
developer_instructions = """
|
|
8
8
|
Role: implementation executor. You own the task end to end.
|
|
@@ -2,7 +2,7 @@ name = "plan"
|
|
|
2
2
|
description = "Strategic planning consultant for work with unresolved design uncertainty after discovery. Produces one executable plan; never implements. Writes the plan to .omo/plans/<slug>.md."
|
|
3
3
|
nickname_candidates = ["Planner"]
|
|
4
4
|
model = "gpt-5.6-sol"
|
|
5
|
-
model_reasoning_effort = "
|
|
5
|
+
model_reasoning_effort = "high"
|
|
6
6
|
|
|
7
7
|
developer_instructions = """
|
|
8
8
|
Role: strategic planning consultant. You produce a single, bulletproof, executable work plan only when discovery leaves unresolved design uncertainty.
|
|
@@ -60,7 +60,7 @@ function buildUltraworkAdditionalContext(options = {}) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// components/ultrawork/src/codex-hook.ts
|
|
63
|
-
var ULTRAWORK_CURRENT_PROMPT_PATTERN = /(?:ultrawork|ulw)/i;
|
|
63
|
+
var ULTRAWORK_CURRENT_PROMPT_PATTERN = /(?:ultrawork|ulw(?!-(?:plan|research)))/i;
|
|
64
64
|
var ULTRAWORK_DIRECTIVE_MARKER = "<ultrawork-mode>";
|
|
65
65
|
var TRANSCRIPT_SEARCH_BYTES = 512000;
|
|
66
66
|
var CONTEXT_PRESSURE_MARKERS = [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/codex-ultrawork",
|
|
3
|
-
"version": "4.19.
|
|
3
|
+
"version": "4.19.1",
|
|
4
4
|
"description": "Codex plugin that injects the ultrawork orchestration directive and ships LazyCodex planning, review, QA, and gate agent roles.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@11.12.1",
|
|
@@ -13,11 +13,30 @@ You are **Prometheus**, a planning consultant. You turn a vague or large request
|
|
|
13
13
|
|
|
14
14
|
Outcome-first: explore a lot, ask few sharp questions - or none, when the intent is fuzzy (see routing) - and stop the moment the plan is done.
|
|
15
15
|
|
|
16
|
+
## MANDATORY OPENING ANNOUNCEMENT
|
|
17
|
+
|
|
18
|
+
The FIRST user-visible line of the turn that activates this skill MUST be exactly:
|
|
19
|
+
|
|
20
|
+
`ULW-PLAN MODE ENABLED!`
|
|
21
|
+
|
|
22
|
+
If another active mode mandates its own first line (ultrawork does), print that line first and this marker on the next line - both contracts stay satisfied.
|
|
23
|
+
|
|
24
|
+
Directly under the marker, before any exploration, state the working contract once, in your own words, carrying ALL of these commitments:
|
|
25
|
+
|
|
26
|
+
1. **Persona + no-implementation pledge** - from now on you work as Prometheus, a planning consultant, and you will never start implementation - no product-code edits, no implementer subagents - until the user explicitly says okay; even then, approval authorizes writing the plan only, and execution starts in a separate worker session (e.g. `$start-work`).
|
|
27
|
+
2. **Workflow preview** - the order of what happens next: parallel read-only exploration (plus outside research when the repo cannot answer) until the open unknowns are resolved; the intent verdict from INTENT ROUTING, announced; questions to the user ONLY when a genuine owner-decision survives exploration - or when exploration and research both come back empty on a fork the plan cannot proceed without; then the approval brief, and the plan is written only after the explicit okay.
|
|
28
|
+
|
|
29
|
+
Example opening (adapt the wording, keep every commitment):
|
|
30
|
+
|
|
31
|
+
> ULW-PLAN MODE ENABLED!
|
|
32
|
+
> From now on I am working as Prometheus, a planning consultant. I will not start any implementation until you explicitly say okay - and approval authorizes writing the plan only; execution starts separately (e.g. `$start-work`).
|
|
33
|
+
> Next, in order: (1) parallel read-only exploration and research, (2) intent verdict announced (CLEAR or UNCLEAR, plus whether high-accuracy review is required), (3) questions only for the forks exploration cannot settle - or where research finds nothing on a blocking decision, (4) approval brief, then (5) the plan is written after your okay.
|
|
34
|
+
|
|
16
35
|
## INTENT ROUTING - pick ONE intent reference
|
|
17
36
|
|
|
18
37
|
**Review modifiers are a gate trigger, not a style cue.** If the user says "high accuracy", "ultra high accuracy", "고정밀", "deep review", or equivalent - in ANY turn, even appended to a follow-up question and even after the plan already exists - set `review_required: true` in the draft: the dual high-accuracy review (native `momus` + the independent Codex CLI review) is now REQUIRED before handoff, and if the plan already exists you run it this same turn. Answering the current question more carefully does NOT satisfy it. This does NOT choose CLEAR/UNCLEAR and does NOT suppress interview.
|
|
19
38
|
|
|
20
|
-
After grounding, make ONE judgment, record `intent: clear|unclear` plus `review_required`, **ANNOUNCE both to the user in one line**, then load ONE intent reference (you ALSO read `references/full-workflow.md` for the shared mechanics - see below). The test keys on whether the desired **OUTCOME** is clear, NOT on request length.
|
|
39
|
+
After grounding, make ONE judgment, record `intent: clear|unclear` plus `review_required`, **ANNOUNCE both to the user in one line**, then load ONE intent reference (you ALSO read `references/full-workflow.md` for the shared mechanics - see below). The test keys on whether the desired **OUTCOME** is clear, NOT on request length. This verdict line and the opening announcement above are the two mandatory user-visible signals of a planning session - it tells the user whether they will be interviewed and whether high-accuracy review is already requested; never skip either.
|
|
21
40
|
|
|
22
41
|
> "Intent: **CLEAR**, review required - you specified the endpoint and asked for high accuracy. I will ask only the genuine forks, then run the high-accuracy review after approval."
|
|
23
42
|
> "Intent: **UNCLEAR**, review required - 'make auth better' is open-ended and you asked for high accuracy. I will choose best-practice defaults, then run the high-accuracy review automatically."
|
|
@@ -2,7 +2,7 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
|
|
3
3
|
import { buildUltraworkAdditionalContext, type UltraworkAdditionalContextOptions } from "./skill-pointer.js";
|
|
4
4
|
|
|
5
|
-
const ULTRAWORK_CURRENT_PROMPT_PATTERN = /(?:ultrawork|ulw)/i;
|
|
5
|
+
const ULTRAWORK_CURRENT_PROMPT_PATTERN = /(?:ultrawork|ulw(?!-(?:plan|research)))/i;
|
|
6
6
|
const ULTRAWORK_DIRECTIVE_MARKER = "<ultrawork-mode>";
|
|
7
7
|
const TRANSCRIPT_SEARCH_BYTES = 512_000;
|
|
8
8
|
const CONTEXT_PRESSURE_MARKERS = [
|
package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts
CHANGED
|
@@ -88,6 +88,48 @@ describe("codex ultrawork trigger policy", () => {
|
|
|
88
88
|
expect(isUltraworkPrompt(prompt)).toBe(true);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
+
it("#given prompt invokes ulw-plan or ulw-research skills #when hook runs #then does not emit directive", () => {
|
|
92
|
+
// given
|
|
93
|
+
const prompts = [
|
|
94
|
+
"$omo:ulw-plan refactor the auth module",
|
|
95
|
+
"omo:ulw-plan",
|
|
96
|
+
"/ulw-plan",
|
|
97
|
+
"ulw-plan",
|
|
98
|
+
"$omo:ulw-research how does the hook pipeline work",
|
|
99
|
+
"ulw-research",
|
|
100
|
+
"please run ULW-PLAN for this",
|
|
101
|
+
] as const;
|
|
102
|
+
|
|
103
|
+
// when
|
|
104
|
+
const outputs = prompts.map((prompt) => runUserPromptSubmitHook({ hook_event_name: "UserPromptSubmit", prompt }));
|
|
105
|
+
|
|
106
|
+
// then
|
|
107
|
+
expect(outputs).toEqual(["", "", "", "", "", "", ""]);
|
|
108
|
+
expect(prompts.map((prompt) => isUltraworkPrompt(prompt))).toEqual([false, false, false, false, false, false, false]);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("#given prompt contains ultrawork or standalone ulw #when hook runs #then emits directive", () => {
|
|
112
|
+
// given
|
|
113
|
+
const prompts = [
|
|
114
|
+
"ultrawork this change",
|
|
115
|
+
"ulw",
|
|
116
|
+
"ulw ",
|
|
117
|
+
"ulw fix this failing test",
|
|
118
|
+
"ulw-loop keep iterating until green",
|
|
119
|
+
] as const;
|
|
120
|
+
|
|
121
|
+
// when
|
|
122
|
+
const outputs = prompts.map((prompt) => runUserPromptSubmitHook({ hook_event_name: "UserPromptSubmit", prompt }));
|
|
123
|
+
|
|
124
|
+
// then
|
|
125
|
+
for (const output of outputs) {
|
|
126
|
+
const parsed = parseHookOutput(output);
|
|
127
|
+
expect(parsed.hookSpecificOutput.hookEventName).toBe("UserPromptSubmit");
|
|
128
|
+
expect(parsed.hookSpecificOutput.additionalContext).toMatch(/^<ultrawork-mode>/);
|
|
129
|
+
}
|
|
130
|
+
expect(prompts.map((prompt) => isUltraworkPrompt(prompt))).toEqual([true, true, true, true, true]);
|
|
131
|
+
});
|
|
132
|
+
|
|
91
133
|
it("#given prior transcript contains triggers but current prompt does not #when hook runs #then does not emit directive", () => {
|
|
92
134
|
// given
|
|
93
135
|
const payload = {
|
|
@@ -11,11 +11,11 @@ Every subcommand below is implemented. Pass `--json` where supported for machine
|
|
|
11
11
|
| Subcommand | Purpose |
|
|
12
12
|
|------------|---------|
|
|
13
13
|
| `omo ulw-loop help` | Print CLI usage. |
|
|
14
|
-
| `omo ulw-loop create-goals` | Create repo-native goals and seed success criteria from a brief
|
|
14
|
+
| `omo ulw-loop create-goals` | Create repo-native goals and seed success criteria from a brief; optionally define review-boundary validation batches with `--validation-batch-json`. |
|
|
15
15
|
| `omo ulw-loop status` | Report active goal, criteria, and evidence state. |
|
|
16
|
-
| `omo ulw-loop complete-goals` |
|
|
17
|
-
| `omo ulw-loop checkpoint` | Gate a goal transition with evidence;
|
|
18
|
-
| `omo ulw-loop steer` | Apply
|
|
16
|
+
| `omo ulw-loop complete-goals` | Manual fallback to start or resume the next eligible goal, or report aggregate completion / blocked handoff. |
|
|
17
|
+
| `omo ulw-loop checkpoint` | Gate a goal transition with evidence; complete checkpoints auto-start the next eligible goal by default, with `--no-advance` preserving the legacy two-call flow. |
|
|
18
|
+
| `omo ulw-loop steer` | Apply one steering mutation proposal or an atomic all-or-nothing batch with `--proposals-json`. |
|
|
19
19
|
| `omo ulw-loop add-goal` | Append a goal to the active plan. |
|
|
20
20
|
| `omo ulw-loop criteria` | Inspect one goal's success criteria. |
|
|
21
21
|
| `omo ulw-loop record-evidence` | Record observable evidence for one criterion. |
|
|
@@ -23,6 +23,8 @@ Every subcommand below is implemented. Pass `--json` where supported for machine
|
|
|
23
23
|
|
|
24
24
|
The final quality gate parsed by `checkpoint` validates `codeReview`, `manualQa`, `gateReview`, `iteration`, and `criteriaCoverage`. `criteriaCoverage` records the original intent, desired outcome, user-facing outcome review, pass counts, and covered adversarial classes.
|
|
25
25
|
|
|
26
|
+
Validation batches are optional review boundaries declared at plan creation with `--validation-batch-json '[{"batchId":"VB001","memberIds":[...],"finalGoalId":"..."}]'`. The batch-final goal cannot complete until every other member is complete or superseded-resolved, every member criterion is pass, and a quality gate's coverage counts match the recomputed member criteria. Steering split/supersede mutations keep batch membership consistent and record `batch_updated`.
|
|
27
|
+
|
|
26
28
|
## Codex Plugin
|
|
27
29
|
|
|
28
30
|
This directory is a component of the aggregate `@sisyphuslabs/omo-codex-plugin` root. Plugin discovery (`.codex-plugin/plugin.json`) is owned by that aggregate root, not by this component. The component ships:
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type CheckpointUlwLoopArgs, type CheckpointUlwLoopResult } from "./checkpoint.js";
|
|
2
|
+
import { type UlwLoopGoalInstruction } from "./codex-goal-instruction.js";
|
|
3
|
+
import type { UlwLoopScope } from "./paths.js";
|
|
4
|
+
import type { UlwLoopItem } from "./types.js";
|
|
5
|
+
type ContinuationNext = {
|
|
6
|
+
readonly resumed: boolean;
|
|
7
|
+
readonly goal: UlwLoopItem;
|
|
8
|
+
readonly instruction: UlwLoopGoalInstruction;
|
|
9
|
+
} | {
|
|
10
|
+
readonly done: true;
|
|
11
|
+
readonly blocked: boolean;
|
|
12
|
+
readonly handoff: string;
|
|
13
|
+
};
|
|
14
|
+
export type CheckpointAndContinueResult = CheckpointUlwLoopResult & {
|
|
15
|
+
readonly next?: ContinuationNext;
|
|
16
|
+
};
|
|
17
|
+
export declare function checkpointAndContinue(repoRoot: string, args: CheckpointUlwLoopArgs & {
|
|
18
|
+
readonly advance: boolean;
|
|
19
|
+
}, scope?: UlwLoopScope): Promise<CheckpointAndContinueResult>;
|
|
20
|
+
export declare function checkpoint(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { checkpointUlwLoop } from "./checkpoint.js";
|
|
2
|
+
import { hasFlag, parseCodexGoalJson, readValue } from "./cli-arg-parser.js";
|
|
3
|
+
import { blockedDecisionHandoff, printJson } from "./cli-output.js";
|
|
4
|
+
import { buildCodexGoalInstruction } from "./codex-goal-instruction.js";
|
|
5
|
+
import { startNextUlwLoop, summarizeUlwLoopPlan } from "./plan-crud.js";
|
|
6
|
+
import { UlwLoopError } from "./types.js";
|
|
7
|
+
export async function checkpointAndContinue(repoRoot, args, scope) {
|
|
8
|
+
const result = await checkpointUlwLoop(repoRoot, args, scope);
|
|
9
|
+
if (args.status !== "complete" || result.aggregateCompletion !== undefined || !args.advance)
|
|
10
|
+
return result;
|
|
11
|
+
const next = await startNextUlwLoop(repoRoot, {}, scope);
|
|
12
|
+
if ("done" in next)
|
|
13
|
+
return { ...result, plan: next.plan, next: doneNext(next.plan) };
|
|
14
|
+
const instruction = buildCodexGoalInstruction({ plan: next.plan, goal: next.goal });
|
|
15
|
+
return { ...result, plan: next.plan, next: { resumed: next.resumed, goal: next.goal, instruction } };
|
|
16
|
+
}
|
|
17
|
+
export async function checkpoint(repoRoot, argv, json, scope) {
|
|
18
|
+
const goalId = required(argv, "--goal-id");
|
|
19
|
+
const statusValue = checkpointStatus(required(argv, "--status"));
|
|
20
|
+
const evidence = required(argv, "--evidence");
|
|
21
|
+
const codexGoalJson = await parseCodexGoalJson(statusValue === "complete" ? required(argv, "--codex-goal-json") : readValue(argv, "--codex-goal-json"));
|
|
22
|
+
if (statusValue === "complete" && codexGoalJson === undefined) {
|
|
23
|
+
throw new UlwLoopError("Missing --codex-goal-json.", "ULW_LOOP_CODEX_GOAL_JSON_REQUIRED");
|
|
24
|
+
}
|
|
25
|
+
const qualityGateJson = readValue(argv, "--quality-gate-json");
|
|
26
|
+
const args = {
|
|
27
|
+
goalId,
|
|
28
|
+
status: statusValue,
|
|
29
|
+
evidence,
|
|
30
|
+
advance: !hasFlag(argv, "--no-advance"),
|
|
31
|
+
...(codexGoalJson === undefined ? {} : { codexGoalJson }),
|
|
32
|
+
...(qualityGateJson === undefined ? {} : { qualityGateJson }),
|
|
33
|
+
};
|
|
34
|
+
const result = await checkpointAndContinue(repoRoot, args, scope);
|
|
35
|
+
if (json)
|
|
36
|
+
printJson({ ok: true, ...result, summary: summarizeUlwLoopPlan(result.plan) });
|
|
37
|
+
else
|
|
38
|
+
printCheckpointText(result);
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
function printCheckpointText(result) {
|
|
42
|
+
process.stdout.write(`ulw-loop checkpoint: ${result.goal.id} -> ${result.goal.status}\n`);
|
|
43
|
+
if (result.next === undefined)
|
|
44
|
+
return;
|
|
45
|
+
if ("instruction" in result.next)
|
|
46
|
+
process.stdout.write(`${result.next.instruction.text}\n`);
|
|
47
|
+
else
|
|
48
|
+
process.stdout.write(`${result.next.handoff || "ulw-loop: all goals complete"}\n`);
|
|
49
|
+
}
|
|
50
|
+
function doneNext(plan) {
|
|
51
|
+
const handoff = blockedDecisionHandoff(plan);
|
|
52
|
+
return { done: true, blocked: handoff.length > 0, handoff };
|
|
53
|
+
}
|
|
54
|
+
function required(argv, flag) {
|
|
55
|
+
const value = readValue(argv, flag)?.trim();
|
|
56
|
+
if (value)
|
|
57
|
+
return value;
|
|
58
|
+
throw new UlwLoopError(`Missing ${flag}.`, "ULW_LOOP_ARGUMENT_MISSING", { details: { flag } });
|
|
59
|
+
}
|
|
60
|
+
function checkpointStatus(value) {
|
|
61
|
+
if (value === "complete" || value === "failed" || value === "blocked")
|
|
62
|
+
return value;
|
|
63
|
+
throw new UlwLoopError("Missing or invalid --status; expected complete, failed, or blocked.", "ULW_LOOP_STATUS_INVALID", { details: { status: value } });
|
|
64
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// biome-ignore-all format: checkpoint stays under the pure LOC ceiling.
|
|
2
2
|
import { existsSync, statSync } from "node:fs";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { resolve } from "node:path";
|
|
@@ -6,9 +6,11 @@ import { buildTaskScopedAggregateReconciliationHint, canReconcileActiveFinalTask
|
|
|
6
6
|
import { formatCodexGoalReconciliation, readCodexGoalSnapshotInput, reconcileCodexGoalSnapshot, } from "./codex-goal-snapshot.js";
|
|
7
7
|
import { requireAllCriteriaPass, requireAllPlanCriteriaPass, requireEssentialCriteriaPass } from "./evidence.js";
|
|
8
8
|
import { codexGoalMode, compatibleCodexObjectives, expectedCodexObjective, isFinalRunCompletionCandidate, } from "./goal-status.js";
|
|
9
|
+
import { ulwLoopAttemptEvidenceDir } from "./paths.js";
|
|
9
10
|
import { appendLedger, readUlwLoopPlan, withUlwLoopMutationLock, writePlan } from "./plan-io.js";
|
|
10
11
|
import { classifyExternalAuthorizationBlocker, clearGoalBlockerFields, sameBlockerOccurrences, validateQualityGate, } from "./quality-gate.js";
|
|
11
12
|
import { iso, UlwLoopError } from "./types.js";
|
|
13
|
+
import { batchClosedBy, requireAllValidationBatchesClosed, requireBatchFinalReady, requireBatchGate } from "./validation-batch.js";
|
|
12
14
|
const QUALITY_GATE_FS = { existsSync, statSync };
|
|
13
15
|
function ulwLoopFail(message, code) {
|
|
14
16
|
throw new UlwLoopError(message, code);
|
|
@@ -112,9 +114,11 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
|
|
|
112
114
|
if (args.status === "complete") {
|
|
113
115
|
const aggregate = codexGoalMode(plan) === "aggregate";
|
|
114
116
|
const final = isFinalRunCompletionCandidate(plan, goal);
|
|
117
|
+
const closesBatch = batchClosedBy(plan, goal.id) !== undefined;
|
|
115
118
|
if (final) {
|
|
116
119
|
requireAllCriteriaPass(goal);
|
|
117
120
|
requireAllPlanCriteriaPass(plan);
|
|
121
|
+
requireAllValidationBatchesClosed(plan, goal.id);
|
|
118
122
|
}
|
|
119
123
|
else if (aggregate)
|
|
120
124
|
requireEssentialCriteriaPass(goal);
|
|
@@ -144,9 +148,13 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
|
|
|
144
148
|
if (!taskScoped)
|
|
145
149
|
throw new UlwLoopError(`${formatCodexGoalReconciliation(reconciliation)}${aggregate && snapshot?.status === "complete" && objective !== undefined ? buildTaskScopedAggregateReconciliationHint(goal, final) : ""}`, "ulw_loop_codex_snapshot_mismatch");
|
|
146
150
|
}
|
|
151
|
+
if (closesBatch)
|
|
152
|
+
requireBatchFinalReady(plan, goal);
|
|
153
|
+
if (closesBatch && args.qualityGateJson === undefined)
|
|
154
|
+
throw new UlwLoopError("Validation batch final checkpoint requires --quality-gate-json.", "ULW_LOOP_VALIDATION_BATCH_GATE_REQUIRED");
|
|
147
155
|
if (final)
|
|
148
156
|
aggregateCompletion = makeAggregateCompletion(now, evidence, codexGoal);
|
|
149
|
-
if (final || aggregateCompletion !== undefined)
|
|
157
|
+
if (final || aggregateCompletion !== undefined || closesBatch) {
|
|
150
158
|
qualityGate = validateQualityGate(await readJsonInput(args.qualityGateJson, repoRoot), {
|
|
151
159
|
repoRoot,
|
|
152
160
|
fs: QUALITY_GATE_FS,
|
|
@@ -154,6 +162,8 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
|
|
|
154
162
|
? { currentAttemptDir: ulwLoopAttemptEvidenceDir(goal.id, goal.attempt, scope) }
|
|
155
163
|
: {}),
|
|
156
164
|
});
|
|
165
|
+
requireBatchGate(plan, goal, qualityGate);
|
|
166
|
+
}
|
|
157
167
|
goal.status = "complete";
|
|
158
168
|
goal.completedAt = now;
|
|
159
169
|
goal.evidence = evidence;
|
|
@@ -172,6 +182,9 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
|
|
|
172
182
|
await writePlan(repoRoot, plan, scope);
|
|
173
183
|
const ledgerEntry = buildLedger(now, args, goal, qualityGate, codexGoal, aggregateCompletion);
|
|
174
184
|
await appendLedger(repoRoot, ledgerEntry, scope);
|
|
185
|
+
const closedBatch = args.status === "complete" ? batchClosedBy(plan, goal.id) : undefined;
|
|
186
|
+
if (closedBatch !== undefined)
|
|
187
|
+
await appendLedger(repoRoot, { at: now, kind: "batch_closed", goalId: goal.id, message: closedBatch.batchId }, scope);
|
|
175
188
|
return aggregateCompletion === undefined
|
|
176
189
|
? { plan, goal, ledgerEntry }
|
|
177
190
|
: { plan, goal, ledgerEntry, aggregateCompletion };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// biome-ignore-all format: keep this module under the mandated pure LOC budget.
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { UlwLoopError } from "./types.js";
|
|
4
|
-
const VALUE_FLAGS = new Set("--brief --brief-file --session-id --codex-goal-mode --goal --goal-id --criterion-id --status --evidence --notes --codex-goal-json --quality-gate-json --kind --rationale --title --objective --target-goal-id --source --after-json --directive-json --directive-file --idempotency-key".split(" "));
|
|
4
|
+
const VALUE_FLAGS = new Set("--brief --brief-file --session-id --codex-goal-mode --validation-batch-json --goal --goal-id --criterion-id --status --evidence --notes --codex-goal-json --quality-gate-json --kind --rationale --title --objective --target-goal-id --source --after-json --directive-json --directive-file --idempotency-key --proposals-json".split(" "));
|
|
5
5
|
const SUBCOMMANDS = new Set("create-goals status complete-goals criteria record-evidence checkpoint steer add-goal record-review-blockers".split(" "));
|
|
6
6
|
export function hasFlag(argv, flag) { return argv.includes(flag); }
|
|
7
7
|
export function readValue(argv, flag) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { checkpoint } from "./checkpoint-continuation.js";
|
|
1
2
|
import { hasFlag, readValue } from "./cli-arg-parser.js";
|
|
2
3
|
import { printJsonError, ULW_LOOP_HELP } from "./cli-output.js";
|
|
3
|
-
import { addGoal, captureEvidence,
|
|
4
|
+
import { addGoal, captureEvidence, completeGoals, createGoals, criteria, reviewBlockers, status, steer, } from "./cli-subcommands.js";
|
|
4
5
|
import { resolveUlwLoopSessionIdFromEnv } from "./paths.js";
|
|
5
6
|
import { UlwLoopError } from "./types.js";
|
|
6
7
|
export const ULW_LOOP_SUBCOMMANDS = [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { UlwLoopCodexGoalMode, UlwLoopPlan } from "./types.js";
|
|
2
|
-
export declare const ULW_LOOP_HELP = "Usage:\n omo ulw-loop create-goals --brief \"...\" [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--force] [--json]\n omo ulw-loop status [--json]\n omo ulw-loop complete-goals [--retry-failed] [--json]\n omo ulw-loop criteria --goal-id <id> [--json]\n omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence \"...\" [--notes \"...\"] [--json]\n omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence \"...\" --codex-goal-json <...> [--quality-gate-json <...>] [--json]\n omo ulw-loop steer --kind <kind> ... --evidence \"...\" --rationale \"...\" [--json]\n omo ulw-loop add-goal --title \"...\" --objective \"...\" [--json]\n omo ulw-loop record-review-blockers --goal-id <id> --title \"...\" --objective \"...\" --evidence \"...\" --codex-goal-json <...> [--json]\n\nAll subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.";
|
|
2
|
+
export declare const ULW_LOOP_HELP = "Usage:\n omo ulw-loop create-goals --brief \"...\" [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]\n omo ulw-loop status [--json]\n omo ulw-loop complete-goals [--retry-failed] [--json]\n omo ulw-loop criteria --goal-id <id> [--json]\n omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence \"...\" [--notes \"...\"] [--json]\n omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence \"...\" --codex-goal-json <...> [--quality-gate-json <...>] [--no-advance] [--json]\n omo ulw-loop steer --kind <kind> ... --evidence \"...\" --rationale \"...\" [--proposals-json <json-or-path>] [--json]\n omo ulw-loop add-goal --title \"...\" --objective \"...\" [--json]\n omo ulw-loop record-review-blockers --goal-id <id> --title \"...\" --objective \"...\" --evidence \"...\" --codex-goal-json <...> [--json]\n\nAll subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.";
|
|
3
3
|
export declare function printJson(value: unknown): void;
|
|
4
4
|
export declare function printJsonError(error: unknown): void;
|
|
5
5
|
export declare function printStatus(plan: UlwLoopPlan): void;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { UlwLoopError } from "./types.js";
|
|
2
2
|
export const ULW_LOOP_HELP = `Usage:
|
|
3
|
-
omo ulw-loop create-goals --brief "..." [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--force] [--json]
|
|
3
|
+
omo ulw-loop create-goals --brief "..." [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]
|
|
4
4
|
omo ulw-loop status [--json]
|
|
5
5
|
omo ulw-loop complete-goals [--retry-failed] [--json]
|
|
6
6
|
omo ulw-loop criteria --goal-id <id> [--json]
|
|
7
7
|
omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence "..." [--notes "..."] [--json]
|
|
8
|
-
omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence "..." --codex-goal-json <...> [--quality-gate-json <...>] [--json]
|
|
9
|
-
omo ulw-loop steer --kind <kind> ... --evidence "..." --rationale "..." [--json]
|
|
8
|
+
omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence "..." --codex-goal-json <...> [--quality-gate-json <...>] [--no-advance] [--json]
|
|
9
|
+
omo ulw-loop steer --kind <kind> ... --evidence "..." --rationale "..." [--proposals-json <json-or-path>] [--json]
|
|
10
10
|
omo ulw-loop add-goal --title "..." --objective "..." [--json]
|
|
11
11
|
omo ulw-loop record-review-blockers --goal-id <id> --title "..." --objective "..." --evidence "..." --codex-goal-json <...> [--json]
|
|
12
12
|
|