oh-my-opencode 5.0.0-beta.1 → 5.0.0-beta.11
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 +44 -16
- package/.agents/skills/publish/SKILL.md +44 -16
- package/.agents/skills/work-with-pr/SKILL.md +37 -23
- package/.opencode/command/publish.md +44 -16
- package/.opencode/skills/work-with-pr/SKILL.md +37 -23
- package/README.md +12 -1
- package/dist/agents/atlas/agent.d.ts +0 -1
- package/dist/agents/sisyphus/grok-4.d.ts +20 -0
- package/dist/agents/sisyphus/index.d.ts +2 -0
- package/dist/agents/sisyphus-agent-config.d.ts +6 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
- package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/index.js +805 -534
- package/dist/cli/run/on-complete-hook.d.ts +2 -0
- package/dist/cli-node/index.js +805 -534
- package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
- package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
- package/dist/index.js +1566 -1217
- package/dist/shared/normalize-sdk-response.d.ts +1 -0
- package/dist/shared/shell-env.d.ts +1 -1
- package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/dist/skills/frontend/SKILL.md +10 -7
- package/dist/skills/frontend/references/design/_INDEX.md +1 -0
- package/dist/skills/frontend/references/design/stylegallery.md +80 -0
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
- package/dist/skills/ulw-plan/SKILL.md +2 -2
- package/dist/skills/ulw-plan/references/full-workflow.md +27 -3
- package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
- package/dist/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/dist/tools/delegate-task/builtin-categories.d.ts +1 -0
- package/dist/tools/delegate-task/builtin-category-definition.d.ts +1 -0
- package/dist/tools/delegate-task/tool-description.d.ts +3 -1
- package/dist/tui.js +184 -83
- package/package.json +21 -19
- package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
- package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
- package/packages/lsp-core/src/lsp/client-wrapper.test.ts +66 -13
- package/packages/lsp-core/src/lsp/client-wrapper.ts +70 -18
- package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
- package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
- package/packages/lsp-core/src/lsp/workspace-markers.ts +1 -0
- package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
- package/packages/lsp-core/src/tools/navigation.ts +4 -2
- package/packages/lsp-core/src/tools/rename.ts +4 -2
- package/packages/lsp-core/src/tools/symbols.ts +1 -1
- package/packages/lsp-daemon/dist/cli.js +160 -71
- package/packages/lsp-daemon/dist/client.js +135 -46
- package/packages/lsp-daemon/dist/index.js +143 -54
- package/packages/lsp-tools-mcp/dist/cli.js +131 -42
- package/packages/lsp-tools-mcp/dist/mcp.js +131 -42
- package/packages/lsp-tools-mcp/dist/tools.js +131 -42
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +118 -8
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +118 -8
- package/packages/omo-codex/plugin/components/codegraph/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/lazycodex-executor-verify/test/codex-hook.test.ts +3 -17
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +147 -64
- 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/rules/test/bundled-rules-priority.test.ts +11 -16
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +16 -23
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
- package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
- package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +37 -69
- package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +1 -15
- package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +3 -2
- 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/start-work-continuation/test/cli.test.ts +0 -3
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +2 -16
- 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/teammode/test/thread-title-hook.test.ts +3 -9
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +24 -12
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +24 -12
- 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/directive.md +6 -0
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +6 -0
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +27 -3
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
- package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +6 -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/SKILL.md +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +2 -35
- package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
- 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 +1 -1
- 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 +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-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 +20 -20
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +10 -7
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +6 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -0
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +27 -3
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +4 -24
- package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
- package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
- package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
- package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
- package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
- package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
- package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
- package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
- package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
- package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
- package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
- package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +57 -19
- package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/shared-skills/skills/frontend/SKILL.md +10 -7
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +2 -2
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +27 -3
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
- package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
- package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
|
@@ -5,14 +5,14 @@ import { formatAdditionalContextOutput } from "../src/hook-output.js";
|
|
|
5
5
|
describe("formatAdditionalContextOutput", () => {
|
|
6
6
|
it("#given context with outer whitespace and CRLF #when serializing hook JSON #then additional context is newline-normalized", () => {
|
|
7
7
|
// given
|
|
8
|
-
const context = "\r\n\r\
|
|
8
|
+
const context = "\r\n\r\nA1\r\nB2\rC3\r\n";
|
|
9
9
|
|
|
10
10
|
// when
|
|
11
11
|
const output = formatAdditionalContextOutput("PostToolUse", context);
|
|
12
12
|
const parsed: unknown = JSON.parse(output);
|
|
13
13
|
|
|
14
14
|
// then
|
|
15
|
-
expect(readAdditionalContext(parsed)).toBe("
|
|
15
|
+
expect(readAdditionalContext(parsed)).toBe("A1\nB2\nC3");
|
|
16
16
|
expect(output.endsWith("\n")).toBe(true);
|
|
17
17
|
});
|
|
18
18
|
|
|
@@ -40,7 +40,6 @@ describe("formatAdditionalContextOutput", () => {
|
|
|
40
40
|
expect(additionalContext.length).toBeLessThanOrEqual(32_000);
|
|
41
41
|
expect(additionalContext).toContain("first");
|
|
42
42
|
expect(additionalContext).not.toContain("last");
|
|
43
|
-
expect(additionalContext).toContain("[Truncated hook additional context to 32000 chars");
|
|
44
43
|
});
|
|
45
44
|
});
|
|
46
45
|
|
package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts
CHANGED
|
@@ -71,25 +71,11 @@ describe("Windows Git Bash bundled rule content", () => {
|
|
|
71
71
|
expect(body).toContain("alwaysApply: true");
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
it(
|
|
75
|
-
const body = readWindowsRuleBody();
|
|
76
|
-
|
|
77
|
-
expect(body).not.toContain('shell: "bash"');
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("#given the bundled rule #when read #then it warns that bare bash often resolves to WSL System32", () => {
|
|
81
|
-
const body = readWindowsRuleBody();
|
|
82
|
-
|
|
83
|
-
expect(body).toMatch(/WSL/i);
|
|
84
|
-
expect(body).toMatch(/System32/i);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("#given the bundled rule #when read #then it prefers the git_bash MCP and the absolute Git Bash path", () => {
|
|
74
|
+
it("#given the bundled rule #when read #then it names the Git Bash runtime identifiers", () => {
|
|
88
75
|
const body = readWindowsRuleBody();
|
|
89
76
|
|
|
90
77
|
expect(body).toContain("git_bash");
|
|
91
78
|
expect(body).toContain("OMO_CODEX_GIT_BASH_PATH");
|
|
92
|
-
expect(body).toContain("C:\\Program Files\\Git\\bin\\bash.exe");
|
|
93
79
|
});
|
|
94
80
|
});
|
|
95
81
|
|
|
@@ -31,9 +31,10 @@ Conventions for human contributors and AI agents working on this repository.
|
|
|
31
31
|
|
|
32
32
|
## Layout
|
|
33
33
|
|
|
34
|
-
- `src/boulder-reader.ts`: reads `.omo/boulder.json`, resolves the active work for the session, re-exports `getPlanChecklist`/`PlanChecklist` from `plan-checklist.ts`. `readContinuationState` returns null
|
|
34
|
+
- `src/boulder-reader.ts`: reads `.omo/boulder.json`, resolves the active work for the session, re-exports `getPlanChecklist`/`PlanChecklist` from `plan-checklist.ts`. `readContinuationState` returns null in four cases: `boulder.json` is missing or unparseable, no work matches the session, the work status is not continuable (only `active` and `paused` continue - `completed`/`abandoned` stop), or `checklist.total === 0`.
|
|
35
35
|
- `src/plan-checklist.ts`: `PlanChecklist` (`completed`/`remaining`/`total`/`nextTaskLabel`) and `getPlanChecklist`/`parsePlanChecklist`. Counts structured `## TODOs` rows (`N. <title>`) and `## Final Verification Wave` rows (`F<number>. <title>`); falls back to simple top-level `- [ ]`/`- [x]` checkboxes. Skips fenced blocks and respects `#`/`##` section boundaries.
|
|
36
|
-
- `src/codex-hook.ts`: Stop/SubagentStop hook; fills `REMAINING_COUNT
|
|
36
|
+
- `src/codex-hook.ts`: Stop/SubagentStop hook; fills nine placeholders into `directive.md` - `PLAN_NAME`, `PLAN_PATH`, `BOULDER_PATH`, `REMAINING_COUNT`, `TOTAL_COUNT`, `NEXT_TASK_LABEL`, `WORKTREE_BLOCK`, `LEDGER_PATH`, `SESSION_ID`. `WORKTREE_BLOCK` renders empty when the work has no worktree. When `remaining === 0`, `nextTaskLabel` is null and renders as "none (final gate pending)".
|
|
37
|
+
- **Context-pressure suppression:** the hook reads `input.transcript_path` through the injected `ReadonlyFileSystem` and returns `""` (no continuation) when the transcript carries any context-pressure marker (`context compacted`, `context_length_exceeded`, `context_too_large`, `codex ran out of room in the model's context window`, and related phrasings). This is the safety valve against an infinite continuation loop once the context window is exhausted; it is pinned by a `#given context-window pressure` test.
|
|
37
38
|
- `directive.md`: directive template with placeholders, applied per invocation.
|
|
38
39
|
|
|
39
40
|
## Build and Hooks
|
|
@@ -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 5.0.0-beta.
|
|
10
|
+
"statusMessage": "(OmO 5.0.0-beta.11) 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 5.0.0-beta.
|
|
22
|
+
"statusMessage": "(OmO 5.0.0-beta.11) Checking Start-Work Continuation"
|
|
23
23
|
}
|
|
24
24
|
]
|
|
25
25
|
}
|
|
@@ -26,9 +26,6 @@ describe("start-work continuation CLI", () => {
|
|
|
26
26
|
expect(result.status).toBe(0);
|
|
27
27
|
const output = parseStopHookOutput(result.stdout);
|
|
28
28
|
expect(output.decision).toBe("block");
|
|
29
|
-
expect(output.reason).toContain("Remaining top-level checkboxes: `2` of `4`");
|
|
30
|
-
expect(output.reason).toContain("Next incomplete task: `1. Implement checklist parser parity`");
|
|
31
|
-
expect(output.reason).toContain("Your session id in boulder.json: `codex:s1`");
|
|
32
29
|
});
|
|
33
30
|
|
|
34
31
|
it("#given valid SubagentStop stdin #when CLI runs #then stdout contains block JSON", () => {
|
package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts
CHANGED
|
@@ -58,16 +58,7 @@ describe("start-work Stop hook", () => {
|
|
|
58
58
|
const output = runStopHook(createStopInput(workspace), fs);
|
|
59
59
|
|
|
60
60
|
// then
|
|
61
|
-
|
|
62
|
-
expect(parsed.decision).toBe("block");
|
|
63
|
-
expect(parsed.reason).toContain("- Plan: `launch-plan`");
|
|
64
|
-
expect(parsed.reason).toContain(`- Plan file: \`${join(workspace, ".omo", "plans", "plan.md")}\``);
|
|
65
|
-
expect(parsed.reason).toContain(`- Boulder state: \`${join(workspace, ".omo", "boulder.json")}\``);
|
|
66
|
-
expect(parsed.reason).toContain("- Remaining top-level checkboxes: `2` of `4`");
|
|
67
|
-
expect(parsed.reason).toContain("- Next incomplete task: `1. Implement checklist parser parity`");
|
|
68
|
-
expect(parsed.reason).toContain("- Worktree: `/tmp/worktree`");
|
|
69
|
-
expect(parsed.reason).toContain(`- Ledger: \`${join(workspace, ".omo", "start-work", "ledger.jsonl")}\``);
|
|
70
|
-
expect(parsed.reason).toContain("- Your session id in boulder.json: `codex:sess_abc`");
|
|
61
|
+
expect(parseBlockOutput(output).decision).toBe("block");
|
|
71
62
|
});
|
|
72
63
|
|
|
73
64
|
it("#given active codex work and an external-blocker marker #when hook runs #then returns empty output", () => {
|
|
@@ -187,12 +178,7 @@ describe("start-work Stop hook", () => {
|
|
|
187
178
|
const output = runStopHook(createStopInput(workspace), fs);
|
|
188
179
|
|
|
189
180
|
// then
|
|
190
|
-
|
|
191
|
-
expect(parsed.decision).toBe("block");
|
|
192
|
-
expect(parsed.reason).toContain("- Remaining top-level checkboxes: `0` of `1`");
|
|
193
|
-
expect(parsed.reason).toContain("- Next incomplete task: `none (final gate pending)`");
|
|
194
|
-
expect(parsed.reason).toContain("When the remaining count is `0`, skip checkbox execution");
|
|
195
|
-
expect(parsed.reason).toContain("re-read the ledger record and verify the exact lane/SHA pair");
|
|
181
|
+
expect(parseBlockOutput(output).decision).toBe("block");
|
|
196
182
|
});
|
|
197
183
|
|
|
198
184
|
it("#given context-window pressure in transcript #when hook runs #then it does not inject continuation text", () => {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
|
|
10
10
|
"timeout": 10,
|
|
11
|
-
"statusMessage": "(OmO 5.0.0-beta.
|
|
11
|
+
"statusMessage": "(OmO 5.0.0-beta.11) Checking Thread Title Hygiene"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -29,9 +29,7 @@ describe("thread title PostToolUse guidance", () => {
|
|
|
29
29
|
expect(isHookOutput(parsed)).toBe(true);
|
|
30
30
|
if (!isHookOutput(parsed)) return;
|
|
31
31
|
expect(parsed.hookSpecificOutput.hookEventName).toBe("PostToolUse");
|
|
32
|
-
expect(parsed.hookSpecificOutput.additionalContext).
|
|
33
|
-
"THREAD ID thread-123: CALL codex_app.set_thread_title NOW. USE THE REAL TASK/ROLE.",
|
|
34
|
-
);
|
|
32
|
+
expect(parsed.hookSpecificOutput.additionalContext).toContain("thread-123");
|
|
35
33
|
});
|
|
36
34
|
|
|
37
35
|
it("#given Codex reports create_thread output as a JSON string #when the hook runs #then it still extracts the thread id", () => {
|
|
@@ -59,9 +57,7 @@ describe("thread title PostToolUse guidance", () => {
|
|
|
59
57
|
// then
|
|
60
58
|
expect(isHookOutput(parsed)).toBe(true);
|
|
61
59
|
if (!isHookOutput(parsed)) return;
|
|
62
|
-
expect(parsed.hookSpecificOutput.additionalContext).
|
|
63
|
-
"THREAD ID 019ef350-ee78-72a3-bd5e-e40cebc3d814: CALL codex_app.set_thread_title NOW. USE THE REAL TASK/ROLE.",
|
|
64
|
-
);
|
|
60
|
+
expect(parsed.hookSpecificOutput.additionalContext).toContain("019ef350-ee78-72a3-bd5e-e40cebc3d814");
|
|
65
61
|
});
|
|
66
62
|
|
|
67
63
|
it("#given an unrelated tool completed #when the hook runs #then it stays silent", () => {
|
|
@@ -141,9 +137,7 @@ describe("thread title PostToolUse guidance", () => {
|
|
|
141
137
|
// then
|
|
142
138
|
expect(isHookOutput(parsed)).toBe(true);
|
|
143
139
|
if (!isHookOutput(parsed)) return;
|
|
144
|
-
expect(parsed.hookSpecificOutput.additionalContext).
|
|
145
|
-
"PENDING WORKTREE ID remote-control:env:test-worktree: WORKTREE THREAD IS NOT READY YET. DO NOT bind-thread OR SEND THE MEMBER BOOTSTRAP UNTIL A REAL THREAD ID EXISTS. THEN CALL codex_app.set_thread_title USING THE REAL TASK/ROLE.",
|
|
146
|
-
);
|
|
140
|
+
expect(parsed.hookSpecificOutput.additionalContext).toContain("remote-control:env:test-worktree");
|
|
147
141
|
});
|
|
148
142
|
});
|
|
149
143
|
|
|
@@ -174,6 +174,7 @@ function writePostHogActivityState(stateDir, nextState, diagnostics) {
|
|
|
174
174
|
// ../../telemetry-core/src/constants.ts
|
|
175
175
|
var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
|
|
176
176
|
var DEFAULT_POSTHOG_API_KEY = "phc_CFJhj5HyvA62QPhvyaUCtaq23aUfznnijg5VaaGkNk74";
|
|
177
|
+
var UNCONFIGURED_POSTHOG_API_KEY = "phc_REPLACE_ME_OMO_NATIVE";
|
|
177
178
|
|
|
178
179
|
// ../../telemetry-core/src/diagnostics.ts
|
|
179
180
|
import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
@@ -310,6 +311,9 @@ function shouldDisableTelemetry(input) {
|
|
|
310
311
|
const env = input.env ?? process.env;
|
|
311
312
|
const globalPrefix = input.globalEnvPrefix ?? "OMO";
|
|
312
313
|
const prefixes = Array.from(new Set([globalPrefix, input.productEnvPrefix]));
|
|
314
|
+
if (isDisableFlag(env["DO_NOT_TRACK"])) {
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
313
317
|
for (const prefix of prefixes) {
|
|
314
318
|
if (isDisableFlag(env[`${prefix}_DISABLE_POSTHOG`])) {
|
|
315
319
|
return true;
|
|
@@ -323,18 +327,15 @@ function shouldDisableTelemetry(input) {
|
|
|
323
327
|
function getTelemetryApiKey(env = process.env, defaultApiKey = DEFAULT_POSTHOG_API_KEY) {
|
|
324
328
|
return env["POSTHOG_API_KEY"]?.trim() ?? defaultApiKey;
|
|
325
329
|
}
|
|
326
|
-
function
|
|
327
|
-
|
|
330
|
+
function isConfiguredTelemetryApiKey(apiKey) {
|
|
331
|
+
const normalized = apiKey.trim();
|
|
332
|
+
return normalized.length > 0 && normalized !== UNCONFIGURED_POSTHOG_API_KEY;
|
|
328
333
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
import { createHash } from "node:crypto";
|
|
332
|
-
import os2 from "node:os";
|
|
333
|
-
function getDefaultTelemetryOsProvider() {
|
|
334
|
-
return os2;
|
|
334
|
+
function hasTelemetryApiKey(env, defaultApiKey) {
|
|
335
|
+
return isConfiguredTelemetryApiKey(getTelemetryApiKey(env, defaultApiKey));
|
|
335
336
|
}
|
|
336
|
-
function
|
|
337
|
-
return
|
|
337
|
+
function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST) {
|
|
338
|
+
return env["POSTHOG_HOST"]?.trim() || defaultHost;
|
|
338
339
|
}
|
|
339
340
|
|
|
340
341
|
// ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
|
|
@@ -5504,6 +5505,16 @@ class PostHog extends PostHogBackendClient {
|
|
|
5504
5505
|
}
|
|
5505
5506
|
}
|
|
5506
5507
|
|
|
5508
|
+
// ../../telemetry-core/src/machine-id.ts
|
|
5509
|
+
import { createHash } from "node:crypto";
|
|
5510
|
+
import os2 from "node:os";
|
|
5511
|
+
function getDefaultTelemetryOsProvider() {
|
|
5512
|
+
return os2;
|
|
5513
|
+
}
|
|
5514
|
+
function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetryOsProvider()) {
|
|
5515
|
+
return createHash("sha256").update(`${machineIdPrefix}${osProvider.hostname()}`).digest("hex");
|
|
5516
|
+
}
|
|
5517
|
+
|
|
5507
5518
|
// ../../telemetry-core/src/posthog-client.ts
|
|
5508
5519
|
var NO_OP_CLIENT = {
|
|
5509
5520
|
enabled: false,
|
|
@@ -5538,7 +5549,7 @@ function createDefaultPostHogTransport(apiKey, options) {
|
|
|
5538
5549
|
}
|
|
5539
5550
|
function isTelemetryClientEnabled(input) {
|
|
5540
5551
|
const env = input.env ?? process.env;
|
|
5541
|
-
return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) &&
|
|
5552
|
+
return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) && hasTelemetryApiKey(env, input.product.defaultApiKey);
|
|
5542
5553
|
}
|
|
5543
5554
|
function createTelemetryClient(input) {
|
|
5544
5555
|
if (!isTelemetryClientEnabled(input)) {
|
|
@@ -5604,7 +5615,8 @@ function createTransport(input) {
|
|
|
5604
5615
|
flushAt: 1,
|
|
5605
5616
|
flushInterval: 0,
|
|
5606
5617
|
host: getTelemetryHost(env, input.product.defaultHost),
|
|
5607
|
-
disableGeoip: false
|
|
5618
|
+
disableGeoip: input.product.disableGeoip ?? false,
|
|
5619
|
+
...input.product.transportOptions
|
|
5608
5620
|
});
|
|
5609
5621
|
} catch (error) {
|
|
5610
5622
|
input.diagnostics?.({
|
|
@@ -170,6 +170,7 @@ function writePostHogActivityState(stateDir, nextState, diagnostics) {
|
|
|
170
170
|
// ../../../../telemetry-core/src/constants.ts
|
|
171
171
|
var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
|
|
172
172
|
var DEFAULT_POSTHOG_API_KEY = "phc_CFJhj5HyvA62QPhvyaUCtaq23aUfznnijg5VaaGkNk74";
|
|
173
|
+
var UNCONFIGURED_POSTHOG_API_KEY = "phc_REPLACE_ME_OMO_NATIVE";
|
|
173
174
|
|
|
174
175
|
// ../../../../telemetry-core/src/diagnostics.ts
|
|
175
176
|
import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
@@ -306,6 +307,9 @@ function shouldDisableTelemetry(input) {
|
|
|
306
307
|
const env = input.env ?? process.env;
|
|
307
308
|
const globalPrefix = input.globalEnvPrefix ?? "OMO";
|
|
308
309
|
const prefixes = Array.from(new Set([globalPrefix, input.productEnvPrefix]));
|
|
310
|
+
if (isDisableFlag(env["DO_NOT_TRACK"])) {
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
309
313
|
for (const prefix of prefixes) {
|
|
310
314
|
if (isDisableFlag(env[`${prefix}_DISABLE_POSTHOG`])) {
|
|
311
315
|
return true;
|
|
@@ -319,18 +323,15 @@ function shouldDisableTelemetry(input) {
|
|
|
319
323
|
function getTelemetryApiKey(env = process.env, defaultApiKey = DEFAULT_POSTHOG_API_KEY) {
|
|
320
324
|
return env["POSTHOG_API_KEY"]?.trim() ?? defaultApiKey;
|
|
321
325
|
}
|
|
322
|
-
function
|
|
323
|
-
|
|
326
|
+
function isConfiguredTelemetryApiKey(apiKey) {
|
|
327
|
+
const normalized = apiKey.trim();
|
|
328
|
+
return normalized.length > 0 && normalized !== UNCONFIGURED_POSTHOG_API_KEY;
|
|
324
329
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
import { createHash } from "node:crypto";
|
|
328
|
-
import os2 from "node:os";
|
|
329
|
-
function getDefaultTelemetryOsProvider() {
|
|
330
|
-
return os2;
|
|
330
|
+
function hasTelemetryApiKey(env, defaultApiKey) {
|
|
331
|
+
return isConfiguredTelemetryApiKey(getTelemetryApiKey(env, defaultApiKey));
|
|
331
332
|
}
|
|
332
|
-
function
|
|
333
|
-
return
|
|
333
|
+
function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST) {
|
|
334
|
+
return env["POSTHOG_HOST"]?.trim() || defaultHost;
|
|
334
335
|
}
|
|
335
336
|
|
|
336
337
|
// ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
|
|
@@ -5500,6 +5501,16 @@ class PostHog extends PostHogBackendClient {
|
|
|
5500
5501
|
}
|
|
5501
5502
|
}
|
|
5502
5503
|
|
|
5504
|
+
// ../../../../telemetry-core/src/machine-id.ts
|
|
5505
|
+
import { createHash } from "node:crypto";
|
|
5506
|
+
import os2 from "node:os";
|
|
5507
|
+
function getDefaultTelemetryOsProvider() {
|
|
5508
|
+
return os2;
|
|
5509
|
+
}
|
|
5510
|
+
function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetryOsProvider()) {
|
|
5511
|
+
return createHash("sha256").update(`${machineIdPrefix}${osProvider.hostname()}`).digest("hex");
|
|
5512
|
+
}
|
|
5513
|
+
|
|
5503
5514
|
// ../../../../telemetry-core/src/posthog-client.ts
|
|
5504
5515
|
var NO_OP_CLIENT = {
|
|
5505
5516
|
enabled: false,
|
|
@@ -5534,7 +5545,7 @@ function createDefaultPostHogTransport(apiKey, options) {
|
|
|
5534
5545
|
}
|
|
5535
5546
|
function isTelemetryClientEnabled(input) {
|
|
5536
5547
|
const env = input.env ?? process.env;
|
|
5537
|
-
return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) &&
|
|
5548
|
+
return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) && hasTelemetryApiKey(env, input.product.defaultApiKey);
|
|
5538
5549
|
}
|
|
5539
5550
|
function createTelemetryClient(input) {
|
|
5540
5551
|
if (!isTelemetryClientEnabled(input)) {
|
|
@@ -5600,7 +5611,8 @@ function createTransport(input) {
|
|
|
5600
5611
|
flushAt: 1,
|
|
5601
5612
|
flushInterval: 0,
|
|
5602
5613
|
host: getTelemetryHost(env, input.product.defaultHost),
|
|
5603
|
-
disableGeoip: false
|
|
5614
|
+
disableGeoip: input.product.disableGeoip ?? false,
|
|
5615
|
+
...input.product.transportOptions
|
|
5604
5616
|
});
|
|
5605
5617
|
} catch (error) {
|
|
5606
5618
|
input.diagnostics?.({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/codex-telemetry",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.11",
|
|
4
4
|
"description": "Codex plugin component that emits omo-codex anonymous daily-active telemetry on SessionStart.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@11.12.1",
|
|
@@ -126,6 +126,12 @@ exactly `objective`; do not include `status`. Only when no goal tool
|
|
|
126
126
|
exists on this surface, open your reply with a `# Goal` block treated
|
|
127
127
|
as binding. Goals are unlimited; never invent a numeric budget or
|
|
128
128
|
limit.
|
|
129
|
+
Check `get_goal` first: continue a matching active goal instead of
|
|
130
|
+
duplicating one; surface a conflicting one. Write the objective
|
|
131
|
+
outcome-first: the concrete thing that will be TRUE when done (an
|
|
132
|
+
outcome, never an activity), the named deliverable surfaces, and
|
|
133
|
+
explicit scope bounds — a vague objective produces vague criteria,
|
|
134
|
+
and vague criteria cannot be proven.
|
|
129
135
|
The criteria MUST list, upfront:
|
|
130
136
|
- The user-visible deliverable in one line, and the tier with its
|
|
131
137
|
justification.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/codex-ultrawork",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.11",
|
|
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",
|
|
@@ -133,6 +133,12 @@ exactly `objective`; do not include `status`. Only when no goal tool
|
|
|
133
133
|
exists on this surface, open your reply with a `# Goal` block treated
|
|
134
134
|
as binding. Goals are unlimited; never invent a numeric budget or
|
|
135
135
|
limit.
|
|
136
|
+
Check `get_goal` first: continue a matching active goal instead of
|
|
137
|
+
duplicating one; surface a conflicting one. Write the objective
|
|
138
|
+
outcome-first: the concrete thing that will be TRUE when done (an
|
|
139
|
+
outcome, never an activity), the named deliverable surfaces, and
|
|
140
|
+
explicit scope bounds — a vague objective produces vague criteria,
|
|
141
|
+
and vague criteria cannot be proven.
|
|
136
142
|
The criteria MUST list, upfront:
|
|
137
143
|
- The user-visible deliverable in one line, and the tier with its
|
|
138
144
|
justification.
|
|
@@ -34,7 +34,7 @@ Example opening (adapt the wording, keep every commitment):
|
|
|
34
34
|
|
|
35
35
|
## INTENT ROUTING - pick ONE intent reference
|
|
36
36
|
|
|
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.
|
|
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. The review runs under the bounded convergence contract in `full-workflow.md`: a 5-round cap (unlimited only on explicit user request), evidence-backed blocker eligibility, and approval-with-notes counting as approval. Answering the current question more carefully does NOT satisfy it. This does NOT choose CLEAR/UNCLEAR and does NOT suppress interview.
|
|
38
38
|
|
|
39
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.
|
|
40
40
|
|
|
@@ -72,7 +72,7 @@ When producing the plan, encode every executable item as a column-zero Markdown
|
|
|
72
72
|
- **Full scope is the default.** Plan the ENTIRE request; "MVP", "v1", "phase 1", or any reduced subset is never an option you invent or ask about - it exists only if the user introduces it. Scope OUT / Must-NOT-Have entries are guardrails against unrequested additions, never reductions of the request.
|
|
73
73
|
- **Explore before asking.** Discoverable facts (repo/system/docs truth) -> research and cite, never ask. Preferences/tradeoffs -> the only things you bring to the user. When unsure which, treat it as a user-decision.
|
|
74
74
|
- **CodeGraph first when present.** Use `codegraph_explore` for repo how/where/what/flow questions before wider reads; if codegraph_* tools are absent, inactive/uninitialized, or cold-start unavailable, continue with Read/Grep/Glob/LSP and the ast-grep skill.
|
|
75
|
-
- **Two filters** on every candidate question, in order: (1) Could collected evidence answer it? -> explore instead. (2) Could the user's stated intent plus a defensible default answer it? -> adopt the default, record it, do not ask - UNLESS it is an owner-decision, which always survives as a question even when a default exists: anything irreversible / destructive / safety-critical, or a cross-cutting product choice the user lives with (public config surface, distribution / packaging, external dependency or pinned SHA, data / schema shape). Default the reversible internals; surface the owner-decisions.
|
|
75
|
+
- **Two filters** on every candidate question, in order: (1) Could collected evidence answer it? -> explore instead. (2) Could the user's stated intent plus a defensible default answer it? -> adopt the default, record it, do not ask - UNLESS it is an owner-decision, which always survives as a question even when a default exists: anything irreversible / destructive / safety-critical, or a cross-cutting product choice the user lives with (public config surface, distribution / packaging, external dependency or pinned SHA, data / schema shape, real budget / paid-service spend, expected scale or capacity target, target-audience / compliance limits). Extrinsic constraints (budget, mandated stack, scale, audience) leave no repo evidence, so exploration can never surface them - sweep those axes explicitly once per plan and classify each as explored, defaulted (ledger), or asked. Default the reversible internals; surface the owner-decisions.
|
|
76
76
|
- **Explore to sufficiency, then STOP.** One research wave per open question; stop when the clearance check is answerable; never re-explore to double-check.
|
|
77
77
|
- **Parallel-dispatch** independent research in ONE turn and keep working while it runs. Subagent outputs are CLAIMS until you independently verify them.
|
|
78
78
|
- **Approval is not execution.** Approval authorizes writing the plan ONLY, never implementation. ONE request -> ONE plan, however large.
|
package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md
CHANGED
|
@@ -136,7 +136,7 @@ No Metis, no plan file, no execution until the user approves. The UNCLEAR path a
|
|
|
136
136
|
|
|
137
137
|
## Phase 3 - Generate the plan (only after approval)
|
|
138
138
|
1. Rerun `node "<skill-root>/scripts/scaffold-plan.mjs" <slug> [--clear|--unclear]` without `--draft-only`. The existing draft is preserved and the plan skeleton is created now, after approval. A plain rerun is a safe no-op; never hand-build the skeleton.
|
|
139
|
-
2. **Metis gap analysis (mandatory):** spawn a metis reviewer for contradictions, missing constraints, scope-creep, unvalidated assumptions, and missing acceptance criteria; fold findings in silently.
|
|
139
|
+
2. **Metis gap analysis (mandatory):** spawn a metis reviewer for contradictions, missing constraints — including unstated extrinsic ones: budget/spend, mandated stack, expected scale, target audience / compliance — scope-creep, unvalidated assumptions, and missing acceptance criteria; fold findings in silently; require each constraint gap to return as a proposed default plus reversibility, or a single owner-question when defaulting is unsafe.
|
|
140
140
|
3. APPEND todo batches into the `## Todos` region with edit/apply_patch - never rewrite the script-emitted headers; 50+ todos is fine; one request -> one plan.
|
|
141
141
|
4. Fill `## TL;DR (For humans)` LAST, after the detailed plan, so it summarizes the real plan, not an intention.
|
|
142
142
|
5. Self-review: every todo has references + agent-executable acceptance criteria + happy+failure QA scenarios; no business-logic assumption without evidence; zero criteria need a human. HR6 backstop - confirm the plan's FIRST `## ` heading is `## TL;DR (For humans)` and that every header below it appears in the template order; if you ever hand-built or reordered the file, the human summary must still lead.
|
|
@@ -180,7 +180,7 @@ Every "present the plan summary/brief" above delivers THIS structure, in the use
|
|
|
180
180
|
6. **Execution handoff** - the plan runs in a worker session via `$start-work <plan-name>`; introduce the options: `--worktree <absolute-path>` (task-owned worktree; required for PR/branch work), `--make-pr` (deliver as a PR; auto-creates a task-owned worktree), `--ship` (implies `--make-pr`, keeps working until the PR is reviewed and MERGED).
|
|
181
181
|
|
|
182
182
|
### High-accuracy review (dual review)
|
|
183
|
-
The high-accuracy review is DUAL and both passes must return OKAY before handoff: (1) the native `momus` reviewer subagent, and (2) an independent Codex CLI review on gpt-5.6-sol at xhigh reasoning, run in a disposable isolated workspace and `CODEX_HOME` with the harness's normal approval and sandbox policy. Do not add flags that disable approvals or sandboxing. Momus runs at High and may take substantially longer than other agents. One round = exactly ONE `momus` + ONE independent review, dispatched together against the COMPLETE plan file (todos + TL;DR filled) at the draft's exact recorded `plan_path`. Keep Momus in flight and wait for its terminal result: elapsed time alone never justifies cancelling, duplicating, replacing, or treating it as failed. After both verdicts return, fix every
|
|
183
|
+
The high-accuracy review is DUAL and both passes must return OKAY before handoff: (1) the native `momus` reviewer subagent, and (2) an independent Codex CLI review on gpt-5.6-sol at xhigh reasoning, run in a disposable isolated workspace and `CODEX_HOME` with the harness's normal approval and sandbox policy. Do not add flags that disable approvals or sandboxing. Momus runs at High and may take substantially longer than other agents. One round = exactly ONE `momus` + ONE independent review, dispatched together against the COMPLETE plan file (todos + TL;DR filled) at the draft's exact recorded `plan_path`. Keep Momus in flight and wait for its terminal result: elapsed time alone never justifies cancelling, duplicating, replacing, or treating it as failed. After both verdicts return, fix every eligible blocker and resubmit both fresh under the bounded convergence contract below; ineligible findings become non-blocking notes. CLEAR: runs when the user opts in or `review_required: true`. UNCLEAR: runs automatically unless Classify=Trivial.
|
|
184
184
|
|
|
185
185
|
Every reviewer prompt must carry this intake contract with all angle-bracket values replaced by literals from the current round before dispatch. Never pass `draft.plan_path`, `draft.plan_sha256`, field names, or another symbolic reference to an isolated reviewer. For the independent Codex lane, materialize the complete plan at that same literal workspace-relative path inside the disposable review workspace, verify the copied file's SHA-256, then dispatch with that disposable workspace's literal canonical root. Its first action is to read the exact recorded path; retrieval drift stops that lane before review:
|
|
186
186
|
|
|
@@ -209,7 +209,31 @@ Every reviewer prompt must carry this intake contract with all angle-bracket val
|
|
|
209
209
|
|
|
210
210
|
The first action must open the literal workspace root as a directory descriptor, then traverse `.omo`, `plans`, and the final target with descriptor-relative no-follow opens, `fstat` each ancestor as a directory and the final descriptor as a regular file, and hash all bytes read from that same final descriptor. If the platform cannot guarantee this chain, or any path/runtime/launch/receipt/digest check drifts, return `INCONCLUSIVE` before reviewing. Echo the literal workspace, runtime home, target, digest, round, and launch ID; the parent separately matches the completion envelope to the persisted session/process receipt. Never search or use another artifact.
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
### Bounded convergence (the review must terminate)
|
|
213
|
+
Review rounds are capped at 5 (unlimited only on explicit user request), and an approval whose only remaining items are notes counts as approval. A finding may BLOCK only when it names at least one `blocker_eligibility` category below with its concrete evidence; every other finding - speculative durability, replay/crash-recovery, schema, CLI-parsing, state-machine, or hardening concerns the accepted scope never required - is recorded as a non-blocking note and becomes implementation/test work, never plan expansion. After round 1 the blocker ledger FREEZES: later rounds verify accepted ledger blockers, regressions introduced by fixes, and new findings that pass eligibility - they never rediscover the plan from scratch. Fixes apply the smallest edit that resolves the cited blocker; neither reviews nor fixes grow the plan's scope. Every reviewer prompt carries this convergence contract alongside the intake contract. On cap exhaustion without approval: STOP, report outstanding blockers, ask the user - continue / accept / adjust.
|
|
214
|
+
|
|
215
|
+
<!-- ulw-plan-review-convergence-contract -->
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"max_rounds": 5,
|
|
219
|
+
"max_rounds_override": "explicit_user_request_only",
|
|
220
|
+
"on_cap_reached": "stop_report_outstanding_blockers_ask_user",
|
|
221
|
+
"blocker_eligibility": [
|
|
222
|
+
"explicit_requirement_or_accepted_decision",
|
|
223
|
+
"existing_failing_regression",
|
|
224
|
+
"reproducible_broken_flow",
|
|
225
|
+
"concrete_security_data_loss_or_compatibility_risk",
|
|
226
|
+
"external_api_provider_or_release_contract_conflict"
|
|
227
|
+
],
|
|
228
|
+
"ineligible_finding_disposition": "non_blocking_note",
|
|
229
|
+
"approval_with_notes_counts_as_approval": true,
|
|
230
|
+
"ledger_freeze_after_round": 1,
|
|
231
|
+
"closure_round_scope": ["accepted_ledger_blockers", "regressions_introduced_by_fixes", "new_findings_passing_blocker_eligibility"],
|
|
232
|
+
"fix_edit_policy": "smallest_edit_no_scope_expansion"
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The draft must record the native Momus session/result, the independent Codex CLI review command/result, and the fix/retry summary, plus the convergence ledger (accepted blockers, non-blocking notes, round count). Immediately before handoff, repeat the same live canonical-path and SHA-256 validation and require it to match the approved round digest; drift invalidates both approvals and starts a fresh round. Do not say "high-accuracy review completed" unless both receipts exist, both final verdicts are unconditional approval, and the final live-plan validation passes.
|
|
213
237
|
|
|
214
238
|
## Delegation discipline (Codex-native)
|
|
215
239
|
Every spawn starts with `TASK:`, then DELIVERABLE / SCOPE / VERIFY inside `message`; state the role inside `message` (agent_type is a routing hint, not a guaranteed TOML selection); use `fork_context: false` unless full history is truly required:
|
package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md
CHANGED
|
@@ -26,7 +26,7 @@ ASK WITH WHY: name what you explored, why it did not resolve, and which part of
|
|
|
26
26
|
|
|
27
27
|
FOGGIEST-GAP targeting (ordinal, NO numbers): each turn aim at the single open gap whose resolution most unblocks the plan, and say why in one sentence; rotate across equally-foggy components. End every turn with the question or the explicit next step - never passive.
|
|
28
28
|
|
|
29
|
-
CLEARANCE CHECK after each turn: objective defined? scope IN/OUT explicit? approach decided? test strategy confirmed? no blocking ambiguity left? Any NO is your next question; all YES -> present the approval brief and stop.
|
|
29
|
+
CLEARANCE CHECK after each turn: objective defined? scope IN/OUT explicit? approach decided? test strategy confirmed? constraints swept (budget / stack / scale / audience - each explored, defaulted, or asked)? no blocking ambiguity left? Any NO is your next question; all YES -> present the approval brief and stop.
|
|
30
30
|
</interview>
|
|
31
31
|
|
|
32
32
|
<approval_and_deliver>
|
|
@@ -40,5 +40,6 @@ Request: "add a 5/min-per-IP rate-limit to `/login`".
|
|
|
40
40
|
3. Two surviving forks, each asked WITH WHY:
|
|
41
41
|
- Storage backend (explored: repo already uses Redis; default = Redis; options Redis / in-memory / per-node) - why: persistence across nodes forks the design.
|
|
42
42
|
- Over-limit response (default = 429 + Retry-After; options 429 / 423 / silent drop) - why: client contract forks on it.
|
|
43
|
+
- Swept axes: no budget/audience fork (internal service); scale bound = existing Redis capacity (defaulted, reversible).
|
|
43
44
|
4. Approval brief -> explicit okay -> scaffold -> append todos -> if `review_required`, run dual review and deliver receipts; otherwise deliver with the optional review question.
|
|
44
45
|
</worked_example>
|
package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md
CHANGED
|
@@ -20,13 +20,13 @@ TOPOLOGY LOCK still applies: enumerate the 1-6 independently-succeed/fail compon
|
|
|
20
20
|
</research_protocol>
|
|
21
21
|
|
|
22
22
|
<default_selection>
|
|
23
|
-
For each open decision, adopt the defensible best-practice default (industry standard or repo convention), RECORD it in the draft's Open-assumptions ledger with rationale and reversibility, and proceed. NO numeric scoring - the ledger IS the audit trail. The ONLY default escalated to a single focused question is one that is irreversible, destructive, or safety-critical and research cannot settle.
|
|
23
|
+
For each open decision - including the extrinsic axes the sweep names (budget, mandated stack, expected scale, target audience / compliance) - adopt the defensible best-practice default (industry standard or repo convention), RECORD it in the draft's Open-assumptions ledger with rationale and reversibility, and proceed. NO numeric scoring - the ledger IS the audit trail. The ONLY default escalated to a single focused question is one that is irreversible, destructive, or safety-critical, or commits real spend the user never authorized, and research cannot settle.
|
|
24
24
|
|
|
25
25
|
Fold a contrarian self-grill into the Metis spawn: challenge the single highest-leverage adopted assumption - is this constraint real or habitual; does any adopted default add complexity the request never asked for? - and return concrete reframes. The grill targets incidental complexity (unneeded abstraction, speculative capacity), NEVER the feature set: reducing, phasing, or deferring part of the request is not a reframe. Fold a reframe into the plan only as a recommended default plus rationale, never as a forced change.
|
|
26
26
|
</default_selection>
|
|
27
27
|
|
|
28
28
|
<high_accuracy_auto>
|
|
29
|
-
Because the human did not steer, adversarial review SUBSTITUTES for the interview you skipped - this is what catches a bad default. Metis runs during plan generation as always; after Metis findings are folded and the plan file is complete, run the dual high-accuracy review defined in `full-workflow.md` AUTOMATICALLY - no "do you want a review?" question - and resubmit fresh
|
|
29
|
+
Because the human did not steer, adversarial review SUBSTITUTES for the interview you skipped - this is what catches a bad default. Metis runs during plan generation as always; after Metis findings are folded and the plan file is complete, run the dual high-accuracy review defined in `full-workflow.md` AUTOMATICALLY - no "do you want a review?" question - and drive it to convergence under the bounded convergence contract in `full-workflow.md`: fix every eligible blocker and resubmit fresh, record ineligible findings as non-blocking notes, and on cap exhaustion stop and ask the user.
|
|
30
30
|
|
|
31
31
|
TRIVIAL-TIER GUARD: if Classify sized the work Trivial, the auto-Momus loop is SUPPRESSED (Metis still runs once) - a vague-but-tiny request ("clean this up") must not trigger the full adversarial loop. UNCLEAR raises the research-plus-default posture; it does not override the Trivial cost guard for Momus.
|
|
32
32
|
</high_accuracy_auto>
|
|
@@ -40,5 +40,5 @@ Request: "make auth better".
|
|
|
40
40
|
1. Research waves -> current auth at `src/auth/*` and evidence for the requested improvement; best-practice baselines via librarian.
|
|
41
41
|
2. Topology lock as an ANNOUNCEMENT, not a question: components refine the evidenced auth intent in full, such as session hardening, brute-force protection, and password policy when the repository supports them. MFA is an adjacent capability and stays in Scope OUT unless the user asks for it or evidence establishes it as part of the requested outcome.
|
|
42
42
|
3. Adopted-defaults table (assumption | default | rationale | reversible?): bcrypt rounds 8 -> 12 (reversible), add 5/min-per-IP login limit (reversible), rotate session id on privilege change (reversible).
|
|
43
|
-
4. Metis folded -> auto dual review (fix
|
|
43
|
+
4. Metis folded -> auto dual review (fix eligible gaps under the bounded convergence contract) -> brief LEADING with the approach and the defaults, surfaced in the human TL;DR for veto.
|
|
44
44
|
</worked_example>
|