oh-my-opencode 5.0.0-beta.62 → 5.0.0-beta.64
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/THIRD-PARTY-NOTICES.md +8 -6
- package/dist/cli/doctor/checks/browser-provider.d.ts +2 -0
- package/dist/cli/index.js +70 -41
- package/dist/cli-node/index.js +70 -41
- package/dist/config/schema/agent-names.d.ts +0 -1
- package/dist/config/schema/browser-automation.d.ts +0 -2
- package/dist/config/schema/oh-my-opencode-config.d.ts +0 -1
- package/dist/hooks/comment-checker/__fixtures__/download-probe.fixture.d.ts +1 -0
- package/dist/index.js +89 -588
- package/dist/oh-my-opencode.schema.json +4 -5
- package/dist/skills/ast-grep/SKILL.md +12 -0
- package/dist/skills/debugging/references/tools/playwright-cli.md +79 -161
- package/dist/skills/frontend/SKILL.md +1 -1
- package/dist/skills/frontend/references/design/aside.md +1 -1
- package/dist/skills/frontend/references/design/clone-from-url.md +1 -1
- package/dist/skills/frontend/scripts/perfection/lighthouse-audit.py +2 -2
- package/dist/skills/review-work/SKILL.md +1 -1
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +1 -82
- package/dist/skills/ultimate-browsing/SKILL.md +17 -29
- package/dist/skills/ultimate-browsing/engine/AGENTS.md +2 -1
- package/dist/skills/ultimate-browsing/engine/templates/package.json +2 -2
- package/dist/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +5 -2
- package/dist/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +8 -6
- package/dist/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +86 -0
- package/dist/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +4 -7
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +86 -100
- package/dist/skills/ultimate-browsing/references/insane-search/README.md +9 -3
- package/dist/skills/ultimate-browsing/references/insane-search/playwright.md +16 -13
- package/dist/skills/ultimate-browsing/scripts/extract_cookies.py +3 -3
- package/dist/skills/ulw-execute/SKILL.md +1 -1
- package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/dist/skills/ulw-research/SKILL.md +3 -3
- package/dist/skills/visual-qa/AGENTS.md +1 -1
- package/dist/skills/visual-qa/SKILL.md +1 -1
- package/dist/skills/visual-qa/references/browser-setup.md +75 -0
- package/dist/tui.js +18 -11
- package/package.json +16 -23
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +4 -2
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +5 -4
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +13 -0
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +5 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +7 -5
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +7 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +7 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +931 -442
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +20 -12
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +8 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/driver-objective-ack.d.ts +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/driver-objective-ack.js +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence-artifacts.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence-artifacts.js +37 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence.js +24 -12
- package/packages/omo-codex/plugin/components/ulw-loop/dist/ledger.d.ts +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/ledger.js +34 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-commit.d.ts +19 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-commit.js +107 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +6 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +54 -25
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-goal-factory.d.ts +10 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-goal-factory.js +38 -31
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +9 -7
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +105 -114
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-log.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-log.js +86 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +15 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +11 -8
- package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/factory.js +28 -12
- package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.d.ts +335 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.js +109 -10
- package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/types.d.ts +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-budget-io.d.ts +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-budget-io.js +67 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +8 -62
- package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.d.ts +11 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.js +120 -88
- package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +18 -10
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-types.d.ts +9 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.d.ts +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +11 -11
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +8 -17
- package/packages/omo-codex/plugin/components/ulw-loop/dist/success-criteria-input.d.ts +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/success-criteria-input.js +41 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +15 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +7 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +26 -14
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +8 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/driver-objective-ack.ts +20 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/evidence-artifacts.ts +45 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/evidence.ts +23 -16
- package/packages/omo-codex/plugin/components/ulw-loop/src/ledger.ts +33 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-commit.ts +124 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +67 -54
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-goal-factory.ts +63 -31
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +126 -140
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-log.ts +84 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +26 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +11 -7
- package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/factory.ts +47 -12
- package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/manifest.ts +124 -10
- package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/types.ts +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-budget-io.ts +59 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +8 -59
- package/packages/omo-codex/plugin/components/ulw-loop/src/state-lock.ts +129 -111
- package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +19 -10
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +5 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-types.ts +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +12 -10
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +8 -16
- package/packages/omo-codex/plugin/components/ulw-loop/src/success-criteria-input.ts +56 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +37 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/barrier.ts +13 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-child.ts +65 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-cli-qa.mjs +76 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-crash.ts +23 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-mutations.mjs +58 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/commit-writer.ts +65 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/lease-clock.ts +23 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-commit-log.test.ts +252 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-commit-recovery.test.ts +190 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +50 -35
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-log-newest.test.ts +72 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-completed-plan.test.ts +43 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-driver-states.test.ts +33 -4
- package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-dx.test.ts +219 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-session-context.test.ts +21 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/state-lock.test.ts +92 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/status-next-actions-surface.test.ts +133 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +12 -12
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +4 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.d.mts +4 -0
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +15 -7
- package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +12 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/playwright-cli.md +79 -161
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/aside.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/clone-from-url.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/lighthouse-audit.py +2 -2
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +1 -82
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +17 -29
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +2 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +2 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +5 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +8 -6
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +86 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +4 -7
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +86 -100
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -3
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +16 -13
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/extract_cookies.py +3 -3
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +5 -4
- package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +3 -3
- package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/visual-qa/references/browser-setup.md +75 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +6 -4
- package/packages/prompts-core/prompts/ultrawork/codex.md +5 -4
- package/packages/shared-skills/skills/ast-grep/SKILL.md +12 -0
- package/packages/shared-skills/skills/debugging/references/tools/playwright-cli.md +79 -161
- package/packages/shared-skills/skills/frontend/SKILL.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/aside.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/clone-from-url.md +1 -1
- package/packages/shared-skills/skills/frontend/scripts/perfection/lighthouse-audit.py +2 -2
- package/packages/shared-skills/skills/review-work/SKILL.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +1 -82
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +17 -29
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +2 -1
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +2 -2
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/playwright_mobile_chrome.js +5 -2
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/playwright_real_chrome.js +8 -6
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +86 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +4 -7
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +86 -100
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -3
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/playwright.md +16 -13
- package/packages/shared-skills/skills/ultimate-browsing/scripts/extract_cookies.py +3 -3
- package/packages/shared-skills/skills/ulw-execute/SKILL.md +1 -1
- package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -3
- package/packages/shared-skills/skills/visual-qa/AGENTS.md +1 -1
- package/packages/shared-skills/skills/visual-qa/SKILL.md +1 -1
- package/packages/shared-skills/skills/visual-qa/references/browser-setup.md +75 -0
- package/dist/skills/visual-qa/references/agent-browser-setup.md +0 -45
- package/packages/omo-codex/plugin/skills/visual-qa/references/agent-browser-setup.md +0 -45
- package/packages/shared-skills/skills/visual-qa/references/agent-browser-setup.md +0 -45
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { type UlwLoopScope, ulwLoopDir } from "./paths.js";
|
|
3
|
+
import { readOptional, readRecords, reconcilePlan } from "./plan-log.js";
|
|
4
|
+
import type { UlwLoopLedgerEntry } from "./types.js";
|
|
5
|
+
|
|
6
|
+
export function readLedgerAt(dir: string): UlwLoopLedgerEntry[] {
|
|
7
|
+
const entries = new Map<string, UlwLoopLedgerEntry>();
|
|
8
|
+
const lines = (readOptional(join(dir, "ledger.jsonl")) ?? "").split(/\r?\n/);
|
|
9
|
+
for (const [index, line] of lines.entries()) {
|
|
10
|
+
if (line.trim().length === 0) continue;
|
|
11
|
+
try {
|
|
12
|
+
const entry: UlwLoopLedgerEntry = JSON.parse(line);
|
|
13
|
+
entry.revision ??= 0;
|
|
14
|
+
entry.id ??= `legacy-${index + 1}`;
|
|
15
|
+
entries.set(entry.id, entry);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
for (const record of readRecords(dir))
|
|
21
|
+
for (const [seq, entry] of record.ledger.entries()) {
|
|
22
|
+
const id = entry.id ?? `${record.revision}-${seq}`;
|
|
23
|
+
entries.set(id, { ...entry, revision: record.revision, id });
|
|
24
|
+
}
|
|
25
|
+
const reset = reconcilePlan(dir)?.ledgerResetRevision ?? 0;
|
|
26
|
+
const sequence = (entry: UlwLoopLedgerEntry) => Number(entry.id?.split("-").at(-1) ?? 0);
|
|
27
|
+
return [...entries.values()]
|
|
28
|
+
.filter((entry) => (entry.revision ?? 0) >= reset)
|
|
29
|
+
.sort((a, b) => (a.revision ?? 0) - (b.revision ?? 0) || sequence(a) - sequence(b));
|
|
30
|
+
}
|
|
31
|
+
export function readLedger(repoRoot: string, scope?: UlwLoopScope): UlwLoopLedgerEntry[] {
|
|
32
|
+
return readLedgerAt(ulwLoopDir(repoRoot, scope));
|
|
33
|
+
}
|
|
@@ -85,6 +85,13 @@ export function repoRelative(absolutePath: string, repoRoot: string): string {
|
|
|
85
85
|
return absolutePath.split("\\").join("/");
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
// The plan-level evidence root stays fixed for the whole run, unlike the per-goal attempt dir, so
|
|
89
|
+
// long lanes that span goals have one stable place to write artifacts.
|
|
90
|
+
export function ulwLoopEvidenceRoot(scope?: UlwLoopScope): string {
|
|
91
|
+
const sessionId = normalizeUlwLoopSessionId(scope?.sessionId);
|
|
92
|
+
return sessionId === null ? ".omo/evidence" : `.omo/evidence/ulw/${sessionId}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
88
95
|
// Both the status --json emitter and the checkpoint enforcement resolve the attempt dir through
|
|
89
96
|
// this function from the scope alone; a second resolution path (env, a literal placeholder)
|
|
90
97
|
// would let the gate reject its own advertised directory.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { linkSync, mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { rename, writeFile } from "node:fs/promises";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { readLedgerAt } from "./ledger.js";
|
|
7
|
+
import { type UlwLoopScope, ulwLoopDir, ulwLoopStateLockPath } from "./paths.js";
|
|
8
|
+
import { assertStateLockOwned, migrationEntries } from "./plan-io.js";
|
|
9
|
+
import { hasCode, type PlanCommitRecord, readOptional, readRecords, reconcilePlan } from "./plan-log.js";
|
|
10
|
+
import { UlwLoopError, type UlwLoopLedgerEntry, type UlwLoopPlan } from "./types.js";
|
|
11
|
+
|
|
12
|
+
interface CommitHooks {
|
|
13
|
+
readonly beforeMutation?: () => void | Promise<void>;
|
|
14
|
+
readonly beforeCommit?: () => void | Promise<void>;
|
|
15
|
+
readonly afterCommit?: () => void | Promise<void>;
|
|
16
|
+
readonly link?: (source: string, destination: string) => void;
|
|
17
|
+
readonly writeView?: (path: string, content: string) => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
const hooks = new AsyncLocalStorage<CommitHooks>();
|
|
20
|
+
export function withCommitHooks<T>(value: CommitHooks, fn: () => Promise<T>): Promise<T> {
|
|
21
|
+
return hooks.run(value, fn);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function beforePlanMutation(): Promise<void> {
|
|
25
|
+
await hooks.getStore()?.beforeMutation?.();
|
|
26
|
+
}
|
|
27
|
+
export async function writeViewFile(path: string, content: string): Promise<void> {
|
|
28
|
+
await (hooks.getStore()?.writeView ?? writeFile)(path, content);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// link is the sole commit point; no copy fallback (Node copyFile is not atomic).
|
|
32
|
+
// A resumed zombie can publish first, but never overwrite an existing revision.
|
|
33
|
+
// Logical audit order is (revision, sequence), not materialization completion time.
|
|
34
|
+
export async function commit(
|
|
35
|
+
repoRoot: string,
|
|
36
|
+
scope: UlwLoopScope | undefined,
|
|
37
|
+
mutation: {
|
|
38
|
+
readonly plan: UlwLoopPlan;
|
|
39
|
+
readonly entries: readonly UlwLoopLedgerEntry[];
|
|
40
|
+
},
|
|
41
|
+
): Promise<void> {
|
|
42
|
+
const { plan } = mutation;
|
|
43
|
+
const dir = ulwLoopDir(repoRoot, scope);
|
|
44
|
+
assertStateLockOwned(ulwLoopStateLockPath(repoRoot, scope));
|
|
45
|
+
await hooks.getStore()?.beforeCommit?.();
|
|
46
|
+
const next = (plan.revision ?? 0) + 1;
|
|
47
|
+
const brief = plan.brief ?? readOptional(join(dir, "brief.md")) ?? "";
|
|
48
|
+
const entries = [...migrationEntries(plan), ...mutation.entries].map((entry, seq) => ({
|
|
49
|
+
...entry,
|
|
50
|
+
revision: next,
|
|
51
|
+
id: `${next}-${seq}`,
|
|
52
|
+
}));
|
|
53
|
+
const record: PlanCommitRecord = {
|
|
54
|
+
version: 1,
|
|
55
|
+
revision: next,
|
|
56
|
+
plan: { ...plan, revision: next, brief },
|
|
57
|
+
ledger: entries,
|
|
58
|
+
};
|
|
59
|
+
mkdirSync(join(dir, "revisions"), { recursive: true });
|
|
60
|
+
mkdirSync(join(dir, "tmp"), { recursive: true });
|
|
61
|
+
const temp = join(dir, "tmp", `${process.pid}-${randomUUID()}.json`);
|
|
62
|
+
try {
|
|
63
|
+
writeFileSync(temp, `${JSON.stringify(record)}\n`, { flag: "wx" });
|
|
64
|
+
try {
|
|
65
|
+
(hooks.getStore()?.link ?? linkSync)(temp, join(dir, "revisions", `${String(next).padStart(8, "0")}.json`));
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (hasCode(error, "EEXIST"))
|
|
68
|
+
throw new UlwLoopError("Another writer published the read revision.", "ULW_LOOP_PUBLISH_CONFLICT", {
|
|
69
|
+
cause: error,
|
|
70
|
+
});
|
|
71
|
+
if (["EPERM", "ENOTSUP", "EXDEV"].some((code) => hasCode(error, code)))
|
|
72
|
+
throw new UlwLoopError(
|
|
73
|
+
"Immutable ulw-loop publication requires atomic hard links.",
|
|
74
|
+
"ULW_LOOP_PUBLISH_UNSUPPORTED_FS",
|
|
75
|
+
{ cause: error },
|
|
76
|
+
);
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
} finally {
|
|
80
|
+
rmSync(temp, { force: true });
|
|
81
|
+
}
|
|
82
|
+
plan.revision = next;
|
|
83
|
+
plan.brief = brief;
|
|
84
|
+
for (const [index, entry] of mutation.entries.entries())
|
|
85
|
+
Object.assign(entry, entries[index + entries.length - mutation.entries.length]);
|
|
86
|
+
await hooks.getStore()?.afterCommit?.();
|
|
87
|
+
await materialize(dir);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function viewContents(dir: string): [string, string][] {
|
|
91
|
+
const plan = reconcilePlan(dir);
|
|
92
|
+
if (plan === undefined || readRecords(dir).length === 0) return [];
|
|
93
|
+
const ledger = readLedgerAt(dir);
|
|
94
|
+
const views: [string, string][] = [
|
|
95
|
+
["goals.json", `${JSON.stringify(plan, null, 2)}\n`],
|
|
96
|
+
["ledger.jsonl", ledger.length === 0 ? "" : `${ledger.map((entry) => JSON.stringify(entry)).join("\n")}\n`],
|
|
97
|
+
["brief.md", plan.brief ?? readOptional(join(dir, "brief.md")) ?? ""],
|
|
98
|
+
];
|
|
99
|
+
return views.filter(([name, content]) => readOptional(join(dir, name)) !== content);
|
|
100
|
+
}
|
|
101
|
+
export function materializeSync(dir: string): void {
|
|
102
|
+
for (const [name, content] of viewContents(dir)) {
|
|
103
|
+
mkdirSync(join(dir, "tmp"), { recursive: true });
|
|
104
|
+
const temp = join(dir, "tmp", `${process.pid}-${randomUUID()}-${name}`);
|
|
105
|
+
try {
|
|
106
|
+
writeFileSync(temp, content, { flag: "wx" });
|
|
107
|
+
renameSync(temp, join(dir, name));
|
|
108
|
+
} finally {
|
|
109
|
+
rmSync(temp, { force: true });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export async function materialize(dir: string): Promise<void> {
|
|
114
|
+
for (const [name, content] of viewContents(dir)) {
|
|
115
|
+
mkdirSync(join(dir, "tmp"), { recursive: true });
|
|
116
|
+
const temp = join(dir, "tmp", `${process.pid}-${randomUUID()}-${name}`);
|
|
117
|
+
try {
|
|
118
|
+
await writeViewFile(temp, content);
|
|
119
|
+
await rename(temp, join(dir, name));
|
|
120
|
+
} finally {
|
|
121
|
+
rmSync(temp, { force: true });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
-
|
|
4
1
|
import { aggregateCodexObjectiveForScope, isUlwLoopDone } from "./goal-status.js";
|
|
5
2
|
import {
|
|
6
3
|
type UlwLoopScope,
|
|
7
|
-
ulwLoopBriefPath,
|
|
8
4
|
ulwLoopBriefRelativePath,
|
|
9
|
-
ulwLoopDir,
|
|
10
|
-
ulwLoopGoalsPath,
|
|
11
5
|
ulwLoopGoalsRelativePath,
|
|
12
|
-
ulwLoopLedgerPath,
|
|
13
6
|
ulwLoopLedgerRelativePath,
|
|
14
7
|
} from "./paths.js";
|
|
8
|
+
import { beforePlanMutation, commit } from "./plan-commit.js";
|
|
15
9
|
import { appendGoalToPlan, deriveGoalCandidates, makeGoal } from "./plan-goal-factory.js";
|
|
16
|
-
import {
|
|
17
|
-
import type {
|
|
10
|
+
import { planExists, readUlwLoopPlan, withUlwLoopMutationLock } from "./plan-io.js";
|
|
11
|
+
import type { SuccessCriterionInput } from "./success-criteria-input.js";
|
|
12
|
+
import type { UlwLoopToolkitSurface } from "./surface.js";
|
|
13
|
+
import type {
|
|
14
|
+
UlwLoopCodexGoalMode,
|
|
15
|
+
UlwLoopItem,
|
|
16
|
+
UlwLoopLedgerEntry,
|
|
17
|
+
UlwLoopPlan,
|
|
18
|
+
UlwLoopSuccessCriterion,
|
|
19
|
+
} from "./types.js";
|
|
18
20
|
import { iso, UlwLoopError } from "./types.js";
|
|
19
21
|
import { parseValidationBatches } from "./validation-batch.js";
|
|
20
22
|
|
|
21
23
|
export { deriveGoalCandidates, seedDefaultSuccessCriteria } from "./plan-goal-factory.js";
|
|
24
|
+
export type { SuccessCriterionInput } from "./success-criteria-input.js";
|
|
22
25
|
|
|
23
26
|
export type UlwLoopPlanSummary = {
|
|
24
27
|
readonly total: number;
|
|
@@ -60,11 +63,19 @@ export async function createUlwLoopPlan(
|
|
|
60
63
|
repoRoot: string,
|
|
61
64
|
args: { brief: string; codexGoalMode?: UlwLoopCodexGoalMode; force?: boolean; validationBatchesJson?: string },
|
|
62
65
|
scope?: UlwLoopScope,
|
|
66
|
+
surface: UlwLoopToolkitSurface = "lazycodex",
|
|
63
67
|
): Promise<UlwLoopPlan> {
|
|
64
68
|
return withUlwLoopMutationLock(repoRoot, scope, async () => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
let existing: UlwLoopPlan | undefined;
|
|
70
|
+
if (planExists(repoRoot, scope)) {
|
|
71
|
+
try {
|
|
72
|
+
existing = await readUlwLoopPlan(repoRoot, scope);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (!args.force) throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!args.force && existing !== undefined) {
|
|
78
|
+
if (isUlwLoopDone(existing)) throw completedPlanExistsError(scope, surface);
|
|
68
79
|
throw new UlwLoopError(
|
|
69
80
|
`Refusing to overwrite existing ${ulwLoopGoalsRelativePath(scope)}; pass --force to recreate it.`,
|
|
70
81
|
"ULW_LOOP_PLAN_EXISTS",
|
|
@@ -72,10 +83,13 @@ export async function createUlwLoopPlan(
|
|
|
72
83
|
}
|
|
73
84
|
const now = iso();
|
|
74
85
|
const goals = deriveGoalCandidates(args.brief).map((goal, index) =>
|
|
75
|
-
makeGoal(goal.title, goal.objective, index, now),
|
|
86
|
+
makeGoal(goal.title, goal.objective, index, now, { surface }),
|
|
76
87
|
);
|
|
77
88
|
const plan: UlwLoopPlan = {
|
|
78
89
|
version: 1,
|
|
90
|
+
revision: existing?.revision ?? 0,
|
|
91
|
+
ledgerResetRevision: (existing?.revision ?? 0) + 1,
|
|
92
|
+
brief: args.brief.endsWith("\n") ? args.brief : `${args.brief}\n`,
|
|
79
93
|
evidenceLayoutVersion: 2,
|
|
80
94
|
createdAt: now,
|
|
81
95
|
updatedAt: now,
|
|
@@ -88,29 +102,27 @@ export async function createUlwLoopPlan(
|
|
|
88
102
|
const validationBatches = await parseValidationBatches(args.validationBatchesJson, goals);
|
|
89
103
|
if (validationBatches !== undefined) plan.validationBatches = validationBatches;
|
|
90
104
|
if (plan.codexGoalMode === "aggregate") plan.codexObjective = aggregateCodexObjectiveForScope(scope);
|
|
91
|
-
await
|
|
92
|
-
await
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
);
|
|
97
|
-
await writePlan(repoRoot, plan, scope);
|
|
98
|
-
await writeFile(ulwLoopLedgerPath(repoRoot, scope), "", "utf8");
|
|
99
|
-
await appendLedger(
|
|
100
|
-
repoRoot,
|
|
101
|
-
{ at: now, kind: "plan_created", message: `${goals.length} goal(s) created` },
|
|
102
|
-
scope,
|
|
103
|
-
);
|
|
105
|
+
await beforePlanMutation();
|
|
106
|
+
await commit(repoRoot, scope, {
|
|
107
|
+
plan,
|
|
108
|
+
entries: [{ at: now, kind: "plan_created", message: `${goals.length} goal(s) created` }],
|
|
109
|
+
});
|
|
104
110
|
return plan;
|
|
105
111
|
});
|
|
106
112
|
}
|
|
107
113
|
|
|
108
|
-
function completedPlanExistsError(scope
|
|
114
|
+
function completedPlanExistsError(scope: UlwLoopScope | undefined, surface: UlwLoopToolkitSurface): UlwLoopError {
|
|
109
115
|
return new UlwLoopError(
|
|
110
116
|
[
|
|
111
117
|
`Existing ulw-loop aggregate is already complete at ${ulwLoopGoalsRelativePath(scope)}.`,
|
|
112
|
-
|
|
113
|
-
|
|
118
|
+
...(surface === "omo-senpi"
|
|
119
|
+
? [
|
|
120
|
+
"Start a new run under a fresh session id (a new senpi session) or call agentToolkit.createGoals({ brief, force: true }) to recreate.",
|
|
121
|
+
]
|
|
122
|
+
: [
|
|
123
|
+
"Start a new run with `omo-agent-toolkit ulw-loop create-goals --session-id <new-id> ...` to isolate fresh state.",
|
|
124
|
+
"Use --force only when you intentionally want to overwrite the completed evidence.",
|
|
125
|
+
]),
|
|
114
126
|
].join(" "),
|
|
115
127
|
"ULW_LOOP_PLAN_EXISTS_COMPLETE",
|
|
116
128
|
);
|
|
@@ -118,19 +130,21 @@ function completedPlanExistsError(scope?: UlwLoopScope): UlwLoopError {
|
|
|
118
130
|
|
|
119
131
|
export async function addUlwLoopGoal(
|
|
120
132
|
repoRoot: string,
|
|
121
|
-
args: { title: string; objective: string },
|
|
133
|
+
args: { title: string; objective: string; successCriteria?: readonly SuccessCriterionInput[] },
|
|
122
134
|
scope?: UlwLoopScope,
|
|
135
|
+
surface: UlwLoopToolkitSurface = "lazycodex",
|
|
123
136
|
): Promise<{ plan: UlwLoopPlan; goal: UlwLoopItem }> {
|
|
124
137
|
return withUlwLoopMutationLock(repoRoot, scope, async () => {
|
|
125
138
|
const plan = await readUlwLoopPlan(repoRoot, scope);
|
|
126
139
|
const now = iso();
|
|
127
|
-
const goal = appendGoalToPlan(plan, args.title, args.objective, now
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
140
|
+
const goal = appendGoalToPlan(plan, args.title, args.objective, now, {
|
|
141
|
+
surface,
|
|
142
|
+
...(args.successCriteria === undefined ? {} : { successCriteria: args.successCriteria }),
|
|
143
|
+
});
|
|
144
|
+
await commit(repoRoot, scope, {
|
|
145
|
+
plan,
|
|
146
|
+
entries: [{ at: now, kind: "goal_added", goalId: goal.id, status: goal.status, message: goal.title }],
|
|
147
|
+
});
|
|
134
148
|
return { plan, goal };
|
|
135
149
|
});
|
|
136
150
|
}
|
|
@@ -146,21 +160,18 @@ export async function startNextUlwLoop(
|
|
|
146
160
|
if (plan.aggregateCompletion?.status === "complete") return { done: true, plan };
|
|
147
161
|
const existing = plan.goals.find((goal) => goal.status === "in_progress" && isScheduleEligible(goal));
|
|
148
162
|
if (existing) return { plan, goal: existing, resumed: true };
|
|
163
|
+
const entries: UlwLoopLedgerEntry[] = [];
|
|
149
164
|
let next = plan.goals.find((goal) => goal.status === "pending" && isScheduleEligible(goal));
|
|
150
165
|
if (!next && args.retryFailed) {
|
|
151
166
|
next = plan.goals.find((goal) => goal.status === "failed" && !goal.nonRetriable && isScheduleEligible(goal));
|
|
152
167
|
if (next)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
...(next.failureReason ? { message: next.failureReason } : {}),
|
|
161
|
-
},
|
|
162
|
-
scope,
|
|
163
|
-
);
|
|
168
|
+
entries.push({
|
|
169
|
+
at: now,
|
|
170
|
+
kind: "goal_retried",
|
|
171
|
+
goalId: next.id,
|
|
172
|
+
status: "pending",
|
|
173
|
+
...(next.failureReason ? { message: next.failureReason } : {}),
|
|
174
|
+
});
|
|
164
175
|
}
|
|
165
176
|
if (!next) return { done: true, plan };
|
|
166
177
|
next.status = "in_progress";
|
|
@@ -170,12 +181,14 @@ export async function startNextUlwLoop(
|
|
|
170
181
|
next.updatedAt = now;
|
|
171
182
|
plan.activeGoalId = next.id;
|
|
172
183
|
plan.updatedAt = now;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
184
|
+
entries.push({
|
|
185
|
+
at: now,
|
|
186
|
+
kind: "goal_started",
|
|
187
|
+
goalId: next.id,
|
|
188
|
+
status: next.status,
|
|
189
|
+
message: `Attempt ${next.attempt}`,
|
|
190
|
+
});
|
|
191
|
+
await commit(repoRoot, scope, { plan, entries });
|
|
179
192
|
return { plan, goal: next, resumed: false };
|
|
180
193
|
});
|
|
181
194
|
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import { criteriaFromInput, criterionId, type SuccessCriterionInput } from "./success-criteria-input.js";
|
|
2
|
+
import type { UlwLoopToolkitSurface } from "./surface.js";
|
|
1
3
|
import type { UlwLoopItem, UlwLoopPlan, UlwLoopSuccessCriterion } from "./types.js";
|
|
2
4
|
import { UlwLoopError } from "./types.js";
|
|
3
5
|
|
|
6
|
+
export interface GoalSeedOptions {
|
|
7
|
+
readonly goalId?: string;
|
|
8
|
+
readonly surface?: UlwLoopToolkitSurface;
|
|
9
|
+
readonly successCriteria?: readonly SuccessCriterionInput[];
|
|
10
|
+
}
|
|
11
|
+
|
|
4
12
|
function cleanLine(line: string): string {
|
|
5
13
|
return line.replace(/^\s*(?:[-*+]\s+|\d+[.)]\s+)/, "").trim();
|
|
6
14
|
}
|
|
@@ -38,40 +46,44 @@ function truncateObjective(objective: string): string {
|
|
|
38
46
|
return objective.length > 80 ? `${objective.slice(0, 77).trimEnd()}...` : objective;
|
|
39
47
|
}
|
|
40
48
|
|
|
41
|
-
|
|
49
|
+
// The placeholder must name the exact call that replaces it on the surface the plan is driven from,
|
|
50
|
+
// so a goal seeded without criteria costs one documented call per criterion instead of a doc hunt.
|
|
51
|
+
function replaceVia(goalId: string, id: string, surface: UlwLoopToolkitSurface): string {
|
|
52
|
+
return surface === "omo-senpi"
|
|
53
|
+
? `Replace via agentToolkit.steer({ kind: "revise_criterion", source: "finding", goalId: "${goalId}", criterionId: "${id}", scenario, expectedEvidence, evidence, rationale }) (or pass successCriteria to addGoal)`
|
|
54
|
+
: `Replace via omo-agent-toolkit ulw-loop steer --kind revise_criterion --goal-id ${goalId} --criterion-id ${id} --scenario "<scenario>" --expected-evidence "<proof>" --evidence "<why>" --rationale "<why>"`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function seedDefaultSuccessCriteria(
|
|
58
|
+
goalIndex: number,
|
|
59
|
+
objective: string,
|
|
60
|
+
options: Pick<GoalSeedOptions, "goalId" | "surface"> = {},
|
|
61
|
+
): UlwLoopSuccessCriterion[] {
|
|
42
62
|
const subject = truncateObjective(normalizeObjective(objective) || `Goal ${goalIndex + 1}`);
|
|
63
|
+
const goalId = options.goalId ?? `G${String(goalIndex + 1).padStart(3, "0")}`;
|
|
64
|
+
const surface = options.surface ?? "lazycodex";
|
|
43
65
|
const rows = [
|
|
66
|
+
["happy", `happy path for: ${subject}`, `observable happy-path proof for goal ${goalIndex + 1}`, true],
|
|
67
|
+
["edge", "edge case (boundary/empty/malformed)", `boundary or malformed-input proof for: ${subject}`, true],
|
|
44
68
|
[
|
|
45
|
-
"C001",
|
|
46
|
-
"happy",
|
|
47
|
-
`happy path for: ${subject}`,
|
|
48
|
-
`Replace via revise_criterion with observable happy-path proof for goal ${goalIndex + 1}.`,
|
|
49
|
-
true,
|
|
50
|
-
],
|
|
51
|
-
[
|
|
52
|
-
"C002",
|
|
53
|
-
"edge",
|
|
54
|
-
"edge case (boundary/empty/malformed)",
|
|
55
|
-
`Replace via revise_criterion with boundary or malformed-input proof for: ${subject}.`,
|
|
56
|
-
true,
|
|
57
|
-
],
|
|
58
|
-
[
|
|
59
|
-
"C003",
|
|
60
69
|
"regression",
|
|
61
70
|
"regression: adjacent surface still works",
|
|
62
|
-
`
|
|
71
|
+
`regression proof for neighboring behavior after: ${subject}`,
|
|
63
72
|
false,
|
|
64
73
|
],
|
|
65
74
|
] as const;
|
|
66
|
-
return rows.map(([
|
|
67
|
-
id
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
return rows.map(([userModel, scenario, proof, essential], index) => {
|
|
76
|
+
const id = criterionId(index);
|
|
77
|
+
return {
|
|
78
|
+
id,
|
|
79
|
+
scenario,
|
|
80
|
+
userModel,
|
|
81
|
+
expectedEvidence: `${replaceVia(goalId, id, surface)} with ${proof}.`,
|
|
82
|
+
essential,
|
|
83
|
+
capturedEvidence: null,
|
|
84
|
+
status: "pending",
|
|
85
|
+
};
|
|
86
|
+
});
|
|
75
87
|
}
|
|
76
88
|
|
|
77
89
|
export function deriveGoalCandidates(brief: string): Array<{ title: string; objective: string }> {
|
|
@@ -101,23 +113,43 @@ export function deriveGoalCandidates(brief: string): Array<{ title: string; obje
|
|
|
101
113
|
}));
|
|
102
114
|
}
|
|
103
115
|
|
|
104
|
-
export function makeGoal(
|
|
116
|
+
export function makeGoal(
|
|
117
|
+
title: string,
|
|
118
|
+
objective: string,
|
|
119
|
+
index: number,
|
|
120
|
+
now: string,
|
|
121
|
+
options: GoalSeedOptions = {},
|
|
122
|
+
): UlwLoopItem {
|
|
105
123
|
const cleanTitle = assertNonEmpty(title, "title");
|
|
106
124
|
const cleanObjective = assertNonEmpty(objective, "objective");
|
|
125
|
+
const id = normalizeGoalId(cleanTitle, index);
|
|
126
|
+
const successCriteria =
|
|
127
|
+
options.successCriteria === undefined
|
|
128
|
+
? seedDefaultSuccessCriteria(index, cleanObjective, {
|
|
129
|
+
goalId: id,
|
|
130
|
+
...(options.surface === undefined ? {} : { surface: options.surface }),
|
|
131
|
+
})
|
|
132
|
+
: criteriaFromInput(options.successCriteria);
|
|
107
133
|
return {
|
|
108
|
-
id
|
|
134
|
+
id,
|
|
109
135
|
title: cleanTitle,
|
|
110
136
|
objective: cleanObjective,
|
|
111
137
|
status: "pending",
|
|
112
|
-
successCriteria
|
|
138
|
+
successCriteria,
|
|
113
139
|
attempt: 0,
|
|
114
140
|
createdAt: now,
|
|
115
141
|
updatedAt: now,
|
|
116
142
|
};
|
|
117
143
|
}
|
|
118
144
|
|
|
119
|
-
export function appendGoalToPlan(
|
|
120
|
-
|
|
145
|
+
export function appendGoalToPlan(
|
|
146
|
+
plan: UlwLoopPlan,
|
|
147
|
+
title: string,
|
|
148
|
+
objective: string,
|
|
149
|
+
now: string,
|
|
150
|
+
options: GoalSeedOptions = {},
|
|
151
|
+
): UlwLoopItem {
|
|
152
|
+
const goal = makeGoal(title, objective, plan.goals.length, now, options);
|
|
121
153
|
plan.goals.push(goal);
|
|
122
154
|
plan.updatedAt = now;
|
|
123
155
|
return goal;
|