oh-my-opencode 4.16.2 → 4.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/command/omomomo.md +1 -1
- package/.agents/skills/hyperplan/SKILL.md +3 -3
- package/.agents/skills/omomomo/SKILL.md +1 -1
- package/.agents/skills/pre-publish-review/SKILL.md +3 -0
- package/.opencode/command/omomomo.md +1 -1
- package/.opencode/skills/hyperplan/SKILL.md +3 -3
- package/.opencode/skills/pre-publish-review/SKILL.md +3 -0
- package/README.ja.md +4 -4
- package/README.ko.md +4 -4
- package/README.md +4 -4
- package/README.ru.md +4 -4
- package/README.zh-cn.md +4 -4
- package/dist/agents/hephaestus/agent.d.ts +1 -1
- package/dist/agents/hephaestus/gpt-5-6.d.ts +2 -0
- package/dist/agents/momus-gpt-5-6.d.ts +1 -0
- package/dist/agents/types.d.ts +2 -0
- package/dist/cli/index.js +947 -567
- package/dist/cli-node/index.js +947 -567
- package/dist/features/background-agent/error-classifier.d.ts +5 -0
- package/dist/features/builtin-commands/templates/refactor-sections/intro-and-analysis.d.ts +1 -1
- package/dist/features/builtin-commands/templates/remove-ai-slops.d.ts +1 -1
- package/dist/features/team-mode/test-support/async-test-helpers.d.ts +2 -2
- package/dist/index.js +523 -81
- package/dist/plugin/chat-message/types.d.ts +4 -0
- package/dist/plugin/command-execute-before.d.ts +1 -0
- package/dist/plugin/stop-continuation.d.ts +17 -0
- package/dist/shared/live-server-route.d.ts +1 -1
- package/dist/skills/remove-ai-slops/SKILL.md +2 -2
- package/dist/skills/review-work/SKILL.md +1 -1
- package/dist/skills/start-work/SKILL.md +5 -2
- package/dist/skills/ulw-plan/references/full-workflow.md +1 -1
- package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +2 -2
- package/dist/skills/ulw-research/SKILL.md +2 -2
- package/dist/skills/visual-qa/SKILL.md +1 -1
- package/dist/tui.js +195 -41
- package/package.json +15 -14
- package/packages/git-bash-mcp/package.json +27 -0
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +3 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +465 -248
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/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/AGENTS.md +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +6 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +6 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +6 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/cli.test.ts +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +67 -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/lsp/test/package-smoke.test.ts +0 -13
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.6.md +93 -0
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +43 -24
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/src/codex-hook.ts +2 -1
- package/packages/omo-codex/plugin/components/rules/src/dynamic-target-fingerprints.ts +15 -6
- package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +7 -2
- package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +2 -2
- package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +32 -0
- package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +106 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +1 -79
- package/packages/omo-codex/plugin/components/teammode/AGENTS.md +12 -9
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +136 -76
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-guide.mjs +94 -23
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-state.mjs +94 -14
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-transport.mjs +55 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +72 -18
- package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +23 -0
- 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/explorer.toml +23 -40
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +7 -7
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +5 -5
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +26 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/{lazycodex-executor.toml → lazycodex-worker-low.toml} +7 -5
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +26 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +20 -48
- package/packages/omo-codex/plugin/components/ultrawork/agents/metis.toml +17 -29
- package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +20 -50
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +22 -43
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +55 -28
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +55 -28
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +22 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +0 -68
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +55 -28
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +405 -25
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +12 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +16 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +20 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +12 -9
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.d.ts +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +148 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.d.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +209 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +25 -2
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +14 -15
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +29 -27
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +14 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +10 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +12 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +27 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +23 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +16 -9
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +138 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +208 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +12 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +4 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +8 -35
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +24 -13
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +43 -8
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +55 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +228 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +193 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +18 -0
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +17 -0
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +2 -2
- 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/model-catalog.json +16 -7
- package/packages/omo-codex/plugin/package-lock.json +13 -13
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +9 -2
- package/packages/omo-codex/plugin/scripts/entry-guard.mjs +26 -0
- package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +3 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +16 -7
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +39 -4
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +24 -4
- package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +3 -3
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +2 -2
- package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +2 -2
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +14 -6
- package/packages/omo-codex/plugin/scripts/sync-version.mjs +4 -2
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +3 -3
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +3 -3
- package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +5 -5
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +9 -3
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +6 -3
- package/packages/omo-codex/plugin/skills/teammode/SKILL.md +136 -76
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-guide.mjs +94 -23
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-state.mjs +94 -14
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-transport.mjs +55 -0
- package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +72 -18
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +55 -28
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +14 -15
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +29 -27
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -4
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +4 -4
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +116 -10
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +23 -2
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +4 -4
- package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +4 -2
- package/packages/omo-codex/plugin/test/auto-update-restart-notice.test.mjs +33 -0
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +4 -4
- package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
- package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +4 -101
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +160 -23
- package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +71 -0
- package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +32 -0
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +20 -2
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +1 -1
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +4 -2
- package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +345 -0
- package/packages/omo-codex/plugin/test/ulw-plan-skill-contract.test.mjs +9 -40
- package/packages/omo-codex/plugin/test/ulw-research-skill-contract.test.mjs +4 -277
- package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +5 -5
- package/packages/omo-codex/scripts/install-config.test.mjs +22 -3
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +508 -286
- package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +111 -1
- package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +2 -2
- package/packages/shared-skills/skills/review-work/SKILL.md +1 -1
- package/packages/shared-skills/skills/start-work/SKILL.md +5 -2
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +2 -2
- package/packages/shared-skills/skills/ulw-research/SKILL.md +2 -2
- package/packages/shared-skills/skills/visual-qa/SKILL.md +1 -1
- package/dist/skills/visual-qa/scripts/skill-prompt-contract.test.ts +0 -296
- package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +0 -70
- package/packages/omo-codex/plugin/test/ulw-research-epistemic-contract.test.mjs +0 -98
- package/packages/shared-skills/skills/visual-qa/scripts/skill-prompt-contract.test.ts +0 -296
- /package/packages/omo-codex/plugin/components/rules/bundled-rules/{hephaestus.md → hephaestus/gpt-5.5.md} +0 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
|
|
6
|
+
import { root } from "./aggregate-plugin-fixture.mjs";
|
|
7
|
+
import {
|
|
8
|
+
cleanupTeamRoot,
|
|
9
|
+
createTeamRoot,
|
|
10
|
+
readTeamJson,
|
|
11
|
+
runTeam,
|
|
12
|
+
runTeamRaw,
|
|
13
|
+
teamDir,
|
|
14
|
+
teamJsonPath,
|
|
15
|
+
} from "./teammode-safety-fixture.mjs";
|
|
16
|
+
|
|
17
|
+
function addV2Members(tempRoot, sessionId) {
|
|
18
|
+
runTeam(
|
|
19
|
+
tempRoot,
|
|
20
|
+
"add-member",
|
|
21
|
+
"--team",
|
|
22
|
+
sessionId,
|
|
23
|
+
"--id",
|
|
24
|
+
"A",
|
|
25
|
+
"--name",
|
|
26
|
+
"runtime-core",
|
|
27
|
+
"--task-name",
|
|
28
|
+
"runtime_core",
|
|
29
|
+
"--focus",
|
|
30
|
+
"runtime state and binding",
|
|
31
|
+
"--lens",
|
|
32
|
+
"ownership",
|
|
33
|
+
"--deliverable",
|
|
34
|
+
"runtime contract",
|
|
35
|
+
);
|
|
36
|
+
runTeam(
|
|
37
|
+
tempRoot,
|
|
38
|
+
"add-member",
|
|
39
|
+
"--team",
|
|
40
|
+
sessionId,
|
|
41
|
+
"--id",
|
|
42
|
+
"B",
|
|
43
|
+
"--name",
|
|
44
|
+
"mailbox-delivery",
|
|
45
|
+
"--task-name",
|
|
46
|
+
"mailbox_delivery",
|
|
47
|
+
"--focus",
|
|
48
|
+
"cross-agent message delivery",
|
|
49
|
+
"--lens",
|
|
50
|
+
"area",
|
|
51
|
+
"--deliverable",
|
|
52
|
+
"delivery evidence",
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
test("#given flat V2 tools are available #when the leader reads teammode #then transport selection and user announcement precede init", () => {
|
|
57
|
+
const skill = readFileSync(join(root, "components", "teammode", "skills", "teammode", "SKILL.md"), "utf8");
|
|
58
|
+
const inspectIndex = skill.indexOf("Inspect your active tool list");
|
|
59
|
+
const initIndex = skill.indexOf('team.mjs" init');
|
|
60
|
+
|
|
61
|
+
assert.notEqual(inspectIndex, -1, "skill must inspect the active tool list");
|
|
62
|
+
assert.notEqual(initIndex, -1, "skill must still document init");
|
|
63
|
+
assert.ok(inspectIndex < initIndex, "transport inspection must happen before init");
|
|
64
|
+
assert.match(skill, /spawn_agent.*task_name[\s\S]*send_message[\s\S]*followup_task[\s\S]*wait_agent[\s\S]*list_agents[\s\S]*interrupt_agent/);
|
|
65
|
+
assert.match(skill, /tell the user|announce.*transport/i);
|
|
66
|
+
assert.match(skill, /MultiAgentV2/i);
|
|
67
|
+
assert.match(skill, /Codex App.*fallback/i);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("#given MultiAgentV2 transport #when members are added and bound #then task names and canonical agent paths form the address book", () => {
|
|
71
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-v2-transport-");
|
|
72
|
+
try {
|
|
73
|
+
const sessionId = "v2-transport";
|
|
74
|
+
runTeam(tempRoot, "init", "--name", "Native", "--session-name", "agents", "--session", sessionId, "--transport", "multi_agent_v2");
|
|
75
|
+
addV2Members(tempRoot, sessionId);
|
|
76
|
+
runTeam(tempRoot, "bind-agent", "--team", sessionId, "--id", "A", "--agent-path", "/root/runtime_core");
|
|
77
|
+
runTeam(tempRoot, "bind-agent", "--team", sessionId, "--id", "B", "--agent-path", "/root/mailbox_delivery");
|
|
78
|
+
|
|
79
|
+
const team = readTeamJson(tempRoot, sessionId);
|
|
80
|
+
const guide = readFileSync(join(teamDir(tempRoot, sessionId), "guide.md"), "utf8");
|
|
81
|
+
const status = runTeam(tempRoot, "status", "--team", sessionId).stdout;
|
|
82
|
+
const prompt = runTeam(tempRoot, "member-prompt", "--team", sessionId, "--id", "A").stdout;
|
|
83
|
+
|
|
84
|
+
assert.equal(team.schemaVersion, 3);
|
|
85
|
+
assert.equal(team.transport, "multi_agent_v2");
|
|
86
|
+
assert.deepEqual(team.leader, { kind: "main-session", sessionId: null, agentPath: "/root" });
|
|
87
|
+
assert.deepEqual(
|
|
88
|
+
team.members.map((member) => ({
|
|
89
|
+
id: member.id,
|
|
90
|
+
taskName: member.taskName,
|
|
91
|
+
agentPath: member.agentPath,
|
|
92
|
+
threadId: member.threadId,
|
|
93
|
+
threadTitle: member.threadTitle,
|
|
94
|
+
status: member.status,
|
|
95
|
+
})),
|
|
96
|
+
[
|
|
97
|
+
{ id: "A", taskName: "runtime_core", agentPath: "/root/runtime_core", threadId: null, threadTitle: null, status: "active" },
|
|
98
|
+
{ id: "B", taskName: "mailbox_delivery", agentPath: "/root/mailbox_delivery", threadId: null, threadTitle: null, status: "active" },
|
|
99
|
+
],
|
|
100
|
+
);
|
|
101
|
+
assert.match(guide, /Transport:.*MultiAgentV2/i);
|
|
102
|
+
assert.match(guide, /members\[\]\.agentPath/);
|
|
103
|
+
assert.match(guide, /send_message/);
|
|
104
|
+
assert.match(guide, /followup_task/);
|
|
105
|
+
assert.doesNotMatch(guide, /codex_app\.send_message_to_thread/);
|
|
106
|
+
assert.doesNotMatch(guide, /codex:\/\/threads\//);
|
|
107
|
+
assert.match(status, /transport=multi_agent_v2/);
|
|
108
|
+
assert.match(status, /agent=\/root\/runtime_core/);
|
|
109
|
+
assert.match(prompt, /target `\/root`/);
|
|
110
|
+
assert.match(prompt, /send_message/);
|
|
111
|
+
assert.doesNotMatch(prompt, /thread title|codex:\/\/threads\//i);
|
|
112
|
+
} finally {
|
|
113
|
+
cleanupTeamRoot(tempRoot);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("#given codex_app transport #when members bind threads #then the existing thread address book and deep links remain", () => {
|
|
118
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-app-transport-");
|
|
119
|
+
try {
|
|
120
|
+
const sessionId = "app-transport";
|
|
121
|
+
runTeam(tempRoot, "init", "--name", "Fallback", "--session-name", "threads", "--session", sessionId, "--transport", "codex_app");
|
|
122
|
+
runTeam(tempRoot, "add-member", "--team", sessionId, "--id", "A", "--name", "alpha", "--focus", "alpha scope", "--lens", "area", "--deliverable", "alpha result");
|
|
123
|
+
runTeam(tempRoot, "add-member", "--team", sessionId, "--id", "B", "--name", "beta", "--focus", "beta scope", "--lens", "ownership", "--deliverable", "beta result");
|
|
124
|
+
runTeam(tempRoot, "bind-thread", "--team", sessionId, "--id", "A", "--thread", "thread-A");
|
|
125
|
+
runTeam(tempRoot, "bind-thread", "--team", sessionId, "--id", "B", "--thread", "thread-B");
|
|
126
|
+
|
|
127
|
+
const team = readTeamJson(tempRoot, sessionId);
|
|
128
|
+
const guide = readFileSync(join(teamDir(tempRoot, sessionId), "guide.md"), "utf8");
|
|
129
|
+
const status = runTeam(tempRoot, "status", "--team", sessionId).stdout;
|
|
130
|
+
|
|
131
|
+
assert.equal(team.schemaVersion, 3);
|
|
132
|
+
assert.equal(team.transport, "codex_app");
|
|
133
|
+
assert.equal(team.leader.sessionId, sessionId);
|
|
134
|
+
assert.equal(team.leader.agentPath, null);
|
|
135
|
+
assert.match(guide, /codex_app\.send_message_to_thread/);
|
|
136
|
+
assert.match(guide, /members\[\]\.threadId/);
|
|
137
|
+
assert.match(guide, /codex:\/\/threads\/thread-A/);
|
|
138
|
+
assert.match(status, /transport=codex_app/);
|
|
139
|
+
assert.match(status, /thread=thread-A/);
|
|
140
|
+
} finally {
|
|
141
|
+
cleanupTeamRoot(tempRoot);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("#given an unsupported transport #when init runs #then it fails before creating team state", () => {
|
|
146
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-invalid-transport-");
|
|
147
|
+
try {
|
|
148
|
+
const result = runTeamRaw(tempRoot, "init", "--name", "Invalid", "--session-name", "transport", "--session", "invalid-transport", "--transport", "other");
|
|
149
|
+
|
|
150
|
+
assert.notEqual(result.status, 0);
|
|
151
|
+
assert.match(result.stderr, /invalid transport.*multi_agent_v2.*codex_app/i);
|
|
152
|
+
assert.equal(existsSync(teamDir(tempRoot, "invalid-transport")), false);
|
|
153
|
+
} finally {
|
|
154
|
+
cleanupTeamRoot(tempRoot);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("#given --transport without a value #when init runs #then it fails before creating team state", () => {
|
|
159
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-valueless-transport-");
|
|
160
|
+
try {
|
|
161
|
+
const result = runTeamRaw(tempRoot, "init", "--name", "Valueless", "--session-name", "transport", "--session", "valueless-transport", "--transport");
|
|
162
|
+
|
|
163
|
+
assert.notEqual(result.status, 0, "a valueless --transport must never silently default");
|
|
164
|
+
assert.match(result.stderr, /invalid transport.*multi_agent_v2.*codex_app/i);
|
|
165
|
+
assert.equal(existsSync(teamDir(tempRoot, "valueless-transport")), false);
|
|
166
|
+
} finally {
|
|
167
|
+
cleanupTeamRoot(tempRoot);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test("#given an existing team #when init re-runs with a conflicting transport #then it fails and state is unchanged", () => {
|
|
172
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-reinit-transport-");
|
|
173
|
+
try {
|
|
174
|
+
runTeam(tempRoot, "init", "--name", "Fallback", "--session-name", "threads", "--session", "reinit", "--transport", "codex_app");
|
|
175
|
+
const before = readFileSync(teamJsonPath(tempRoot, "reinit"), "utf8");
|
|
176
|
+
|
|
177
|
+
const conflict = runTeamRaw(tempRoot, "init", "--name", "Fallback", "--session-name", "threads", "--session", "reinit", "--transport", "multi_agent_v2");
|
|
178
|
+
assert.notEqual(conflict.status, 0, "re-init must not silently accept a conflicting transport");
|
|
179
|
+
assert.match(conflict.stderr, /transport.*immutable|already exists with transport/i);
|
|
180
|
+
assert.equal(readFileSync(teamJsonPath(tempRoot, "reinit"), "utf8"), before);
|
|
181
|
+
|
|
182
|
+
const sameTransport = runTeam(tempRoot, "init", "--name", "Fallback", "--session-name", "threads", "--session", "reinit", "--transport", "codex_app");
|
|
183
|
+
assert.match(sameTransport.stdout, /exists:.*transport: codex_app/);
|
|
184
|
+
assert.equal(readFileSync(teamJsonPath(tempRoot, "reinit"), "utf8"), before);
|
|
185
|
+
} finally {
|
|
186
|
+
cleanupTeamRoot(tempRoot);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test("#given a V2 team #when the whole team is archived without a note #then no output claims runtime members were closed", () => {
|
|
191
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-v2-archive-");
|
|
192
|
+
try {
|
|
193
|
+
runTeam(tempRoot, "init", "--name", "Native", "--session-name", "agents", "--session", "v2-archive", "--transport", "multi_agent_v2");
|
|
194
|
+
addV2Members(tempRoot, "v2-archive");
|
|
195
|
+
|
|
196
|
+
const result = runTeam(tempRoot, "archive", "--team", "v2-archive");
|
|
197
|
+
const team = readTeamJson(tempRoot, "v2-archive");
|
|
198
|
+
const archiveEntry = team.log.find((entry) => entry.event === "archive");
|
|
199
|
+
|
|
200
|
+
assert.equal(team.status, "archived");
|
|
201
|
+
assert.doesNotMatch(result.stdout, /closed all members/i, "V2 has no runtime close/archive operation to claim");
|
|
202
|
+
assert.match(result.stdout, /no runtime archive operation/i);
|
|
203
|
+
assert.doesNotMatch(archiveEntry.detail, /all members closed/i);
|
|
204
|
+
assert.match(archiveEntry.detail, /no runtime archive operation/i);
|
|
205
|
+
} finally {
|
|
206
|
+
cleanupTeamRoot(tempRoot);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test("#given a V2 team #when one member is archived #then output scopes the archive to team state, not the runtime agent", () => {
|
|
211
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-v2-archive-member-");
|
|
212
|
+
try {
|
|
213
|
+
runTeam(tempRoot, "init", "--name", "Native", "--session-name", "agents", "--session", "v2-archive-member", "--transport", "multi_agent_v2");
|
|
214
|
+
addV2Members(tempRoot, "v2-archive-member");
|
|
215
|
+
|
|
216
|
+
const result = runTeam(tempRoot, "archive", "--team", "v2-archive-member", "--id", "A");
|
|
217
|
+
const team = readTeamJson(tempRoot, "v2-archive-member");
|
|
218
|
+
const entry = team.log.find((logEntry) => logEntry.event === "archive-member");
|
|
219
|
+
|
|
220
|
+
assert.equal(team.members.find((member) => member.id === "A").status, "archived");
|
|
221
|
+
assert.match(result.stdout, /team state/i, "V2 per-member archive must scope the claim to team state");
|
|
222
|
+
assert.match(result.stdout, /no runtime archive operation/i);
|
|
223
|
+
assert.match(entry.detail, /no runtime archive operation/i);
|
|
224
|
+
} finally {
|
|
225
|
+
cleanupTeamRoot(tempRoot);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test("#given a codex_app team #when one member is archived #then the existing wording is preserved", () => {
|
|
230
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-app-archive-member-");
|
|
231
|
+
try {
|
|
232
|
+
runTeam(tempRoot, "init", "--name", "Fallback", "--session-name", "threads", "--session", "app-archive-member", "--transport", "codex_app");
|
|
233
|
+
runTeam(tempRoot, "add-member", "--team", "app-archive-member", "--id", "A", "--name", "alpha", "--focus", "alpha scope", "--lens", "area", "--deliverable", "a");
|
|
234
|
+
runTeam(tempRoot, "add-member", "--team", "app-archive-member", "--id", "B", "--name", "beta", "--focus", "beta scope", "--lens", "ownership", "--deliverable", "b");
|
|
235
|
+
|
|
236
|
+
const result = runTeam(tempRoot, "archive", "--team", "app-archive-member", "--id", "A");
|
|
237
|
+
|
|
238
|
+
assert.match(result.stdout, /archived member A/);
|
|
239
|
+
assert.doesNotMatch(result.stdout, /no runtime archive operation/i);
|
|
240
|
+
} finally {
|
|
241
|
+
cleanupTeamRoot(tempRoot);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test("#given a transport-specific team #when the wrong bind command runs #then it fails without changing team.json", () => {
|
|
246
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-cross-bind-");
|
|
247
|
+
try {
|
|
248
|
+
runTeam(tempRoot, "init", "--name", "Native", "--session-name", "agents", "--session", "cross-v2", "--transport", "multi_agent_v2");
|
|
249
|
+
addV2Members(tempRoot, "cross-v2");
|
|
250
|
+
const v2Before = readFileSync(teamJsonPath(tempRoot, "cross-v2"), "utf8");
|
|
251
|
+
const threadResult = runTeamRaw(tempRoot, "bind-thread", "--team", "cross-v2", "--id", "A", "--thread", "thread-A");
|
|
252
|
+
assert.notEqual(threadResult.status, 0);
|
|
253
|
+
assert.match(threadResult.stderr, /bind-thread.*codex_app/i);
|
|
254
|
+
assert.equal(readFileSync(teamJsonPath(tempRoot, "cross-v2"), "utf8"), v2Before);
|
|
255
|
+
|
|
256
|
+
runTeam(tempRoot, "init", "--name", "Fallback", "--session-name", "threads", "--session", "cross-app", "--transport", "codex_app");
|
|
257
|
+
runTeam(tempRoot, "add-member", "--team", "cross-app", "--id", "A", "--name", "alpha", "--focus", "alpha scope", "--lens", "area", "--deliverable", "alpha result");
|
|
258
|
+
runTeam(tempRoot, "add-member", "--team", "cross-app", "--id", "B", "--name", "beta", "--focus", "beta scope", "--lens", "ownership", "--deliverable", "beta result");
|
|
259
|
+
const appBefore = readFileSync(teamJsonPath(tempRoot, "cross-app"), "utf8");
|
|
260
|
+
const agentResult = runTeamRaw(tempRoot, "bind-agent", "--team", "cross-app", "--id", "A", "--agent-path", "/root/alpha");
|
|
261
|
+
assert.notEqual(agentResult.status, 0);
|
|
262
|
+
assert.match(agentResult.stderr, /bind-agent.*multi_agent_v2/i);
|
|
263
|
+
assert.equal(readFileSync(teamJsonPath(tempRoot, "cross-app"), "utf8"), appBefore);
|
|
264
|
+
} finally {
|
|
265
|
+
cleanupTeamRoot(tempRoot);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
test("#given V2 expected task identity #when bind-agent receives another path #then it fails without activating the member", () => {
|
|
270
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-agent-path-");
|
|
271
|
+
try {
|
|
272
|
+
runTeam(tempRoot, "init", "--name", "Native", "--session-name", "agents", "--session", "agent-path", "--transport", "multi_agent_v2");
|
|
273
|
+
addV2Members(tempRoot, "agent-path");
|
|
274
|
+
const before = readFileSync(teamJsonPath(tempRoot, "agent-path"), "utf8");
|
|
275
|
+
|
|
276
|
+
const result = runTeamRaw(tempRoot, "bind-agent", "--team", "agent-path", "--id", "A", "--agent-path", "/root/not_runtime_core");
|
|
277
|
+
|
|
278
|
+
assert.notEqual(result.status, 0);
|
|
279
|
+
assert.match(result.stderr, /expected.*\/root\/runtime_core/i);
|
|
280
|
+
assert.equal(readFileSync(teamJsonPath(tempRoot, "agent-path"), "utf8"), before);
|
|
281
|
+
} finally {
|
|
282
|
+
cleanupTeamRoot(tempRoot);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test("#given a V2 member has no valid task name #when add-member runs #then state remains unchanged", () => {
|
|
287
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-task-name-");
|
|
288
|
+
try {
|
|
289
|
+
runTeam(tempRoot, "init", "--name", "Native", "--session-name", "agents", "--session", "task-name", "--transport", "multi_agent_v2");
|
|
290
|
+
const before = readFileSync(teamJsonPath(tempRoot, "task-name"), "utf8");
|
|
291
|
+
|
|
292
|
+
const missing = runTeamRaw(tempRoot, "add-member", "--team", "task-name", "--id", "A", "--name", "alpha", "--focus", "alpha scope", "--lens", "area", "--deliverable", "alpha result");
|
|
293
|
+
assert.notEqual(missing.status, 0);
|
|
294
|
+
assert.match(missing.stderr, /task name is required/i);
|
|
295
|
+
assert.equal(readFileSync(teamJsonPath(tempRoot, "task-name"), "utf8"), before);
|
|
296
|
+
|
|
297
|
+
const malformed = runTeamRaw(tempRoot, "add-member", "--team", "task-name", "--id", "A", "--name", "alpha", "--task-name", "Alpha-Hyphen", "--focus", "alpha scope", "--lens", "area", "--deliverable", "alpha result");
|
|
298
|
+
assert.notEqual(malformed.status, 0);
|
|
299
|
+
assert.match(malformed.stderr, /lowercase letters, digits, and underscores/i);
|
|
300
|
+
assert.equal(readFileSync(teamJsonPath(tempRoot, "task-name"), "utf8"), before);
|
|
301
|
+
} finally {
|
|
302
|
+
cleanupTeamRoot(tempRoot);
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test("#given legacy schemaVersion 2 state with existing members #when a mutation succeeds #then it upgrades in place as codex_app", () => {
|
|
307
|
+
const tempRoot = createTeamRoot("omo-codex-teammode-schema-migration-");
|
|
308
|
+
try {
|
|
309
|
+
// given - a populated legacy team: the schema downgrade happens AFTER members exist so the
|
|
310
|
+
// member-migration path is actually exercised, not just addMember defaults.
|
|
311
|
+
runTeam(tempRoot, "init", "--name", "Legacy", "--session-name", "threads", "--session", "schema-migration");
|
|
312
|
+
runTeam(tempRoot, "add-member", "--team", "schema-migration", "--id", "A", "--name", "alpha", "--focus", "alpha scope", "--lens", "area", "--deliverable", "alpha result");
|
|
313
|
+
runTeam(tempRoot, "add-member", "--team", "schema-migration", "--id", "B", "--name", "beta", "--focus", "beta scope", "--lens", "ownership", "--deliverable", "beta result");
|
|
314
|
+
runTeam(tempRoot, "bind-thread", "--team", "schema-migration", "--id", "A", "--thread", "legacy-thread-a");
|
|
315
|
+
const path = teamJsonPath(tempRoot, "schema-migration");
|
|
316
|
+
const legacy = readTeamJson(tempRoot, "schema-migration");
|
|
317
|
+
legacy.schemaVersion = 2;
|
|
318
|
+
delete legacy.transport;
|
|
319
|
+
delete legacy.leader.agentPath;
|
|
320
|
+
for (const member of legacy.members) {
|
|
321
|
+
delete member.taskName;
|
|
322
|
+
delete member.agentPath;
|
|
323
|
+
}
|
|
324
|
+
writeFileSync(path, `${JSON.stringify(legacy, null, 2)}\n`);
|
|
325
|
+
|
|
326
|
+
// when - any mutating command loads, migrates, and persists
|
|
327
|
+
runTeam(tempRoot, "set-status", "--team", "schema-migration", "--id", "B", "--status", "blocked", "--note", "legacy migration check");
|
|
328
|
+
const migrated = readTeamJson(tempRoot, "schema-migration");
|
|
329
|
+
|
|
330
|
+
// then - the persisted file is schema 3 codex_app and PRE-EXISTING members gained null V2 fields
|
|
331
|
+
assert.equal(migrated.schemaVersion, 3);
|
|
332
|
+
assert.equal(migrated.transport, "codex_app");
|
|
333
|
+
assert.equal(migrated.leader.agentPath, null);
|
|
334
|
+
assert.deepEqual(
|
|
335
|
+
migrated.members.map((member) => ({ id: member.id, taskName: member.taskName, agentPath: member.agentPath, threadId: member.threadId })),
|
|
336
|
+
[
|
|
337
|
+
{ id: "A", taskName: null, agentPath: null, threadId: "legacy-thread-a" },
|
|
338
|
+
{ id: "B", taskName: null, agentPath: null, threadId: null },
|
|
339
|
+
],
|
|
340
|
+
);
|
|
341
|
+
assert.equal(migrated.members[1].status, "blocked");
|
|
342
|
+
} finally {
|
|
343
|
+
cleanupTeamRoot(tempRoot);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
@@ -6,47 +6,16 @@ import { fileURLToPath } from "node:url";
|
|
|
6
6
|
|
|
7
7
|
const root = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
8
8
|
|
|
9
|
-
async
|
|
9
|
+
test("#given ulw-plan skill copies #when component source and packaged copy are compared #then they are byte-identical and expose the loader-parsed name", async () => {
|
|
10
|
+
// given
|
|
10
11
|
const componentPath = join(root, "components", "ultrawork", "skills", "ulw-plan", "SKILL.md");
|
|
11
12
|
const packagedPath = join(root, "skills", "ulw-plan", "SKILL.md");
|
|
12
|
-
return [
|
|
13
|
-
{ label: "component", path: componentPath, content: await readFile(componentPath, "utf8") },
|
|
14
|
-
{ label: "packaged", path: packagedPath, content: await readFile(packagedPath, "utf8") },
|
|
15
|
-
];
|
|
16
|
-
}
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
`${copy.label}: must preserve independent spawn waves`,
|
|
26
|
-
);
|
|
27
|
-
assert.match(
|
|
28
|
-
copy.content,
|
|
29
|
-
/After the wave\s+is launched[\s\S]{0,240}multi_agent_v1\.wait_agent[\s\S]{0,240}terminal status/i,
|
|
30
|
-
`${copy.label}: must wait after the wave is launched`,
|
|
31
|
-
);
|
|
32
|
-
assert.doesNotMatch(
|
|
33
|
-
copy.content,
|
|
34
|
-
/Immediately after any `multi_agent_v1\.spawn_agent`/i,
|
|
35
|
-
`${copy.label}: must not serialize independent spawns`,
|
|
36
|
-
);
|
|
37
|
-
assert.match(copy.content, /terminal status/i, `${copy.label}: must wait until terminal status`);
|
|
38
|
-
assert.match(copy.content, /WORKING:/, `${copy.label}: must keep progress liveness guidance`);
|
|
39
|
-
assert.match(copy.content, /BLOCKED:/, `${copy.label}: must keep blocked liveness guidance`);
|
|
40
|
-
assert.match(
|
|
41
|
-
copy.content,
|
|
42
|
-
/timeout only means no new mailbox update arrived/i,
|
|
43
|
-
`${copy.label}: must frame wait timeouts as mailbox silence`,
|
|
44
|
-
);
|
|
45
|
-
assert.match(copy.content, /Fallback only when/, `${copy.label}: must keep explicit fallback conditions`);
|
|
46
|
-
assert.match(
|
|
47
|
-
copy.content,
|
|
48
|
-
/do not start dependent planning, drafting, approval-gate work, or final handoff/i,
|
|
49
|
-
`${copy.label}: must block dependent planning work before child results are integrated`,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
14
|
+
// when
|
|
15
|
+
const component = await readFile(componentPath, "utf8");
|
|
16
|
+
const packaged = await readFile(packagedPath, "utf8");
|
|
17
|
+
|
|
18
|
+
// then
|
|
19
|
+
assert.equal(packaged, component);
|
|
20
|
+
assert.match(component, /^name: ulw-plan$/m);
|
|
52
21
|
});
|