oh-my-opencode 4.5.1 → 4.5.12
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/README.ja.md +33 -18
- package/README.ko.md +33 -18
- package/README.md +82 -24
- package/README.ru.md +33 -18
- package/README.zh-cn.md +45 -24
- package/bin/oh-my-opencode.js +47 -2
- package/bin/oh-my-opencode.test.ts +174 -0
- package/bin/platform.d.ts +6 -0
- package/bin/platform.js +19 -0
- package/bin/platform.test.ts +66 -1
- package/dist/cli/cli-program.d.ts +18 -0
- package/dist/cli/index.js +28472 -26159
- package/dist/cli/install-codex/codex-cache-bundled-mcps.d.ts +5 -0
- package/dist/cli/install-codex/codex-cache-command-shim.d.ts +1 -0
- package/dist/cli/install-codex/codex-cache-legacy-bins.d.ts +3 -0
- package/dist/cli/install-codex/codex-cache-local-dependencies.d.ts +1 -0
- package/dist/cli/install-codex/codex-cache-paths.d.ts +2 -0
- package/dist/cli/install-codex/codex-cache.d.ts +31 -0
- package/dist/cli/install-codex/codex-config-toml.d.ts +11 -0
- package/dist/cli/install-codex/codex-hook-trust.d.ts +6 -0
- package/dist/cli/install-codex/codex-marketplace-snapshot.d.ts +15 -0
- package/dist/cli/install-codex/codex-marketplace.d.ts +9 -0
- package/dist/cli/install-codex/codex-multi-agent-v2-config.d.ts +1 -0
- package/dist/cli/install-codex/codex-process.d.ts +2 -0
- package/dist/cli/install-codex/index.d.ts +7 -0
- package/dist/cli/install-codex/install-codex.d.ts +17 -0
- package/dist/cli/install-codex/link-cached-plugin-agents.d.ts +12 -0
- package/dist/cli/install-codex/toml-section-editor.d.ts +9 -0
- package/dist/cli/install-codex/types.d.ts +56 -0
- package/dist/cli/star-request.d.ts +2 -0
- package/dist/cli/tui-install-prompts.d.ts +3 -2
- package/dist/cli/types.d.ts +8 -0
- package/dist/config/schema/agent-names.d.ts +4 -1
- package/dist/config/schema/commands.d.ts +1 -2
- package/dist/config/schema/oh-my-opencode-config.d.ts +5 -3
- package/dist/create-managers.d.ts +1 -0
- package/dist/features/background-agent/parent-wake-message-activity.d.ts +23 -0
- package/dist/features/background-agent/parent-wake-notifier.d.ts +0 -1
- package/dist/features/boulder-state/storage.d.ts +1 -1
- package/dist/features/builtin-commands/templates/refactor.d.ts +1 -1
- package/dist/features/builtin-commands/templates/remove-ai-slops.d.ts +2 -2
- package/dist/features/builtin-commands/types.d.ts +1 -1
- package/dist/features/builtin-skills/skill-file-loader.d.ts +4 -0
- package/dist/features/builtin-skills/skills/index.d.ts +4 -1
- package/dist/features/builtin-skills/skills/init-deep.d.ts +2 -0
- package/dist/features/builtin-skills/skills/remove-ai-slops.d.ts +2 -0
- package/dist/features/builtin-skills/skills/security-research.d.ts +2 -0
- package/dist/features/builtin-skills/skills/security-review.d.ts +2 -0
- package/dist/features/opencode-runtime-skills/index.d.ts +2 -0
- package/dist/features/opencode-runtime-skills/runtime-skill-config.d.ts +17 -0
- package/dist/features/opencode-runtime-skills/skill-markdown.d.ts +7 -0
- package/dist/features/opencode-runtime-skills/source-server.d.ts +8 -0
- package/dist/hooks/claude-code-hooks/hook-text.d.ts +2 -0
- package/dist/hooks/session-recovery/storage/latest-assistant-message.d.ts +5 -0
- package/dist/hooks/session-recovery/storage/thinking-prepend.d.ts +3 -0
- package/dist/hooks/thinking-block-validator/hook.d.ts +0 -18
- package/dist/hooks/todo-continuation-enforcer/pending-question-detection.d.ts +4 -0
- package/dist/index.js +1684 -1801
- package/dist/oh-my-opencode.schema.json +4 -2
- package/dist/plugin-handlers/config-handler.d.ts +2 -1
- package/dist/shared/external-plugin-detector.d.ts +8 -0
- package/dist/shared/prompt-async-gate/message-inspection-error.d.ts +1 -0
- package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +1 -0
- package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +8 -0
- package/dist/shared/prompt-timeout-context.d.ts +2 -0
- package/dist/testing/create-plugin-module.d.ts +5 -1
- package/dist/tools/delegate-task/sync-prompt-sender.d.ts +2 -2
- package/package.json +31 -16
- package/packages/ast-grep-mcp/dist/cli.js +245 -40
- package/packages/lsp-tools-mcp/dist/cli.js +1 -1
- package/packages/omo-codex/marketplace.json +17 -0
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +35 -0
- package/packages/omo-codex/plugin/.mcp.json +14 -0
- package/packages/omo-codex/plugin/README.md +13 -0
- package/packages/omo-codex/plugin/components/comment-checker/.gitattributes +13 -0
- package/packages/omo-codex/plugin/components/comment-checker/.github/CODEOWNERS +12 -0
- package/packages/omo-codex/plugin/components/comment-checker/.github/ISSUE_TEMPLATE/bug.yml +40 -0
- package/packages/omo-codex/plugin/components/comment-checker/.github/ISSUE_TEMPLATE/feature.yml +27 -0
- package/packages/omo-codex/plugin/components/comment-checker/.github/branch-ruleset.json +45 -0
- package/packages/omo-codex/plugin/components/comment-checker/.github/dependabot.yml +16 -0
- package/packages/omo-codex/plugin/components/comment-checker/.github/pull_request_template.md +19 -0
- package/packages/omo-codex/plugin/components/comment-checker/.github/workflows/ci.yml +47 -0
- package/packages/omo-codex/plugin/components/comment-checker/.github/workflows/publish.yml +51 -0
- package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +35 -0
- package/packages/omo-codex/plugin/components/comment-checker/CHANGELOG.md +33 -0
- package/packages/omo-codex/plugin/components/comment-checker/LICENSE +21 -0
- package/packages/omo-codex/plugin/components/comment-checker/NOTICE +6 -0
- package/packages/omo-codex/plugin/components/comment-checker/README.md +87 -0
- package/packages/omo-codex/plugin/components/comment-checker/biome.json +48 -0
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +17 -0
- package/packages/omo-codex/plugin/components/comment-checker/package.json +57 -0
- package/packages/omo-codex/plugin/components/comment-checker/skills/comment-checker/SKILL.md +16 -0
- package/packages/omo-codex/plugin/components/comment-checker/src/cli.ts +12 -0
- package/packages/omo-codex/plugin/components/comment-checker/src/codex-hook.ts +205 -0
- package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +361 -0
- package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +195 -0
- package/packages/omo-codex/plugin/components/comment-checker/test/codex-hook-newline.test.ts +52 -0
- package/packages/omo-codex/plugin/components/comment-checker/test/codex-hook.test.ts +368 -0
- package/packages/omo-codex/plugin/components/comment-checker/test/fixtures/post-tool-use.json +15 -0
- package/packages/omo-codex/plugin/components/comment-checker/test/package-smoke.test.ts +93 -0
- package/packages/omo-codex/plugin/components/comment-checker/test/runner.test.ts +66 -0
- package/packages/omo-codex/plugin/components/comment-checker/tsconfig.build.json +12 -0
- package/packages/omo-codex/plugin/components/comment-checker/tsconfig.json +27 -0
- package/packages/omo-codex/plugin/components/comment-checker/vitest.config.ts +9 -0
- package/packages/omo-codex/plugin/components/lsp/.gitattributes +13 -0
- package/packages/omo-codex/plugin/components/lsp/.github/CODEOWNERS +1 -0
- package/packages/omo-codex/plugin/components/lsp/.github/ISSUE_TEMPLATE/bug.yml +26 -0
- package/packages/omo-codex/plugin/components/lsp/.github/ISSUE_TEMPLATE/feature.yml +19 -0
- package/packages/omo-codex/plugin/components/lsp/.github/branch-ruleset.json +45 -0
- package/packages/omo-codex/plugin/components/lsp/.github/dependabot.yml +11 -0
- package/packages/omo-codex/plugin/components/lsp/.github/pull_request_template.md +11 -0
- package/packages/omo-codex/plugin/components/lsp/.github/workflows/ci.yml +56 -0
- package/packages/omo-codex/plugin/components/lsp/.github/workflows/publish.yml +60 -0
- package/packages/omo-codex/plugin/components/lsp/.mcp.json +9 -0
- package/packages/omo-codex/plugin/components/lsp/AGENTS.md +25 -0
- package/packages/omo-codex/plugin/components/lsp/CHANGELOG.md +25 -0
- package/packages/omo-codex/plugin/components/lsp/LICENSE +21 -0
- package/packages/omo-codex/plugin/components/lsp/NOTICE +3 -0
- package/packages/omo-codex/plugin/components/lsp/README.md +148 -0
- package/packages/omo-codex/plugin/components/lsp/biome.json +48 -0
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +17 -0
- package/packages/omo-codex/plugin/components/lsp/package.json +64 -0
- package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-tools.mjs +46 -0
- package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-tools.test.mjs +104 -0
- package/packages/omo-codex/plugin/components/lsp/scripts/clean-dist.mjs +5 -0
- package/packages/omo-codex/plugin/components/lsp/scripts/test.mjs +8 -0
- package/packages/omo-codex/plugin/components/lsp/skills/lsp/SKILL.md +35 -0
- package/packages/omo-codex/plugin/components/lsp/src/cli.ts +44 -0
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +285 -0
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +358 -0
- package/packages/omo-codex/plugin/components/lsp/test/fixtures/broken.py +1 -0
- package/packages/omo-codex/plugin/components/lsp/test/fixtures/post-tool-use.json +15 -0
- package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +153 -0
- package/packages/omo-codex/plugin/components/lsp/tsconfig.build.json +12 -0
- package/packages/omo-codex/plugin/components/lsp/tsconfig.json +27 -0
- package/packages/omo-codex/plugin/components/lsp/vitest.config.ts +9 -0
- package/packages/omo-codex/plugin/components/rules/.codex-plugin/plugin.json +3 -0
- package/packages/omo-codex/plugin/components/rules/.gitattributes +13 -0
- package/packages/omo-codex/plugin/components/rules/.github/CODEOWNERS +12 -0
- package/packages/omo-codex/plugin/components/rules/.github/ISSUE_TEMPLATE/bug.yml +49 -0
- package/packages/omo-codex/plugin/components/rules/.github/ISSUE_TEMPLATE/feature.yml +27 -0
- package/packages/omo-codex/plugin/components/rules/.github/branch-ruleset.json +45 -0
- package/packages/omo-codex/plugin/components/rules/.github/dependabot.yml +16 -0
- package/packages/omo-codex/plugin/components/rules/.github/pull_request_template.md +20 -0
- package/packages/omo-codex/plugin/components/rules/.github/workflows/ci.yml +47 -0
- package/packages/omo-codex/plugin/components/rules/.github/workflows/publish.yml +51 -0
- package/packages/omo-codex/plugin/components/rules/AGENTS.md +34 -0
- package/packages/omo-codex/plugin/components/rules/CHANGELOG.md +19 -0
- package/packages/omo-codex/plugin/components/rules/LICENSE +21 -0
- package/packages/omo-codex/plugin/components/rules/NOTICE +15 -0
- package/packages/omo-codex/plugin/components/rules/README.md +124 -0
- package/packages/omo-codex/plugin/components/rules/biome.json +48 -0
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +209 -0
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +54 -0
- package/packages/omo-codex/plugin/components/rules/package.json +62 -0
- package/packages/omo-codex/plugin/components/rules/scripts/bench-codex-rules.mjs +268 -0
- package/packages/omo-codex/plugin/components/rules/skills/rules/SKILL.md +34 -0
- package/packages/omo-codex/plugin/components/rules/src/cli.ts +143 -0
- package/packages/omo-codex/plugin/components/rules/src/codex-hook-options.ts +4 -0
- package/packages/omo-codex/plugin/components/rules/src/codex-hook.ts +238 -0
- package/packages/omo-codex/plugin/components/rules/src/config.ts +107 -0
- package/packages/omo-codex/plugin/components/rules/src/context-pressure.ts +26 -0
- package/packages/omo-codex/plugin/components/rules/src/debug-log.ts +65 -0
- package/packages/omo-codex/plugin/components/rules/src/dynamic-target-fingerprints.ts +98 -0
- package/packages/omo-codex/plugin/components/rules/src/hook-output.ts +19 -0
- package/packages/omo-codex/plugin/components/rules/src/path-utils.ts +29 -0
- package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +234 -0
- package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +104 -0
- package/packages/omo-codex/plugin/components/rules/src/post-compact-claim.ts +13 -0
- package/packages/omo-codex/plugin/components/rules/src/post-compact-state.ts +45 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/cache.ts +64 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/constants.ts +115 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/engine.ts +535 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/errors.ts +13 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/finder-cache.ts +73 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/finder-paths.ts +47 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/finder-sources.ts +50 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/finder.ts +207 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/formatter.ts +123 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/matcher.ts +142 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/ordering.ts +33 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/parser.ts +326 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/plugin-root.ts +55 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/project-root.ts +30 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/scanner.ts +162 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/truncator.ts +67 -0
- package/packages/omo-codex/plugin/components/rules/src/rules/types.ts +141 -0
- package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +24 -0
- package/packages/omo-codex/plugin/components/rules/src/session-state-lock.ts +47 -0
- package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +56 -0
- package/packages/omo-codex/plugin/components/rules/src/tool-paths.ts +192 -0
- package/packages/omo-codex/plugin/components/rules/src/transcript-rule-filter.ts +44 -0
- package/packages/omo-codex/plugin/components/rules/src/transcript-search.ts +108 -0
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +107 -0
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +268 -0
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-context-pressure.test.ts +243 -0
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-performance.test.ts +99 -0
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +132 -0
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +156 -0
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +299 -0
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-lock.test.ts +46 -0
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-process.test.ts +83 -0
- package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +667 -0
- package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +192 -0
- package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +102 -0
- package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +168 -0
- package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +42 -0
- package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +206 -0
- package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +151 -0
- package/packages/omo-codex/plugin/components/rules/test/persistent-cache.test.ts +63 -0
- package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +172 -0
- package/packages/omo-codex/plugin/components/rules/test/post-compact-test-fixture.ts +196 -0
- package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +63 -0
- package/packages/omo-codex/plugin/components/rules/test/tool-paths.test.ts +198 -0
- package/packages/omo-codex/plugin/components/rules/tsconfig.build.json +12 -0
- package/packages/omo-codex/plugin/components/rules/tsconfig.json +27 -0
- package/packages/omo-codex/plugin/components/rules/vitest.config.ts +8 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/.gitattributes +13 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +43 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/CHANGELOG.md +5 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/LICENSE +21 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/NOTICE +5 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/README.md +55 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/biome.json +48 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +51 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +28 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +53 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +167 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/src/cli.ts +52 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/src/codex-hook.ts +66 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/src/directive.ts +6 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/src/index.ts +5 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/src/types.ts +23 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +63 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +124 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +160 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/boulder-completed.json +19 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/boulder-mixed-platforms.json +27 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/boulder-single-codex-work.json +19 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/plan-all-done.md +5 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/plan-with-nested-checkboxes.md +11 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/plan-with-unchecked.md +6 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/tsconfig.build.json +12 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/tsconfig.json +27 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/vitest.config.ts +10 -0
- package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +37 -0
- package/packages/omo-codex/plugin/components/telemetry/README.md +102 -0
- package/packages/omo-codex/plugin/components/telemetry/biome.json +48 -0
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +16 -0
- package/packages/omo-codex/plugin/components/telemetry/package.json +56 -0
- package/packages/omo-codex/plugin/components/telemetry/src/atomic-write.ts +22 -0
- package/packages/omo-codex/plugin/components/telemetry/src/cli.ts +69 -0
- package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +49 -0
- package/packages/omo-codex/plugin/components/telemetry/src/data-path.ts +45 -0
- package/packages/omo-codex/plugin/components/telemetry/src/env-flags.ts +43 -0
- package/packages/omo-codex/plugin/components/telemetry/src/posthog-activity-state.ts +81 -0
- package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +165 -0
- package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +35 -0
- package/packages/omo-codex/plugin/components/telemetry/test/codex-hook.test.ts +270 -0
- package/packages/omo-codex/plugin/components/telemetry/tsconfig.build.json +12 -0
- package/packages/omo-codex/plugin/components/telemetry/tsconfig.json +27 -0
- package/packages/omo-codex/plugin/components/telemetry/vitest.config.ts +8 -0
- package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +41 -0
- package/packages/omo-codex/plugin/components/ultrawork/CHANGELOG.md +25 -0
- package/packages/omo-codex/plugin/components/ultrawork/LICENSE +21 -0
- package/packages/omo-codex/plugin/components/ultrawork/NOTICE +5 -0
- package/packages/omo-codex/plugin/components/ultrawork/README.md +60 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/codex-ultrawork-reviewer.toml +17 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +82 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +221 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/metis.toml +65 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +69 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +163 -0
- package/packages/omo-codex/plugin/components/ultrawork/biome.json +48 -0
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +264 -0
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +16 -0
- package/packages/omo-codex/plugin/components/ultrawork/package.json +54 -0
- package/packages/omo-codex/plugin/components/ultrawork/src/cli.ts +50 -0
- package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +84 -0
- package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +3 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +252 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +78 -0
- package/packages/omo-codex/plugin/components/ultrawork/tsconfig.build.json +12 -0
- package/packages/omo-codex/plugin/components/ultrawork/tsconfig.json +27 -0
- package/packages/omo-codex/plugin/components/ulw-loop/.gitattributes +13 -0
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +48 -0
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/LICENSE +21 -0
- package/packages/omo-codex/plugin/components/ulw-loop/NOTICE +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +74 -0
- package/packages/omo-codex/plugin/components/ulw-loop/biome.json +48 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +29 -0
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +55 -0
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/.gitkeep +0 -0
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +222 -0
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/agents/openai.yaml +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/.gitkeep +0 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +155 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +95 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +156 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +63 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +94 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +40 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +129 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +139 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +177 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/evidence.ts +122 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +88 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +73 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +113 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +124 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +102 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +81 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +270 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/types.ts +277 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint.test.ts +213 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +375 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-helpers.test.ts +250 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering.test.ts +407 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +169 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +156 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +275 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/evidence-criteria-gate.test.ts +100 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/evidence.test.ts +263 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/.gitkeep +0 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/codex-goal-snapshot.json +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/sample-brief.md +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/sample-plan.json +108 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/sample-quality-gate.json +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/steering-proposal.json +8 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/user-prompt-submit.json +10 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/goal-status.test.ts +327 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +164 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +62 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-crud.test.ts +256 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +239 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +203 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/review-blockers.test.ts +180 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +353 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/types.test.ts +79 -0
- package/packages/omo-codex/plugin/components/ulw-loop/tsconfig.build.json +12 -0
- package/packages/omo-codex/plugin/components/ulw-loop/tsconfig.json +27 -0
- package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +10 -0
- package/packages/omo-codex/plugin/hooks/hooks.json +138 -0
- package/packages/omo-codex/plugin/package-lock.json +1750 -0
- package/packages/omo-codex/plugin/package.json +26 -0
- package/packages/omo-codex/plugin/scripts/build-bundled-mcp-runtimes.mjs +50 -0
- package/packages/omo-codex/plugin/scripts/build-components.mjs +23 -0
- package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +46 -0
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +75 -0
- package/packages/omo-codex/plugin/skills/comment-checker/SKILL.md +16 -0
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +116 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +108 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +130 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/04-oracle-triple.md +136 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/05-escalate.md +69 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/06-fix.md +116 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/08-qa.md +94 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/09-cleanup.md +164 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/partial-runtime-evidence.md +229 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/bundled-js-binary.md +415 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +252 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +484 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +260 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +248 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +234 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/ghidra.md +212 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/playwright-cli.md +194 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/pwndbg.md +263 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/pwntools.md +265 -0
- package/packages/omo-codex/plugin/skills/frontend-ui-ux/SKILL.md +77 -0
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +325 -0
- package/packages/omo-codex/plugin/skills/lsp/SKILL.md +35 -0
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +463 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/README.md +90 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/backend-stack.md +641 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/bootstrap.md +328 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/bubbletea-v2.md +360 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/cobra-stack.md +468 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/concurrency.md +362 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/data-modeling.md +329 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/error-handling.md +359 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/golangci-strict.md +236 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/grpc-connect.md +375 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/libraries.md +337 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/one-liners.md +202 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/sqlc-pgx.md +471 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/testing.md +467 -0
- package/packages/omo-codex/plugin/skills/programming/references/go/type-patterns.md +298 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/README.md +314 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/async-anyio.md +442 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/data-modeling.md +233 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/data-processing.md +133 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/error-handling.md +218 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/fastapi-stack.md +316 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/httpx2-optimization.md +360 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/libraries.md +307 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/one-liners.md +268 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/orjson-stack.md +378 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/pydantic-ai.md +285 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/pyproject-strict.md +232 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/textual-tui.md +201 -0
- package/packages/omo-codex/plugin/skills/programming/references/python/type-patterns.md +176 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/README.md +317 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/async-tokio.md +299 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/axum-stack.md +467 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/cargo-strict.md +317 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/clap-stack.md +409 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/concurrency.md +375 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/libraries.md +439 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/one-liners.md +291 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/proptest-insta.md +429 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/type-state.md +354 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/unsafe-discipline.md +250 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust/zero-cost-safety.md +527 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust-ub/README.md +289 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust-ub/miri-sanitizers-loom.md +411 -0
- package/packages/omo-codex/plugin/skills/programming/references/rust-ub/ub-taxonomy.md +269 -0
- package/packages/omo-codex/plugin/skills/programming/references/typescript/README.md +195 -0
- package/packages/omo-codex/plugin/skills/programming/references/typescript/backend-hono.md +672 -0
- package/packages/omo-codex/plugin/skills/programming/references/typescript/bootstrap.md +199 -0
- package/packages/omo-codex/plugin/skills/programming/references/typescript/data-modeling.md +202 -0
- package/packages/omo-codex/plugin/skills/programming/references/typescript/error-handling.md +169 -0
- package/packages/omo-codex/plugin/skills/programming/references/typescript/tsconfig-strict.md +152 -0
- package/packages/omo-codex/plugin/skills/programming/references/typescript/type-patterns.md +196 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/check-no-excuse-rules.sh +173 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/new-project.py +138 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/.editorconfig +13 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/.golangci.yml +95 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/AGENTS.md.tmpl +24 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/README.md.tmpl +12 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/Taskfile.yml +40 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/ci.yml +37 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/config.go +24 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/gitignore +15 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/main.go.tmpl +22 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/go/templates/run.go +15 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/python/check-no-excuse-rules.py +687 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/python/new-project.py +172 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/python/new-script.py +116 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/rust/check-no-excuse-rules.py +296 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/rust/check-no-excuse-rules.sh +158 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/rust/new-project.py +175 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +282 -0
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/new-project.ts +177 -0
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +779 -0
- package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +333 -0
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +549 -0
- package/packages/omo-codex/plugin/skills/rules/SKILL.md +34 -0
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +129 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/.gitkeep +0 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +222 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/agents/openai.yaml +6 -0
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +399 -0
- package/packages/omo-codex/plugin/test/aggregate.test.mjs +330 -0
- package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +66 -0
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +150 -0
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +199 -0
- package/packages/omo-codex/scripts/install/agents.mjs +84 -0
- package/packages/omo-codex/scripts/install/cache.mjs +245 -0
- package/packages/omo-codex/scripts/install/command-shim.mjs +1 -0
- package/packages/omo-codex/scripts/install/config.mjs +229 -0
- package/packages/omo-codex/scripts/install/hook-trust.mjs +84 -0
- package/packages/omo-codex/scripts/install/legacy-bins.mjs +57 -0
- package/packages/omo-codex/scripts/install/marketplace.mjs +104 -0
- package/packages/omo-codex/scripts/install/mcp-runtime-cache.mjs +77 -0
- package/packages/omo-codex/scripts/install/multi-agent-v2-config.mjs +32 -0
- package/packages/omo-codex/scripts/install/process.mjs +19 -0
- package/packages/omo-codex/scripts/install/snapshot.mjs +54 -0
- package/packages/omo-codex/scripts/install/toml-editor.mjs +47 -0
- package/packages/omo-codex/scripts/install/utils.mjs +15 -0
- package/packages/omo-codex/scripts/install-agent-links.test.mjs +104 -0
- package/packages/omo-codex/scripts/install-bin-links.test.mjs +123 -0
- package/packages/omo-codex/scripts/install-cache-copy.test.mjs +30 -0
- package/packages/omo-codex/scripts/install-config.test.mjs +118 -0
- package/packages/omo-codex/scripts/install-local.mjs +192 -0
- package/packages/omo-codex/scripts/install-local.test.mjs +379 -0
- package/packages/omo-codex/scripts/install-mcp-runtime.test.mjs +173 -0
- package/packages/omo-codex/scripts/install-test-fixtures.mjs +58 -0
- package/packages/omo-codex/scripts/sync-telemetry-component.mjs +115 -0
- package/packages/omo-codex/scripts/sync-telemetry-component.test.mjs +94 -0
- package/packages/shared-skills/index.mjs +5 -0
- package/packages/shared-skills/package.json +14 -0
- package/packages/shared-skills/skills/debugging/SKILL.md +116 -0
- package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +108 -0
- package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +130 -0
- package/packages/shared-skills/skills/debugging/references/methodology/04-oracle-triple.md +136 -0
- package/packages/shared-skills/skills/debugging/references/methodology/05-escalate.md +69 -0
- package/packages/shared-skills/skills/debugging/references/methodology/06-fix.md +116 -0
- package/packages/shared-skills/skills/debugging/references/methodology/08-qa.md +94 -0
- package/packages/shared-skills/skills/debugging/references/methodology/09-cleanup.md +164 -0
- package/packages/shared-skills/skills/debugging/references/methodology/partial-runtime-evidence.md +229 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/bundled-js-binary.md +415 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/go.md +252 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +484 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/node.md +260 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/python.md +248 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +234 -0
- package/packages/shared-skills/skills/debugging/references/tools/ghidra.md +212 -0
- package/packages/shared-skills/skills/debugging/references/tools/playwright-cli.md +194 -0
- package/packages/shared-skills/skills/debugging/references/tools/pwndbg.md +263 -0
- package/packages/shared-skills/skills/debugging/references/tools/pwntools.md +265 -0
- package/packages/shared-skills/skills/frontend-ui-ux/SKILL.md +77 -0
- package/packages/shared-skills/skills/init-deep/SKILL.md +309 -0
- package/packages/shared-skills/skills/programming/SKILL.md +463 -0
- package/packages/shared-skills/skills/programming/references/go/README.md +90 -0
- package/packages/shared-skills/skills/programming/references/go/backend-stack.md +641 -0
- package/packages/shared-skills/skills/programming/references/go/bootstrap.md +328 -0
- package/packages/shared-skills/skills/programming/references/go/bubbletea-v2.md +360 -0
- package/packages/shared-skills/skills/programming/references/go/cobra-stack.md +468 -0
- package/packages/shared-skills/skills/programming/references/go/concurrency.md +362 -0
- package/packages/shared-skills/skills/programming/references/go/data-modeling.md +329 -0
- package/packages/shared-skills/skills/programming/references/go/error-handling.md +359 -0
- package/packages/shared-skills/skills/programming/references/go/golangci-strict.md +236 -0
- package/packages/shared-skills/skills/programming/references/go/grpc-connect.md +375 -0
- package/packages/shared-skills/skills/programming/references/go/libraries.md +337 -0
- package/packages/shared-skills/skills/programming/references/go/one-liners.md +202 -0
- package/packages/shared-skills/skills/programming/references/go/sqlc-pgx.md +471 -0
- package/packages/shared-skills/skills/programming/references/go/testing.md +467 -0
- package/packages/shared-skills/skills/programming/references/go/type-patterns.md +298 -0
- package/packages/shared-skills/skills/programming/references/python/README.md +314 -0
- package/packages/shared-skills/skills/programming/references/python/async-anyio.md +442 -0
- package/packages/shared-skills/skills/programming/references/python/data-modeling.md +233 -0
- package/packages/shared-skills/skills/programming/references/python/data-processing.md +133 -0
- package/packages/shared-skills/skills/programming/references/python/error-handling.md +218 -0
- package/packages/shared-skills/skills/programming/references/python/fastapi-stack.md +316 -0
- package/packages/shared-skills/skills/programming/references/python/httpx2-optimization.md +360 -0
- package/packages/shared-skills/skills/programming/references/python/libraries.md +307 -0
- package/packages/shared-skills/skills/programming/references/python/one-liners.md +268 -0
- package/packages/shared-skills/skills/programming/references/python/orjson-stack.md +378 -0
- package/packages/shared-skills/skills/programming/references/python/pydantic-ai.md +285 -0
- package/packages/shared-skills/skills/programming/references/python/pyproject-strict.md +232 -0
- package/packages/shared-skills/skills/programming/references/python/textual-tui.md +201 -0
- package/packages/shared-skills/skills/programming/references/python/type-patterns.md +176 -0
- package/packages/shared-skills/skills/programming/references/rust/README.md +317 -0
- package/packages/shared-skills/skills/programming/references/rust/async-tokio.md +299 -0
- package/packages/shared-skills/skills/programming/references/rust/axum-stack.md +467 -0
- package/packages/shared-skills/skills/programming/references/rust/cargo-strict.md +317 -0
- package/packages/shared-skills/skills/programming/references/rust/clap-stack.md +409 -0
- package/packages/shared-skills/skills/programming/references/rust/concurrency.md +375 -0
- package/packages/shared-skills/skills/programming/references/rust/libraries.md +439 -0
- package/packages/shared-skills/skills/programming/references/rust/one-liners.md +291 -0
- package/packages/shared-skills/skills/programming/references/rust/proptest-insta.md +429 -0
- package/packages/shared-skills/skills/programming/references/rust/type-state.md +354 -0
- package/packages/shared-skills/skills/programming/references/rust/unsafe-discipline.md +250 -0
- package/packages/shared-skills/skills/programming/references/rust/zero-cost-safety.md +527 -0
- package/packages/shared-skills/skills/programming/references/rust-ub/README.md +289 -0
- package/packages/shared-skills/skills/programming/references/rust-ub/miri-sanitizers-loom.md +411 -0
- package/packages/shared-skills/skills/programming/references/rust-ub/ub-taxonomy.md +269 -0
- package/packages/shared-skills/skills/programming/references/typescript/README.md +195 -0
- package/packages/shared-skills/skills/programming/references/typescript/backend-hono.md +672 -0
- package/packages/shared-skills/skills/programming/references/typescript/bootstrap.md +199 -0
- package/packages/shared-skills/skills/programming/references/typescript/data-modeling.md +202 -0
- package/packages/shared-skills/skills/programming/references/typescript/error-handling.md +169 -0
- package/packages/shared-skills/skills/programming/references/typescript/tsconfig-strict.md +152 -0
- package/packages/shared-skills/skills/programming/references/typescript/type-patterns.md +196 -0
- package/packages/shared-skills/skills/programming/scripts/go/check-no-excuse-rules.sh +173 -0
- package/packages/shared-skills/skills/programming/scripts/go/new-project.py +138 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/.editorconfig +13 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/.golangci.yml +95 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/AGENTS.md.tmpl +24 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/README.md.tmpl +12 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/Taskfile.yml +40 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/ci.yml +37 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/config.go +24 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/gitignore +15 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/main.go.tmpl +22 -0
- package/packages/shared-skills/skills/programming/scripts/go/templates/run.go +15 -0
- package/packages/shared-skills/skills/programming/scripts/python/check-no-excuse-rules.py +687 -0
- package/packages/shared-skills/skills/programming/scripts/python/new-project.py +172 -0
- package/packages/shared-skills/skills/programming/scripts/python/new-script.py +116 -0
- package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.py +296 -0
- package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.sh +158 -0
- package/packages/shared-skills/skills/programming/scripts/rust/new-project.py +175 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +282 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/new-project.ts +177 -0
- package/packages/shared-skills/skills/refactor/SKILL.md +763 -0
- package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +317 -0
- package/packages/shared-skills/skills/review-work/SKILL.md +549 -0
- package/packages/shared-skills/skills/start-work/SKILL.md +129 -0
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +383 -0
- package/postinstall.mjs +6 -2
- package/dist/features/builtin-commands/templates/init-deep.d.ts +0 -1
- package/dist/features/builtin-skills/skills/ai-slop-remover.d.ts +0 -2
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { appendFile, mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
|
|
3
|
+
import { aggregateCodexObjectiveForScope } from "./goal-status.js";
|
|
4
|
+
import {
|
|
5
|
+
repoRelative,
|
|
6
|
+
type UlwLoopScope,
|
|
7
|
+
ulwLoopDir,
|
|
8
|
+
ulwLoopGoalsPath,
|
|
9
|
+
ulwLoopLedgerPath,
|
|
10
|
+
ulwLoopRelativeDir,
|
|
11
|
+
} from "./paths.js";
|
|
12
|
+
import type { UlwLoopLedgerEntry, UlwLoopPlan } from "./types.js";
|
|
13
|
+
import { iso, ULW_LOOP_DIR, ULW_LOOP_GOALS, ULW_LOOP_LEDGER, UlwLoopError } from "./types.js";
|
|
14
|
+
|
|
15
|
+
const LEGACY_OBJECTIVE_PREFIX = `Complete all ulw-loop stories in ${ULW_LOOP_DIR}/${ULW_LOOP_GOALS}: `;
|
|
16
|
+
const LEGACY_OBJECTIVE = `Complete all ulw-loop stories listed in ${ULW_LOOP_DIR}/${ULW_LOOP_GOALS}. Use ${ULW_LOOP_DIR}/${ULW_LOOP_LEDGER} as the durable audit trail.`;
|
|
17
|
+
const locks = new Map<string, Promise<unknown>>();
|
|
18
|
+
|
|
19
|
+
function hasCode(error: unknown, code: string): boolean {
|
|
20
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isLegacyEnumeratedAggregateObjective(objective: string | undefined): objective is string {
|
|
24
|
+
return objective === LEGACY_OBJECTIVE || Boolean(objective?.startsWith(LEGACY_OBJECTIVE_PREFIX));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isSteeringKind(value: unknown): value is UlwLoopLedgerEntry["kind"] {
|
|
28
|
+
return value === "steering_accepted" || value === "steering_rejected" || value === "criteria_revised";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function withUlwLoopMutationLock<T>(repoRoot: string, fn: () => Promise<T>): Promise<T>;
|
|
32
|
+
export async function withUlwLoopMutationLock<T>(
|
|
33
|
+
repoRoot: string,
|
|
34
|
+
scope: UlwLoopScope | undefined,
|
|
35
|
+
fn: () => Promise<T>,
|
|
36
|
+
): Promise<T>;
|
|
37
|
+
export async function withUlwLoopMutationLock<T>(
|
|
38
|
+
repoRoot: string,
|
|
39
|
+
scopeOrFn: UlwLoopScope | (() => Promise<T>) | undefined,
|
|
40
|
+
maybeFn?: () => Promise<T>,
|
|
41
|
+
): Promise<T> {
|
|
42
|
+
const scope = typeof scopeOrFn === "function" ? undefined : scopeOrFn;
|
|
43
|
+
const fn = typeof scopeOrFn === "function" ? scopeOrFn : maybeFn;
|
|
44
|
+
if (fn === undefined) throw new UlwLoopError("Missing ulw-loop mutation body.", "ULW_LOOP_LOCK_BODY_MISSING");
|
|
45
|
+
const lockKey = `${repoRoot}\0${ulwLoopRelativeDir(scope)}`;
|
|
46
|
+
const prior = locks.get(lockKey) ?? Promise.resolve();
|
|
47
|
+
const run = prior.then(fn, fn);
|
|
48
|
+
locks.set(
|
|
49
|
+
lockKey,
|
|
50
|
+
run.catch(() => undefined),
|
|
51
|
+
);
|
|
52
|
+
return run;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function readUlwLoopPlan(repoRoot: string, scope?: UlwLoopScope): Promise<UlwLoopPlan> {
|
|
56
|
+
const path = ulwLoopGoalsPath(repoRoot, scope);
|
|
57
|
+
let raw: string;
|
|
58
|
+
try {
|
|
59
|
+
raw = await readFile(path, "utf8");
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (!hasCode(error, "ENOENT")) throw error;
|
|
62
|
+
throw new UlwLoopError(
|
|
63
|
+
`No ulw-loop plan found at ${repoRelative(path, repoRoot)}. Run \`omo ulw-loop create-goals ...\` first.`,
|
|
64
|
+
"ULW_LOOP_PLAN_MISSING",
|
|
65
|
+
{ cause: error },
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
const parsed: UlwLoopPlan = JSON.parse(raw);
|
|
69
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.goals)) {
|
|
70
|
+
throw new UlwLoopError(`Invalid ulw-loop plan at ${repoRelative(path, repoRoot)}.`, "ULW_LOOP_PLAN_INVALID");
|
|
71
|
+
}
|
|
72
|
+
const previousObjective = parsed.codexObjective;
|
|
73
|
+
if (
|
|
74
|
+
(parsed.codexGoalMode ?? "per_story") === "aggregate" &&
|
|
75
|
+
isLegacyEnumeratedAggregateObjective(previousObjective)
|
|
76
|
+
) {
|
|
77
|
+
const now = iso();
|
|
78
|
+
parsed.codexObjective = aggregateCodexObjectiveForScope(scope);
|
|
79
|
+
parsed.codexObjectiveAliases = [...new Set([...(parsed.codexObjectiveAliases ?? []), previousObjective])];
|
|
80
|
+
parsed.updatedAt = now;
|
|
81
|
+
await writePlan(repoRoot, parsed, scope);
|
|
82
|
+
await appendLedger(
|
|
83
|
+
repoRoot,
|
|
84
|
+
{
|
|
85
|
+
at: now,
|
|
86
|
+
kind: "aggregate_objective_migrated",
|
|
87
|
+
message: "Migrated legacy enumerated aggregate Codex objective to the stable pointer objective.",
|
|
88
|
+
before: { codexObjective: previousObjective },
|
|
89
|
+
after: { codexObjective: parsed.codexObjective },
|
|
90
|
+
},
|
|
91
|
+
scope,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return parsed;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function writePlan(repoRoot: string, plan: UlwLoopPlan, scope?: UlwLoopScope): Promise<void> {
|
|
98
|
+
await mkdir(ulwLoopDir(repoRoot, scope), { recursive: true });
|
|
99
|
+
const path = ulwLoopGoalsPath(repoRoot, scope);
|
|
100
|
+
const tmpPath = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
101
|
+
await writeFile(tmpPath, `${JSON.stringify(plan, null, 2)}\n`, "utf8");
|
|
102
|
+
await rename(tmpPath, path);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function appendLedger(repoRoot: string, entry: UlwLoopLedgerEntry, scope?: UlwLoopScope): Promise<void> {
|
|
106
|
+
await mkdir(ulwLoopDir(repoRoot, scope), { recursive: true });
|
|
107
|
+
await appendFile(ulwLoopLedgerPath(repoRoot, scope), `${JSON.stringify(entry)}\n`, "utf8");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function readSteeringLedgerEntries(repoRoot: string, scope?: UlwLoopScope): Promise<UlwLoopLedgerEntry[]> {
|
|
111
|
+
let raw: string;
|
|
112
|
+
try {
|
|
113
|
+
raw = await readFile(ulwLoopLedgerPath(repoRoot, scope), "utf8");
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (hasCode(error, "ENOENT")) return [];
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
const entries: UlwLoopLedgerEntry[] = [];
|
|
119
|
+
for (const line of raw.split(/\r?\n/).filter(Boolean)) {
|
|
120
|
+
const entry: UlwLoopLedgerEntry = JSON.parse(line);
|
|
121
|
+
if (isSteeringKind(entry.kind)) entries.push(entry);
|
|
122
|
+
}
|
|
123
|
+
return entries;
|
|
124
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { UlwLoopItem, UlwLoopPlan, UlwLoopQualityGate } from "./types.js";
|
|
2
|
+
import { UlwLoopError } from "./types.js";
|
|
3
|
+
|
|
4
|
+
const BLOCKER_FIELD_KEYS = "blocker blockerSignature blockerEvidence blockerOccurrences blockedAt".split(" ");
|
|
5
|
+
const URL_PATTERN = /https?:\/\/\S+/g;
|
|
6
|
+
const PUNCTUATION_PATTERN = /[`"'()[\]{}:,;]/g;
|
|
7
|
+
const WHITESPACE_PATTERN = /\s+/g;
|
|
8
|
+
const AUTH_PATTERN = /\b(auth\w*|credential\w*|token|permission\w*|scope\w*|access|unauthorized|forbidden|401|403)\b/;
|
|
9
|
+
const MISSING_PATTERN =
|
|
10
|
+
/\b(unset|missing|required|requires|without|omit\w*|not set|not available|no read packages|read packages)\b/;
|
|
11
|
+
const GHCR_PATTERN =
|
|
12
|
+
/\b(ghcr|github container registry|read packages|imagepullsecret|package api|anonymous|container image)\b/;
|
|
13
|
+
const GHCR_401_PATTERN = /\b(401|unauthorized|anonymous pull|authentication required)\b/;
|
|
14
|
+
const GHCR_403_PATTERN = /\b(403|forbidden|read packages|package api)\b/;
|
|
15
|
+
|
|
16
|
+
function invalid(message: string, field: string): never {
|
|
17
|
+
throw new UlwLoopError(message, "ULW_LOOP_QUALITY_GATE_INVALID", { details: { field } });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
21
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function section(value: unknown, field: string): Record<string, unknown> {
|
|
25
|
+
return isRecord(value) ? value : invalid(`Final quality gate is missing ${field} evidence.`, field);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function nonEmptyString(value: unknown, field: string): string {
|
|
29
|
+
return typeof value === "string" && value.trim() !== ""
|
|
30
|
+
? value
|
|
31
|
+
: invalid(`Final quality gate requires non-empty ${field}.`, field);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function numberField(value: unknown, field: string): number {
|
|
35
|
+
return typeof value === "number" && Number.isFinite(value)
|
|
36
|
+
? value
|
|
37
|
+
: invalid(`Final quality gate requires numeric ${field}.`, field);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function stringArray(value: unknown, field: string): string[] {
|
|
41
|
+
if (!Array.isArray(value) || value.length === 0) return invalid(`Final quality gate requires ${field}.`, field);
|
|
42
|
+
return value.map((item) => nonEmptyString(item, field));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function validateQualityGate(input: unknown): UlwLoopQualityGate {
|
|
46
|
+
const gate = section(input, "qualityGate");
|
|
47
|
+
const cleaner = section(gate["aiSlopCleaner"], "aiSlopCleaner");
|
|
48
|
+
const verification = section(gate["verification"], "verification");
|
|
49
|
+
const review = section(gate["codeReview"], "codeReview");
|
|
50
|
+
const coverage = section(gate["criteriaCoverage"], "criteriaCoverage");
|
|
51
|
+
if (cleaner["status"] !== "passed") invalid("aiSlopCleaner.status must be passed.", "aiSlopCleaner.status");
|
|
52
|
+
if (verification["status"] !== "passed") invalid("verification.status must be passed.", "verification.status");
|
|
53
|
+
if (review["recommendation"] !== "APPROVE") invalid("recommendation must be APPROVE.", "codeReview.recommendation");
|
|
54
|
+
if (review["architectStatus"] !== "CLEAR") invalid("architectStatus must be CLEAR.", "codeReview.architectStatus");
|
|
55
|
+
const totalCriteria = numberField(coverage["totalCriteria"], "criteriaCoverage.totalCriteria");
|
|
56
|
+
const passCount = numberField(coverage["passCount"], "criteriaCoverage.passCount");
|
|
57
|
+
if (passCount < totalCriteria)
|
|
58
|
+
invalid("criteriaCoverage.passCount must cover totalCriteria.", "criteriaCoverage.passCount");
|
|
59
|
+
const commands = stringArray(verification["commands"], "verification.commands");
|
|
60
|
+
const covered = stringArray(coverage["adversarialClassesCovered"], "criteriaCoverage.adversarialClassesCovered");
|
|
61
|
+
const cleanerEvidence = nonEmptyString(cleaner["evidence"], "aiSlopCleaner.evidence");
|
|
62
|
+
const verificationEvidence = nonEmptyString(verification["evidence"], "verification.evidence");
|
|
63
|
+
const reviewEvidence = nonEmptyString(review["evidence"], "codeReview.evidence");
|
|
64
|
+
const result: UlwLoopQualityGate = {
|
|
65
|
+
aiSlopCleaner: { status: "passed", evidence: cleanerEvidence },
|
|
66
|
+
verification: { status: "passed", commands, evidence: verificationEvidence },
|
|
67
|
+
codeReview: { recommendation: "APPROVE", architectStatus: "CLEAR", evidence: reviewEvidence },
|
|
68
|
+
};
|
|
69
|
+
Object.assign(result, { criteriaCoverage: { totalCriteria, passCount, adversarialClassesCovered: covered } });
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function normalizeBlockerEvidence(evidence: string): string {
|
|
74
|
+
const withoutUrls = evidence.toLowerCase().replace(URL_PATTERN, " ");
|
|
75
|
+
const withoutPunctuation = withoutUrls.replace(PUNCTUATION_PATTERN, " ");
|
|
76
|
+
return withoutPunctuation.replace(WHITESPACE_PATTERN, " ").trim();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function classifyExternalAuthorizationBlocker(evidence: string): string | null {
|
|
80
|
+
const normalized = normalizeBlockerEvidence(evidence);
|
|
81
|
+
if (!normalized || !AUTH_PATTERN.test(normalized) || !MISSING_PATTERN.test(normalized)) return null;
|
|
82
|
+
if (!GHCR_PATTERN.test(normalized)) return "EXTERNAL_AUTHORIZATION_REQUIRED";
|
|
83
|
+
const status401 = GHCR_401_PATTERN.test(normalized) ? "HTTP_401_ANONYMOUS" : null;
|
|
84
|
+
const status403 = GHCR_403_PATTERN.test(normalized) ? "HTTP_403_NO_READ_PACKAGES" : null;
|
|
85
|
+
const status = [status401, status403].filter((part): part is string => part !== null).join("+");
|
|
86
|
+
return `GHCR_PULL_ACCESS:${status || "AUTHORIZATION_REQUIRED"}:GHCR_VISIBILITY_OR_CREDENTIAL_REQUIRED`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function nestedBlockerSignature(goal: UlwLoopItem): string | null {
|
|
90
|
+
const blocker = Reflect.get(goal, "blocker");
|
|
91
|
+
const signature = isRecord(blocker) ? blocker["signature"] : null;
|
|
92
|
+
return typeof signature === "string" ? signature : null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function sameBlockerOccurrences(plan: UlwLoopPlan, signature: string): number {
|
|
96
|
+
return plan.goals.filter((goal) => goal.blockerSignature === signature || nestedBlockerSignature(goal) === signature)
|
|
97
|
+
.length;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function clearGoalBlockerFields(goal: UlwLoopItem): void {
|
|
101
|
+
for (const key of BLOCKER_FIELD_KEYS) Reflect.deleteProperty(goal, key);
|
|
102
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// biome-ignore-all format: compact port must stay within the requested pure LOC budget.
|
|
2
|
+
|
|
3
|
+
import { readCodexGoalSnapshotInput, reconcileCodexGoalSnapshot } from "./codex-goal-snapshot.js";
|
|
4
|
+
import { codexGoalMode, compatibleCodexObjectives, expectedCodexObjective, isFinalRunCompletionCandidate } from "./goal-status.js";
|
|
5
|
+
import type { UlwLoopScope } from "./paths.js";
|
|
6
|
+
import { seedDefaultSuccessCriteria } from "./plan-crud.js";
|
|
7
|
+
import { appendLedger, readUlwLoopPlan, withUlwLoopMutationLock, writePlan } from "./plan-io.js";
|
|
8
|
+
import type { UlwLoopItem, UlwLoopLedgerEntry, UlwLoopPlan } from "./types.js";
|
|
9
|
+
import { iso, UlwLoopError } from "./types.js";
|
|
10
|
+
|
|
11
|
+
export interface RecordFinalReviewBlockersArgs { readonly goalId: string; readonly title: string; readonly objective: string; readonly evidence: string; readonly codexGoalJson: string }
|
|
12
|
+
export interface RecordFinalReviewBlockersResult { readonly plan: UlwLoopPlan; readonly blockedGoal: UlwLoopItem; readonly newGoal: UlwLoopItem; readonly ledgerEntries: UlwLoopLedgerEntry[] }
|
|
13
|
+
|
|
14
|
+
const BLOCKER_FIELDS = "blockedReason blockerSignature blockerOccurrenceCount requiredExternalDecision nonRetriable failedAt failureReason completedAt blocker blockerEvidence blockerOccurrences blockedAt".split(" ");
|
|
15
|
+
|
|
16
|
+
function ulwLoopError(message: string, code: string): never {
|
|
17
|
+
throw new UlwLoopError(message, code);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function nextGoalId(plan: UlwLoopPlan): string {
|
|
21
|
+
const max = plan.goals.reduce((current, goal) => {
|
|
22
|
+
const digits = /^G(\d+)/u.exec(goal.id)?.[1];
|
|
23
|
+
return digits === undefined ? current : Math.max(current, Number(digits));
|
|
24
|
+
}, 0);
|
|
25
|
+
return `G${String(max + 1).padStart(3, "0")}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function appendBlockerGoal(plan: UlwLoopPlan, args: RecordFinalReviewBlockersArgs, now: string): UlwLoopItem {
|
|
29
|
+
const index = plan.goals.length;
|
|
30
|
+
const goal: UlwLoopItem = {
|
|
31
|
+
id: nextGoalId(plan),
|
|
32
|
+
title: args.title,
|
|
33
|
+
objective: args.objective,
|
|
34
|
+
status: "pending",
|
|
35
|
+
successCriteria: seedDefaultSuccessCriteria(index, args.objective),
|
|
36
|
+
attempt: 0,
|
|
37
|
+
createdAt: now,
|
|
38
|
+
updatedAt: now,
|
|
39
|
+
};
|
|
40
|
+
plan.goals.push(goal);
|
|
41
|
+
return goal;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function recordFinalReviewBlockers(
|
|
45
|
+
repoRoot: string,
|
|
46
|
+
args: RecordFinalReviewBlockersArgs,
|
|
47
|
+
scope?: UlwLoopScope,
|
|
48
|
+
): Promise<RecordFinalReviewBlockersResult> {
|
|
49
|
+
return withUlwLoopMutationLock(repoRoot, scope, async () => {
|
|
50
|
+
const plan = await readUlwLoopPlan(repoRoot, scope);
|
|
51
|
+
const goal = plan.goals.find((candidate) => candidate.id === args.goalId);
|
|
52
|
+
if (goal === undefined) ulwLoopError(`Unknown ulw-loop id: ${args.goalId}`, "ulw_loop_goal_not_found");
|
|
53
|
+
if (goal.status !== "in_progress") ulwLoopError(`${goal.id} is ${goal.status}.`, "ulw_loop_goal_not_in_progress");
|
|
54
|
+
if (!isFinalRunCompletionCandidate(plan, goal)) ulwLoopError(`${goal.id} is not final.`, "ulw_loop_not_final_story");
|
|
55
|
+
|
|
56
|
+
const snapshot = await readCodexGoalSnapshotInput(args.codexGoalJson, repoRoot);
|
|
57
|
+
const aggregate = codexGoalMode(plan) === "aggregate";
|
|
58
|
+
const reconciliation = reconcileCodexGoalSnapshot(snapshot, { expectedObjective: expectedCodexObjective(plan, goal), ...(aggregate ? { acceptedObjectives: compatibleCodexObjectives(plan) } : {}), allowedStatuses: ["active"], requireSnapshot: true, requireComplete: false });
|
|
59
|
+
if (!reconciliation.ok) ulwLoopError(reconciliation.errors.join(" "), "ulw_loop_codex_snapshot_mismatch");
|
|
60
|
+
|
|
61
|
+
const now = iso();
|
|
62
|
+
for (const field of BLOCKER_FIELDS) Reflect.deleteProperty(goal, field);
|
|
63
|
+
goal.status = "review_blocked";
|
|
64
|
+
goal.reviewBlockedAt = now;
|
|
65
|
+
goal.evidence = args.evidence;
|
|
66
|
+
goal.updatedAt = now;
|
|
67
|
+
if (plan.activeGoalId === goal.id) delete plan.activeGoalId;
|
|
68
|
+
const newGoal = appendBlockerGoal(plan, args, now);
|
|
69
|
+
plan.updatedAt = now;
|
|
70
|
+
|
|
71
|
+
const codexGoal = reconciliation.snapshot.raw;
|
|
72
|
+
const blockedEntry: UlwLoopLedgerEntry = { at: now, kind: "goal_review_blocked", goalId: goal.id, status: goal.status, evidence: args.evidence, codexGoal };
|
|
73
|
+
const addedEntry: UlwLoopLedgerEntry = { at: now, kind: "goal_added", goalId: newGoal.id, status: newGoal.status, evidence: args.evidence, message: newGoal.title };
|
|
74
|
+
const summaryEntry: UlwLoopLedgerEntry = { at: now, kind: "goal_review_blocked", goalId: goal.id, status: goal.status, evidence: args.evidence, codexGoal, message: `Review blockers recorded; appended ${newGoal.id}.` };
|
|
75
|
+
Reflect.set(summaryEntry, "kind", "blocker_recorded");
|
|
76
|
+
const ledgerEntries = [blockedEntry, addedEntry, summaryEntry];
|
|
77
|
+
await writePlan(repoRoot, plan, scope);
|
|
78
|
+
for (const entry of ledgerEntries) await appendLedger(repoRoot, entry, scope);
|
|
79
|
+
return { plan, blockedGoal: goal, newGoal, ledgerEntries };
|
|
80
|
+
});
|
|
81
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// biome-ignore-all format: compact steering module must stay below the 240 pure-LOC budget
|
|
2
|
+
import { isUlwLoopDone } from "./goal-status.js";
|
|
3
|
+
import type { UlwLoopScope } from "./paths.js";
|
|
4
|
+
import { seedDefaultSuccessCriteria } from "./plan-crud.js";
|
|
5
|
+
import { appendLedger, readSteeringLedgerEntries, readUlwLoopPlan, withUlwLoopMutationLock, writePlan } from "./plan-io.js";
|
|
6
|
+
import type {
|
|
7
|
+
SteerUlwLoopResult,
|
|
8
|
+
UlwLoopItem,
|
|
9
|
+
UlwLoopLedgerEntry,
|
|
10
|
+
UlwLoopPlan,
|
|
11
|
+
UlwLoopSteeringAudit,
|
|
12
|
+
UlwLoopSteeringChildGoal,
|
|
13
|
+
UlwLoopSteeringMutationKind,
|
|
14
|
+
UlwLoopSteeringProposal,
|
|
15
|
+
UlwLoopSteeringSource,
|
|
16
|
+
UlwLoopSuccessCriterionUserModel,
|
|
17
|
+
} from "./types.js";
|
|
18
|
+
import { iso, ULW_LOOP_STEERING_MUTATION_KINDS, ULW_LOOP_SUCCESS_CRITERION_USER_MODELS } from "./types.js";
|
|
19
|
+
|
|
20
|
+
const SOURCES = ["user_prompt_submit", "finding", "cli"] as const satisfies readonly UlwLoopSteeringSource[];
|
|
21
|
+
const PROTECTED = new Set(["aggregateCompletion", "codexObjective", "codexObjectiveAliases", "originalConstraints", "qualityGate", "status", "completedAt", "completionStatus"]);
|
|
22
|
+
const isObject = (value: unknown): value is object => typeof value === "object" && value !== null; const isPlain = (value: unknown): value is object => isObject(value) && !Array.isArray(value);
|
|
23
|
+
const read = (value: object, key: string): unknown => Object.entries(value).find(([name]) => name === key)?.[1];
|
|
24
|
+
const isText = (value: unknown): value is string => typeof value === "string" && value.trim().length > 0;
|
|
25
|
+
const text = (value: object, key: string): string | undefined => {
|
|
26
|
+
const candidate = read(value, key);
|
|
27
|
+
return isText(candidate) ? candidate.trim() : undefined;
|
|
28
|
+
};
|
|
29
|
+
const isKind = (value: unknown): value is UlwLoopSteeringMutationKind => typeof value === "string" && ULW_LOOP_STEERING_MUTATION_KINDS.some((kind) => kind === value);
|
|
30
|
+
const isSource = (value: unknown): value is UlwLoopSteeringSource => typeof value === "string" && SOURCES.some((source) => source === value);
|
|
31
|
+
const isModel = (value: unknown): value is UlwLoopSuccessCriterionUserModel => typeof value === "string" && ULW_LOOP_SUCCESS_CRITERION_USER_MODELS.some((model) => model === value);
|
|
32
|
+
const texts = (value: object, key: string): string[] => {
|
|
33
|
+
const candidate = read(value, key);
|
|
34
|
+
return Array.isArray(candidate) && candidate.every((item) => typeof item === "string") ? candidate : [];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function targets(proposal: object): string[] {
|
|
38
|
+
const many = texts(proposal, "targetGoalIds");
|
|
39
|
+
const one = text(proposal, "targetGoalId") ?? text(proposal, "goalId");
|
|
40
|
+
return many.length > 0 ? many : one === undefined ? [] : [one];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const after = (proposal: object): object | undefined => {
|
|
44
|
+
const candidate = read(proposal, "after");
|
|
45
|
+
return isPlain(candidate) ? candidate : undefined;
|
|
46
|
+
};
|
|
47
|
+
const revised = (proposal: object, direct: string, nested: string): string | undefined => text(proposal, direct) ?? text(after(proposal) ?? proposal, nested);
|
|
48
|
+
|
|
49
|
+
function child(value: unknown): UlwLoopSteeringChildGoal | null {
|
|
50
|
+
if (!isPlain(value)) return null;
|
|
51
|
+
const title = text(value, "title");
|
|
52
|
+
const objective = text(value, "objective");
|
|
53
|
+
if (title === undefined || objective === undefined) return null;
|
|
54
|
+
return { title, objective };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function childValues(proposal: object): unknown[] {
|
|
58
|
+
const direct = read(proposal, "childGoals");
|
|
59
|
+
if (Array.isArray(direct) && direct.length > 0) return direct;
|
|
60
|
+
const nested = after(proposal);
|
|
61
|
+
const fromAfter = nested === undefined ? undefined : read(nested, "children");
|
|
62
|
+
return Array.isArray(fromAfter) ? fromAfter : [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const children = (proposal: object): UlwLoopSteeringChildGoal[] => childValues(proposal).map(child).filter((item): item is UlwLoopSteeringChildGoal => item !== null);
|
|
66
|
+
const pendingOrder = (proposal: object): string[] => {
|
|
67
|
+
const direct = texts(proposal, "pendingOrder");
|
|
68
|
+
return direct.length > 0 ? direct : texts(after(proposal) ?? proposal, "pendingGoalIds");
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function hasProtected(value: unknown): boolean {
|
|
72
|
+
if (!isObject(value)) return false;
|
|
73
|
+
for (const [key, childValue] of Object.entries(value)) if (PROTECTED.has(key) || key.toLowerCase().includes("complete") || hasProtected(childValue)) return true;
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function allText(value: unknown): string {
|
|
78
|
+
if (typeof value === "string") return value;
|
|
79
|
+
return isObject(value) ? Object.values(value).map(allText).filter(Boolean).join("\n") : "";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function weakens(value: unknown): boolean {
|
|
83
|
+
const valueText = allText(value).toLowerCase();
|
|
84
|
+
return /\b(skip|bypass|weaken|remove|omit|auto[-\s]?complete|mark complete|complete faster)\b/.test(valueText) && /\b(test|tests|verification|review|quality gate|complete|completion)\b/.test(valueText);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function auditFor(proposal: unknown, reasons: string[]): UlwLoopSteeringAudit {
|
|
88
|
+
const object = isPlain(proposal) ? proposal : undefined;
|
|
89
|
+
const kindRaw = object === undefined ? undefined : read(object, "kind");
|
|
90
|
+
const sourceRaw = object === undefined ? undefined : read(object, "source");
|
|
91
|
+
const evidence = object === undefined ? "" : (text(object, "evidence") ?? "");
|
|
92
|
+
const rationale = object === undefined ? "" : (text(object, "rationale") ?? "");
|
|
93
|
+
const audit: UlwLoopSteeringAudit = { kind: isKind(kindRaw) ? kindRaw : "annotate_ledger", source: isSource(sourceRaw) ? sourceRaw : "cli", targetGoalIds: object === undefined ? [] : targets(object), evidence, rationale, invariant: { accepted: reasons.length === 0, structuralInvariantAccepted: reasons.length === 0, evidenceBackedNecessity: evidence.length > 0 && rationale.length > 0, noEasierCompletion: !weakens(proposal), rejectedReasons: reasons, reasons } };
|
|
94
|
+
if (object === undefined) return audit;
|
|
95
|
+
const criterionId = text(object, "criterionId");
|
|
96
|
+
const directiveText = text(object, "directiveText");
|
|
97
|
+
const promptSignature = text(object, "promptSignature");
|
|
98
|
+
const idempotencyKey = text(object, "idempotencyKey");
|
|
99
|
+
if (criterionId !== undefined) audit.criterionId = criterionId;
|
|
100
|
+
if (directiveText !== undefined) audit.directiveText = directiveText;
|
|
101
|
+
if (promptSignature !== undefined) audit.promptSignature = promptSignature;
|
|
102
|
+
if (idempotencyKey !== undefined) audit.idempotencyKey = idempotencyKey;
|
|
103
|
+
return audit;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function validateUlwLoopSteeringProposal(plan: UlwLoopPlan, proposal: unknown): UlwLoopSteeringAudit {
|
|
107
|
+
const reasons: string[] = [];
|
|
108
|
+
if (!isPlain(proposal)) reasons.push("proposal must be an object");
|
|
109
|
+
const object = isPlain(proposal) ? proposal : {};
|
|
110
|
+
const kind = read(object, "kind");
|
|
111
|
+
if (!isKind(kind)) reasons.push(`invalid kind: ${String(kind)}`);
|
|
112
|
+
if (!isSource(read(object, "source"))) reasons.push(`invalid source: ${String(read(object, "source"))}`);
|
|
113
|
+
if (text(object, "evidence") === undefined) reasons.push("missing evidence");
|
|
114
|
+
if (text(object, "rationale") === undefined) reasons.push("missing rationale");
|
|
115
|
+
if (hasProtected(proposal)) reasons.push("protected payload");
|
|
116
|
+
if (weakens(proposal)) reasons.push("weakened completion");
|
|
117
|
+
if (isUlwLoopDone(plan)) reasons.push("plan already complete");
|
|
118
|
+
if (isKind(kind)) validateKind(plan, object, kind, reasons);
|
|
119
|
+
return auditFor(proposal, reasons);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function goal(plan: UlwLoopPlan, id: string | undefined): UlwLoopItem | undefined {
|
|
123
|
+
return id === undefined ? undefined : plan.goals.find((item) => item.id === id);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function validateKind(plan: UlwLoopPlan, proposal: object, kind: UlwLoopSteeringMutationKind, reasons: string[]): void {
|
|
127
|
+
const target = goal(plan, targets(proposal)[0]);
|
|
128
|
+
if (kind === "add_subgoal" && (text(proposal, "title") === undefined || text(proposal, "objective") === undefined)) reasons.push("add_subgoal requires title/objective");
|
|
129
|
+
if ((kind === "split_subgoal" || kind === "revise_pending_wording" || kind === "mark_blocked_superseded") && target === undefined) reasons.push(`${kind} requires target`);
|
|
130
|
+
if ((kind === "split_subgoal" || kind === "revise_pending_wording") && target !== undefined && target.status !== "pending") reasons.push(`${kind} requires pending target`);
|
|
131
|
+
const rawChildren = childValues(proposal);
|
|
132
|
+
if (kind === "split_subgoal" && rawChildren.length === 0) reasons.push("split_subgoal requires children");
|
|
133
|
+
if ((kind === "split_subgoal" || kind === "mark_blocked_superseded") && rawChildren.some((item) => child(item) === null)) reasons.push(`${kind} children require title/objective`);
|
|
134
|
+
if (kind === "reorder_pending") validateOrder(plan, proposal, reasons);
|
|
135
|
+
if (kind === "revise_pending_wording" && revised(proposal, "revisedTitle", "title") === undefined && revised(proposal, "revisedObjective", "objective") === undefined) reasons.push("revise_pending_wording requires update");
|
|
136
|
+
if (kind === "revise_criterion") validateCriterion(plan, proposal, reasons);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function validateOrder(plan: UlwLoopPlan, proposal: object, reasons: string[]): void {
|
|
140
|
+
const requested = pendingOrder(proposal);
|
|
141
|
+
const pending = plan.goals.filter((item) => item.status === "pending" && item.steeringStatus === undefined).map((item) => item.id);
|
|
142
|
+
if (requested.length === 0) reasons.push("reorder_pending requires ids");
|
|
143
|
+
if (new Set(requested).size !== requested.length) reasons.push("duplicate pending id");
|
|
144
|
+
if (requested.some((id) => !pending.includes(id))) reasons.push("unknown pending id");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function validateCriterion(plan: UlwLoopPlan, proposal: object, reasons: string[]): void {
|
|
148
|
+
const target = goal(plan, targets(proposal)[0]);
|
|
149
|
+
const criterionId = text(proposal, "criterionId");
|
|
150
|
+
if (target === undefined) reasons.push("revise_criterion requires goalId");
|
|
151
|
+
else if (criterionId === undefined || target.successCriteria.every((item) => item.id !== criterionId)) reasons.push("revise_criterion requires criterionId");
|
|
152
|
+
const model = read(proposal, "userModel");
|
|
153
|
+
if (read(proposal, "scenario") === undefined && read(proposal, "expectedEvidence") === undefined && model === undefined) reasons.push("revise_criterion requires update");
|
|
154
|
+
if (model !== undefined && !isModel(model)) reasons.push("invalid userModel");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function nextId(plan: UlwLoopPlan, offset: number): string {
|
|
158
|
+
const max = plan.goals.reduce((current, item) => {
|
|
159
|
+
const digits = /^G(\d+)(?:-|$)/u.exec(item.id)?.[1];
|
|
160
|
+
return digits === undefined ? current : Math.max(current, Number(digits));
|
|
161
|
+
}, 0);
|
|
162
|
+
return `G${String(max + offset).padStart(3, "0")}`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function makeGoal(plan: UlwLoopPlan, childGoal: UlwLoopSteeringChildGoal, evidence: string, now: string, offset: number): UlwLoopItem {
|
|
166
|
+
const id = nextId(plan, offset);
|
|
167
|
+
const digits = /^G(\d+)/u.exec(id)?.[1];
|
|
168
|
+
const goalIndex = digits === undefined ? plan.goals.length + offset - 1 : Number(digits) - 1;
|
|
169
|
+
return { id, title: childGoal.title, objective: childGoal.objective, status: "pending", successCriteria: seedDefaultSuccessCriteria(goalIndex, childGoal.objective), attempt: 0, createdAt: now, updatedAt: now, evidence };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function applySteeringMutation(plan: UlwLoopPlan, proposal: UlwLoopSteeringProposal, audit: UlwLoopSteeringAudit): UlwLoopPlan {
|
|
173
|
+
const next = structuredClone(plan);
|
|
174
|
+
if (!audit.invariant.accepted) return next;
|
|
175
|
+
const now = proposal.now?.toISOString() ?? iso();
|
|
176
|
+
if (proposal.kind === "add_subgoal") next.goals.push(makeGoal(next, { title: proposal.title ?? "", objective: proposal.objective ?? "" }, proposal.evidence, now, 1));
|
|
177
|
+
if (proposal.kind === "reorder_pending") {
|
|
178
|
+
const order = pendingOrder(proposal);
|
|
179
|
+
next.goals = [...order.map((id) => goal(next, id)).filter((item): item is UlwLoopItem => item !== undefined), ...next.goals.filter((item) => !order.includes(item.id))];
|
|
180
|
+
}
|
|
181
|
+
if (proposal.kind === "revise_pending_wording") reviseWording(next, proposal, now);
|
|
182
|
+
if (proposal.kind === "split_subgoal" || proposal.kind === "mark_blocked_superseded") splitOrBlock(next, proposal, now);
|
|
183
|
+
if (proposal.kind === "revise_criterion") reviseCriterion(next, proposal, now);
|
|
184
|
+
if (proposal.kind !== "annotate_ledger") next.updatedAt = now;
|
|
185
|
+
return next;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function reviseWording(plan: UlwLoopPlan, proposal: UlwLoopSteeringProposal, now: string): void {
|
|
189
|
+
const target = goal(plan, targets(proposal)[0]);
|
|
190
|
+
if (target === undefined) return;
|
|
191
|
+
target.title = revised(proposal, "revisedTitle", "title") ?? target.title;
|
|
192
|
+
target.objective = revised(proposal, "revisedObjective", "objective") ?? target.objective;
|
|
193
|
+
target.steeringEvidence = proposal.evidence;
|
|
194
|
+
target.steeringRationale = proposal.rationale;
|
|
195
|
+
target.updatedAt = now;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function splitOrBlock(plan: UlwLoopPlan, proposal: UlwLoopSteeringProposal, now: string): void {
|
|
199
|
+
const target = goal(plan, targets(proposal)[0]);
|
|
200
|
+
if (target === undefined) return;
|
|
201
|
+
const replacements = children(proposal).map((item, index) => makeGoal(plan, item, proposal.evidence, now, index + 1));
|
|
202
|
+
target.steeringEvidence = proposal.evidence;
|
|
203
|
+
target.steeringRationale = proposal.rationale;
|
|
204
|
+
target.updatedAt = now;
|
|
205
|
+
if (replacements.length === 0) {
|
|
206
|
+
target.status = "blocked";
|
|
207
|
+
target.steeringStatus = "blocked";
|
|
208
|
+
target.blockedReason = proposal.blockedReason ?? proposal.rationale;
|
|
209
|
+
} else {
|
|
210
|
+
target.steeringStatus = "superseded";
|
|
211
|
+
target.supersededBy = replacements.map((item) => item.id);
|
|
212
|
+
for (const item of replacements) item.supersedes = [target.id];
|
|
213
|
+
plan.goals.splice(plan.goals.indexOf(target) + 1, 0, ...replacements);
|
|
214
|
+
}
|
|
215
|
+
if (plan.activeGoalId === target.id) delete plan.activeGoalId;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function reviseCriterion(plan: UlwLoopPlan, proposal: UlwLoopSteeringProposal, now: string): void {
|
|
219
|
+
const target = goal(plan, targets(proposal)[0]);
|
|
220
|
+
const index = target?.successCriteria.findIndex((item) => item.id === proposal.criterionId) ?? -1;
|
|
221
|
+
const current = target?.successCriteria[index];
|
|
222
|
+
if (target === undefined || current === undefined) return;
|
|
223
|
+
const model = read(proposal, "userModel");
|
|
224
|
+
target.successCriteria[index] = { ...current, scenario: text(proposal, "scenario") ?? current.scenario, expectedEvidence: text(proposal, "expectedEvidence") ?? current.expectedEvidence, userModel: isModel(model) ? model : current.userModel };
|
|
225
|
+
target.updatedAt = now;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function isProposal(value: unknown): value is UlwLoopSteeringProposal {
|
|
229
|
+
return isPlain(value) && isKind(read(value, "kind")) && isSource(read(value, "source")) && isText(read(value, "evidence")) && isText(read(value, "rationale"));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export function parseUlwLoopSteeringDirective(text: string): UlwLoopSteeringProposal | null {
|
|
233
|
+
const match = /(?:^|\s)(?:OMO_ULW_LOOP_STEER|omo\.ulw-loop\.steer|omo ulw-loop steer):\s*([\s\S]+)$/u.exec(text);
|
|
234
|
+
if (match?.[1] === undefined) return null;
|
|
235
|
+
try {
|
|
236
|
+
const parsed: unknown = JSON.parse(match[1].trim());
|
|
237
|
+
return isProposal(parsed) ? parsed : null;
|
|
238
|
+
} catch (error) {
|
|
239
|
+
if (error instanceof SyntaxError) return null;
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export async function steerUlwLoop(repoRoot: string, proposal: UlwLoopSteeringProposal, scope?: UlwLoopScope): Promise<SteerUlwLoopResult> {
|
|
245
|
+
return withUlwLoopMutationLock(repoRoot, scope, async () => {
|
|
246
|
+
const plan = await readUlwLoopPlan(repoRoot, scope);
|
|
247
|
+
const key = proposal.idempotencyKey ?? proposal.promptSignature;
|
|
248
|
+
const prior = key === undefined ? undefined : (await readSteeringLedgerEntries(repoRoot, scope)).find((entry) => entry.steering?.invariant.accepted === true && (entry.idempotencyKey === key || entry.steering.idempotencyKey === key || entry.steering.promptSignature === key));
|
|
249
|
+
if (prior?.steering !== undefined) return { plan, accepted: true, audit: { ...prior.steering, deduped: true }, rejectedReasons: [], deduped: true };
|
|
250
|
+
const audit = validateUlwLoopSteeringProposal(plan, proposal);
|
|
251
|
+
const accepted = audit.invariant.accepted;
|
|
252
|
+
const next = accepted ? applySteeringMutation(plan, proposal, audit) : plan;
|
|
253
|
+
const finalAudit: UlwLoopSteeringAudit = { ...audit, before: plan };
|
|
254
|
+
if (accepted) finalAudit.after = next;
|
|
255
|
+
if (accepted) await writePlan(repoRoot, next, scope);
|
|
256
|
+
await appendLedger(repoRoot, ledgerEntry(proposal, finalAudit, proposal.now?.toISOString() ?? iso()), scope);
|
|
257
|
+
return { plan: next, accepted, audit: finalAudit, rejectedReasons: audit.invariant.rejectedReasons, deduped: false };
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function ledgerEntry(proposal: UlwLoopSteeringProposal, audit: UlwLoopSteeringAudit, at: string): UlwLoopLedgerEntry {
|
|
262
|
+
const entry: UlwLoopLedgerEntry = { at, kind: audit.invariant.accepted ? (proposal.kind === "revise_criterion" ? "criteria_revised" : "steering_accepted") : "steering_rejected", evidence: proposal.evidence, message: proposal.rationale, steering: audit, mutationKind: proposal.kind };
|
|
263
|
+
const goalId = audit.targetGoalIds[0];
|
|
264
|
+
if (goalId !== undefined) entry.goalId = goalId;
|
|
265
|
+
if (proposal.criterionId !== undefined) entry.criterionId = proposal.criterionId;
|
|
266
|
+
if (proposal.idempotencyKey !== undefined) entry.idempotencyKey = proposal.idempotencyKey;
|
|
267
|
+
if (audit.before !== undefined) entry.before = audit.before;
|
|
268
|
+
if (audit.after !== undefined) entry.after = audit.after;
|
|
269
|
+
return entry;
|
|
270
|
+
}
|