@duypham93/openkit 0.2.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/.opencode/README.md +47 -0
- package/.opencode/install-manifest.json +41 -0
- package/.opencode/lib/artifact-scaffolder.js +111 -0
- package/.opencode/lib/contract-consistency.js +218 -0
- package/.opencode/lib/parallel-execution-rules.js +261 -0
- package/.opencode/lib/runtime-paths.js +95 -0
- package/.opencode/lib/runtime-summary.js +82 -0
- package/.opencode/lib/state-guard.js +99 -0
- package/.opencode/lib/task-board-rules.js +375 -0
- package/.opencode/lib/work-item-store.js +280 -0
- package/.opencode/lib/workflow-state-controller.js +1739 -0
- package/.opencode/lib/workflow-state-rules.js +331 -0
- package/.opencode/opencode.json +93 -0
- package/.opencode/package.json +3 -0
- package/.opencode/tests/artifact-scaffolder.test.js +733 -0
- package/.opencode/tests/multi-work-item-runtime.test.js +369 -0
- package/.opencode/tests/parallel-execution-runtime.test.js +259 -0
- package/.opencode/tests/session-start-hook.test.js +357 -0
- package/.opencode/tests/state-guard.test.js +124 -0
- package/.opencode/tests/task-board-rules.test.js +204 -0
- package/.opencode/tests/work-item-store.test.js +380 -0
- package/.opencode/tests/workflow-behavior.test.js +149 -0
- package/.opencode/tests/workflow-contract-consistency.test.js +387 -0
- package/.opencode/tests/workflow-state-cli.test.js +1275 -0
- package/.opencode/tests/workflow-state-controller.test.js +1038 -0
- package/.opencode/work-items/feature-001/state.json +70 -0
- package/.opencode/work-items/index.json +13 -0
- package/.opencode/workflow-state.js +489 -0
- package/.opencode/workflow-state.json +70 -0
- package/AGENTS.md +265 -0
- package/README.md +401 -0
- package/agents/architect-agent.md +63 -0
- package/agents/ba-agent.md +56 -0
- package/agents/code-reviewer.md +77 -0
- package/agents/fullstack-agent.md +115 -0
- package/agents/master-orchestrator.md +60 -0
- package/agents/pm-agent.md +56 -0
- package/agents/qa-agent.md +124 -0
- package/agents/tech-lead-agent.md +60 -0
- package/assets/install-bundle/README.md +7 -0
- package/assets/install-bundle/opencode/README.md +11 -0
- package/assets/install-bundle/opencode/agents/ArchitectAgent.md +63 -0
- package/assets/install-bundle/opencode/agents/BAAgent.md +56 -0
- package/assets/install-bundle/opencode/agents/CodeReviewer.md +77 -0
- package/assets/install-bundle/opencode/agents/FullstackAgent.md +115 -0
- package/assets/install-bundle/opencode/agents/MasterOrchestrator.md +60 -0
- package/assets/install-bundle/opencode/agents/PMAgent.md +56 -0
- package/assets/install-bundle/opencode/agents/QAAgent.md +124 -0
- package/assets/install-bundle/opencode/agents/TechLeadAgent.md +60 -0
- package/assets/install-bundle/opencode/commands/brainstorm.md +44 -0
- package/assets/install-bundle/opencode/commands/delivery.md +45 -0
- package/assets/install-bundle/opencode/commands/execute-plan.md +44 -0
- package/assets/install-bundle/opencode/commands/migrate.md +61 -0
- package/assets/install-bundle/opencode/commands/quick-task.md +45 -0
- package/assets/install-bundle/opencode/commands/task.md +46 -0
- package/assets/install-bundle/opencode/commands/write-plan.md +50 -0
- package/assets/install-bundle/opencode/context/core/lane-selection.md +54 -0
- package/assets/install-bundle/opencode/skills/brainstorming/SKILL.md +51 -0
- package/assets/install-bundle/opencode/skills/code-review/SKILL.md +48 -0
- package/assets/install-bundle/opencode/skills/subagent-driven-development/SKILL.md +79 -0
- package/assets/install-bundle/opencode/skills/systematic-debugging/SKILL.md +61 -0
- package/assets/install-bundle/opencode/skills/test-driven-development/SKILL.md +48 -0
- package/assets/install-bundle/opencode/skills/using-skills/SKILL.md +39 -0
- package/assets/install-bundle/opencode/skills/verification-before-completion/SKILL.md +137 -0
- package/assets/install-bundle/opencode/skills/writing-plans/SKILL.md +68 -0
- package/assets/install-bundle/opencode/skills/writing-specs/SKILL.md +47 -0
- package/assets/opencode.json.template +11 -0
- package/assets/openkit-install.json.template +19 -0
- package/bin/openkit.js +9 -0
- package/commands/brainstorm.md +44 -0
- package/commands/delivery.md +45 -0
- package/commands/execute-plan.md +44 -0
- package/commands/migrate.md +61 -0
- package/commands/quick-task.md +45 -0
- package/commands/task.md +46 -0
- package/commands/write-plan.md +50 -0
- package/context/core/approval-gates.md +146 -0
- package/context/core/code-quality.md +42 -0
- package/context/core/issue-routing.md +85 -0
- package/context/core/lane-selection.md +54 -0
- package/context/core/project-config.md +143 -0
- package/context/core/session-resume.md +85 -0
- package/context/core/workflow-state-schema.md +224 -0
- package/context/core/workflow.md +442 -0
- package/context/navigation.md +94 -0
- package/docs/adr/README.md +6 -0
- package/docs/architecture/2026-03-20-task-intake-dashboard.md +54 -0
- package/docs/architecture/README.md +7 -0
- package/docs/briefs/2026-03-20-task-intake-dashboard.md +48 -0
- package/docs/briefs/README.md +7 -0
- package/docs/governance/README.md +25 -0
- package/docs/governance/adr-policy.md +27 -0
- package/docs/governance/definition-of-done.md +17 -0
- package/docs/governance/naming-conventions.md +21 -0
- package/docs/governance/severity-levels.md +12 -0
- package/docs/maintainer/README.md +51 -0
- package/docs/operations/README.md +79 -0
- package/docs/operations/internal-records/2026-03-24-release-checklist.md +79 -0
- package/docs/operations/internal-records/2026-03-24-simplified-install-ux.md +36 -0
- package/docs/operations/internal-records/README.md +18 -0
- package/docs/operations/runbooks/README.md +23 -0
- package/docs/operations/runbooks/openkit-daily-usage.md +288 -0
- package/docs/operations/runbooks/workflow-state-smoke-tests.md +302 -0
- package/docs/operator/README.md +50 -0
- package/docs/plans/2026-03-20-task-intake-dashboard.md +49 -0
- package/docs/plans/2026-03-21-openkit-full-delivery-multi-task-runtime.md +521 -0
- package/docs/plans/2026-03-23-openkit-global-install-runtime.md +157 -0
- package/docs/plans/README.md +7 -0
- package/docs/qa/2026-03-20-task-intake-dashboard.md +41 -0
- package/docs/qa/README.md +7 -0
- package/docs/specs/2026-03-20-task-intake-dashboard.md +50 -0
- package/docs/specs/2026-03-21-openkit-full-delivery-multi-task-runtime.md +462 -0
- package/docs/specs/README.md +7 -0
- package/docs/templates/README.md +36 -0
- package/docs/templates/adr-template.md +18 -0
- package/docs/templates/architecture-template.md +31 -0
- package/docs/templates/implementation-plan-template.md +32 -0
- package/docs/templates/migration-baseline-checklist.md +48 -0
- package/docs/templates/migration-plan-template.md +52 -0
- package/docs/templates/migration-report-template.md +74 -0
- package/docs/templates/migration-verify-checklist.md +39 -0
- package/docs/templates/product-brief-template.md +32 -0
- package/docs/templates/qa-report-template.md +37 -0
- package/docs/templates/quick-task-template.md +36 -0
- package/docs/templates/spec-template.md +31 -0
- package/hooks/hooks.json +16 -0
- package/hooks/session-start +162 -0
- package/package.json +24 -0
- package/registry.json +328 -0
- package/skills/brainstorming/SKILL.md +51 -0
- package/skills/code-review/SKILL.md +48 -0
- package/skills/subagent-driven-development/SKILL.md +79 -0
- package/skills/systematic-debugging/SKILL.md +61 -0
- package/skills/test-driven-development/SKILL.md +48 -0
- package/skills/using-skills/SKILL.md +39 -0
- package/skills/verification-before-completion/SKILL.md +137 -0
- package/skills/writing-plans/SKILL.md +68 -0
- package/skills/writing-specs/SKILL.md +47 -0
- package/src/audit/vietnamese-detection.js +259 -0
- package/src/cli/commands/detect-vietnamese.js +24 -0
- package/src/cli/commands/doctor.js +33 -0
- package/src/cli/commands/help.js +33 -0
- package/src/cli/commands/init.js +25 -0
- package/src/cli/commands/install-global.js +26 -0
- package/src/cli/commands/install.js +25 -0
- package/src/cli/commands/run.js +63 -0
- package/src/cli/commands/uninstall.js +32 -0
- package/src/cli/commands/upgrade.js +25 -0
- package/src/cli/conflict-output.js +19 -0
- package/src/cli/index.js +56 -0
- package/src/global/doctor.js +101 -0
- package/src/global/ensure-install.js +32 -0
- package/src/global/install-state.js +73 -0
- package/src/global/launcher.js +51 -0
- package/src/global/materialize.js +123 -0
- package/src/global/paths.js +85 -0
- package/src/global/uninstall.js +25 -0
- package/src/global/workspace-state.js +63 -0
- package/src/install/asset-manifest.js +284 -0
- package/src/install/conflicts.js +43 -0
- package/src/install/discovery.js +138 -0
- package/src/install/install-state.js +136 -0
- package/src/install/materialize.js +158 -0
- package/src/install/merge-policy.js +145 -0
- package/src/runtime/doctor.js +281 -0
- package/src/runtime/launcher.js +49 -0
- package/src/runtime/opencode-layering.js +135 -0
- package/src/runtime/openkit-managed-summary.js +27 -0
- package/tests/cli/openkit-cli.test.js +417 -0
- package/tests/global/doctor.test.js +130 -0
- package/tests/global/ensure-install.test.js +105 -0
- package/tests/install/discovery.test.js +124 -0
- package/tests/install/install-state.test.js +346 -0
- package/tests/install/materialize.test.js +244 -0
- package/tests/install/merge-policy.test.js +177 -0
- package/tests/runtime/doctor.test.js +430 -0
- package/tests/runtime/launcher.test.js +230 -0
- package/tests/runtime/module-boundary.test.js +16 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
const test = require("node:test")
|
|
2
|
+
const assert = require("node:assert/strict")
|
|
3
|
+
const fs = require("fs")
|
|
4
|
+
const os = require("os")
|
|
5
|
+
const path = require("path")
|
|
6
|
+
|
|
7
|
+
const { runDoctor, getContractConsistencyReport } = require("../lib/workflow-state-controller")
|
|
8
|
+
|
|
9
|
+
function makeTempProject() {
|
|
10
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), "openkit-contract-check-"))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function setupTempRuntime(projectRoot) {
|
|
14
|
+
const opencodeDir = path.join(projectRoot, ".opencode")
|
|
15
|
+
const hooksDir = path.join(projectRoot, "hooks")
|
|
16
|
+
const skillsDir = path.join(projectRoot, "skills", "using-skills")
|
|
17
|
+
const contextCoreDir = path.join(projectRoot, "context", "core")
|
|
18
|
+
const commandsDir = path.join(projectRoot, "commands")
|
|
19
|
+
const agentsDir = path.join(projectRoot, "agents")
|
|
20
|
+
|
|
21
|
+
fs.mkdirSync(opencodeDir, { recursive: true })
|
|
22
|
+
fs.mkdirSync(hooksDir, { recursive: true })
|
|
23
|
+
fs.mkdirSync(skillsDir, { recursive: true })
|
|
24
|
+
fs.mkdirSync(contextCoreDir, { recursive: true })
|
|
25
|
+
fs.mkdirSync(commandsDir, { recursive: true })
|
|
26
|
+
fs.mkdirSync(agentsDir, { recursive: true })
|
|
27
|
+
|
|
28
|
+
const fixtureState = JSON.parse(
|
|
29
|
+
fs.readFileSync(path.resolve(__dirname, "../workflow-state.json"), "utf8"),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
fs.writeFileSync(
|
|
33
|
+
path.join(opencodeDir, "workflow-state.json"),
|
|
34
|
+
`${JSON.stringify(fixtureState, null, 2)}\n`,
|
|
35
|
+
"utf8",
|
|
36
|
+
)
|
|
37
|
+
fs.writeFileSync(
|
|
38
|
+
path.join(opencodeDir, "opencode.json"),
|
|
39
|
+
`${JSON.stringify({
|
|
40
|
+
kit: {
|
|
41
|
+
name: "OpenKit AI Software Factory",
|
|
42
|
+
version: "0.1.0",
|
|
43
|
+
entryAgent: "MasterOrchestrator",
|
|
44
|
+
registry: {
|
|
45
|
+
path: "registry.json",
|
|
46
|
+
schema: "openkit/component-registry@1",
|
|
47
|
+
},
|
|
48
|
+
installManifest: {
|
|
49
|
+
path: ".opencode/install-manifest.json",
|
|
50
|
+
schema: "openkit/install-manifest@1",
|
|
51
|
+
},
|
|
52
|
+
activeProfile: "openkit-core",
|
|
53
|
+
},
|
|
54
|
+
agents: {
|
|
55
|
+
primary: "agents/master-orchestrator.md",
|
|
56
|
+
teamRoles: [
|
|
57
|
+
"agents/master-orchestrator.md",
|
|
58
|
+
"agents/fullstack-agent.md",
|
|
59
|
+
"agents/qa-agent.md",
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
commands: {
|
|
63
|
+
available: [
|
|
64
|
+
"commands/task.md",
|
|
65
|
+
"commands/quick-task.md",
|
|
66
|
+
"commands/migrate.md",
|
|
67
|
+
"commands/delivery.md",
|
|
68
|
+
"commands/brainstorm.md",
|
|
69
|
+
"commands/write-plan.md",
|
|
70
|
+
"commands/execute-plan.md",
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
}, null, 2)}\n`,
|
|
74
|
+
"utf8",
|
|
75
|
+
)
|
|
76
|
+
fs.writeFileSync(
|
|
77
|
+
path.join(projectRoot, "registry.json"),
|
|
78
|
+
`${JSON.stringify({
|
|
79
|
+
schema: "openkit/component-registry@1",
|
|
80
|
+
registryVersion: 1,
|
|
81
|
+
profiles: [
|
|
82
|
+
{
|
|
83
|
+
id: "profile.openkit-core",
|
|
84
|
+
name: "openkit-core",
|
|
85
|
+
description: "Core profile",
|
|
86
|
+
componentRefs: ["agents", "runtime", "docs"],
|
|
87
|
+
defaultForRepository: true,
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
}, null, 2)}\n`,
|
|
91
|
+
"utf8",
|
|
92
|
+
)
|
|
93
|
+
fs.writeFileSync(
|
|
94
|
+
path.join(opencodeDir, "install-manifest.json"),
|
|
95
|
+
`${JSON.stringify({
|
|
96
|
+
schema: "openkit/install-manifest@1",
|
|
97
|
+
manifestVersion: 1,
|
|
98
|
+
installation: {
|
|
99
|
+
activeProfile: "openkit-core",
|
|
100
|
+
},
|
|
101
|
+
}, null, 2)}\n`,
|
|
102
|
+
"utf8",
|
|
103
|
+
)
|
|
104
|
+
fs.writeFileSync(path.join(hooksDir, "hooks.json"), '{"hooks":{}}\n', "utf8")
|
|
105
|
+
fs.writeFileSync(path.join(hooksDir, "session-start"), "#!/usr/bin/env bash\n", "utf8")
|
|
106
|
+
fs.writeFileSync(path.join(skillsDir, "SKILL.md"), "# using-skills\n", "utf8")
|
|
107
|
+
fs.writeFileSync(path.join(opencodeDir, "workflow-state.js"), "#!/usr/bin/env node\n", "utf8")
|
|
108
|
+
|
|
109
|
+
fs.writeFileSync(
|
|
110
|
+
path.join(contextCoreDir, "workflow.md"),
|
|
111
|
+
[
|
|
112
|
+
"# Workflow",
|
|
113
|
+
"",
|
|
114
|
+
"Quick Task+ is the live semantics of the quick lane, not a third lane.",
|
|
115
|
+
"Mode enums remain `quick`, `migration`, and `full`.",
|
|
116
|
+
"Commands remain `/task`, `/quick-task`, `/migrate`, `/delivery`, and `/write-plan`.",
|
|
117
|
+
"Migration is the dedicated upgrade and modernization lane.",
|
|
118
|
+
"Migration work must stay free of task boards.",
|
|
119
|
+
"Migration must preserve behavior first and decouple blockers before broad upgrade work.",
|
|
120
|
+
"Lane tie breaker: product uncertainty chooses full, compatibility uncertainty chooses migration, low local uncertainty chooses quick.",
|
|
121
|
+
"Lane Decision Matrix: use examples to choose the lane when wording alone is not enough.",
|
|
122
|
+
"Do not invent a quick task board; quick work stays task-board free.",
|
|
123
|
+
"Full Delivery owns the execution task board when one exists.",
|
|
124
|
+
"Quick stages: `quick_intake -> quick_plan -> quick_build -> quick_verify -> quick_done`.",
|
|
125
|
+
"Migration stages: `migration_intake -> migration_baseline -> migration_strategy -> migration_upgrade -> migration_verify -> migration_done`.",
|
|
126
|
+
"Full stages: `full_intake -> full_brief -> full_spec -> full_architecture -> full_plan -> full_implementation -> full_qa -> full_done`.",
|
|
127
|
+
"Quick approvals: `quick_verified`.",
|
|
128
|
+
"Migration approvals: `baseline_to_strategy`, `strategy_to_upgrade`, `upgrade_to_verify`, `migration_verified`.",
|
|
129
|
+
"Full approvals: `pm_to_ba`, `ba_to_architect`, `architect_to_tech_lead`, `tech_lead_to_fullstack`, `fullstack_to_qa`, `qa_to_done`.",
|
|
130
|
+
"Quick artifacts: `task_card`; migration artifacts may include `architecture`, `plan`, `migration_report`; full artifacts: `brief`, `spec`, `architecture`, `plan`, `qa_report`, `adr`.",
|
|
131
|
+
"",
|
|
132
|
+
].join("\n"),
|
|
133
|
+
"utf8",
|
|
134
|
+
)
|
|
135
|
+
fs.writeFileSync(
|
|
136
|
+
path.join(contextCoreDir, "workflow-state-schema.md"),
|
|
137
|
+
[
|
|
138
|
+
"# Workflow State Schema",
|
|
139
|
+
"",
|
|
140
|
+
"Modes: `quick`, `migration`, `full`.",
|
|
141
|
+
"Quick stages: `quick_intake`, `quick_plan`, `quick_build`, `quick_verify`, `quick_done`.",
|
|
142
|
+
"Migration stages: `migration_intake`, `migration_baseline`, `migration_strategy`, `migration_upgrade`, `migration_verify`, `migration_done`.",
|
|
143
|
+
"Full stages: `full_intake`, `full_brief`, `full_spec`, `full_architecture`, `full_plan`, `full_implementation`, `full_qa`, `full_done`.",
|
|
144
|
+
"Artifact keys: `task_card`, `brief`, `spec`, `architecture`, `plan`, `migration_report`, `qa_report`, `adr`.",
|
|
145
|
+
"Routing profile keys: `work_intent`, `behavior_delta`, `dominant_uncertainty`, `scope_shape`, `selection_reason`.",
|
|
146
|
+
"Quick approvals: `quick_verified`.",
|
|
147
|
+
"Migration approvals: `baseline_to_strategy`, `strategy_to_upgrade`, `upgrade_to_verify`, `migration_verified`.",
|
|
148
|
+
"Full approvals: `pm_to_ba`, `ba_to_architect`, `architect_to_tech_lead`, `tech_lead_to_fullstack`, `fullstack_to_qa`, `qa_to_done`.",
|
|
149
|
+
"Compatibility mirror behavior remains active for the current work item.",
|
|
150
|
+
"",
|
|
151
|
+
].join("\n"),
|
|
152
|
+
"utf8",
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
for (const commandName of ["task", "quick-task", "migrate", "delivery", "brainstorm", "write-plan", "execute-plan"]) {
|
|
156
|
+
fs.writeFileSync(path.join(commandsDir, `${commandName}.md`), `# ${commandName}\n`, "utf8")
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (const agentName of ["master-orchestrator", "fullstack-agent", "qa-agent"]) {
|
|
160
|
+
fs.writeFileSync(path.join(agentsDir, `${agentName}.md`), `# ${agentName}\n`, "utf8")
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
test("contract consistency report passes for aligned runtime surfaces", () => {
|
|
165
|
+
const projectRoot = makeTempProject()
|
|
166
|
+
setupTempRuntime(projectRoot)
|
|
167
|
+
|
|
168
|
+
const report = getContractConsistencyReport(path.join(projectRoot, ".opencode", "workflow-state.json"))
|
|
169
|
+
|
|
170
|
+
assert.equal(report.summary.error, 0)
|
|
171
|
+
assert.ok(report.checks.length > 0)
|
|
172
|
+
assert.ok(report.checks.every((check) => check.ok))
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
test("doctor reports contract consistency failures for missing command files", () => {
|
|
176
|
+
const projectRoot = makeTempProject()
|
|
177
|
+
setupTempRuntime(projectRoot)
|
|
178
|
+
fs.rmSync(path.join(projectRoot, "commands", "quick-task.md"))
|
|
179
|
+
|
|
180
|
+
const report = runDoctor(path.join(projectRoot, ".opencode", "workflow-state.json"))
|
|
181
|
+
|
|
182
|
+
assert.ok(report.summary.error > 0)
|
|
183
|
+
assert.ok(
|
|
184
|
+
report.checks.some(
|
|
185
|
+
(check) => check.label === "declared command files exist" && check.ok === false,
|
|
186
|
+
),
|
|
187
|
+
)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test("doctor reports contract consistency failures for schema/runtime parity mismatches", () => {
|
|
191
|
+
const projectRoot = makeTempProject()
|
|
192
|
+
setupTempRuntime(projectRoot)
|
|
193
|
+
fs.writeFileSync(
|
|
194
|
+
path.join(projectRoot, "context", "core", "workflow-state-schema.md"),
|
|
195
|
+
[
|
|
196
|
+
"# Workflow State Schema",
|
|
197
|
+
"",
|
|
198
|
+
"Modes: `quick`, `migration`, `full`.",
|
|
199
|
+
"Quick stages: `quick_intake`, `quick_build`, `quick_verify`, `quick_done`.",
|
|
200
|
+
"Migration stages: `migration_intake`, `migration_baseline`, `migration_strategy`, `migration_upgrade`, `migration_verify`, `migration_done`.",
|
|
201
|
+
"Full stages: `full_intake`, `full_brief`, `full_spec`, `full_architecture`, `full_plan`, `full_implementation`, `full_qa`, `full_done`.",
|
|
202
|
+
"Artifact keys: `task_card`, `brief`, `spec`, `architecture`, `plan`, `qa_report`, `adr`.",
|
|
203
|
+
"Routing profile keys: `work_intent`, `behavior_delta`, `dominant_uncertainty`, `scope_shape`, `selection_reason`.",
|
|
204
|
+
"Quick approvals: `quick_verified`.",
|
|
205
|
+
"Migration approvals: `baseline_to_strategy`, `strategy_to_upgrade`, `upgrade_to_verify`, `migration_verified`.",
|
|
206
|
+
"Full approvals: `pm_to_ba`, `ba_to_architect`, `architect_to_tech_lead`, `tech_lead_to_fullstack`, `fullstack_to_qa`, `qa_to_done`.",
|
|
207
|
+
"",
|
|
208
|
+
].join("\n"),
|
|
209
|
+
"utf8",
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
const report = runDoctor(path.join(projectRoot, ".opencode", "workflow-state.json"))
|
|
213
|
+
|
|
214
|
+
assert.ok(report.summary.error > 0)
|
|
215
|
+
assert.ok(
|
|
216
|
+
report.checks.some(
|
|
217
|
+
(check) => check.label === "workflow schema matches runtime stage sequences" && check.ok === false,
|
|
218
|
+
),
|
|
219
|
+
)
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
test("doctor reports contract consistency failures when quick/task-board separation language drifts", () => {
|
|
223
|
+
const projectRoot = makeTempProject()
|
|
224
|
+
setupTempRuntime(projectRoot)
|
|
225
|
+
fs.writeFileSync(
|
|
226
|
+
path.join(projectRoot, "context", "core", "workflow.md"),
|
|
227
|
+
[
|
|
228
|
+
"# Workflow",
|
|
229
|
+
"",
|
|
230
|
+
"Quick Task+ is the live semantics of the quick lane, not a third lane.",
|
|
231
|
+
"Mode enums remain `quick`, `migration`, and `full`.",
|
|
232
|
+
"Commands remain `/task`, `/quick-task`, `/migrate`, `/delivery`, and `/write-plan`.",
|
|
233
|
+
"Quick stages: `quick_intake -> quick_plan -> quick_build -> quick_verify -> quick_done`.",
|
|
234
|
+
"Migration is the dedicated upgrade and modernization lane.",
|
|
235
|
+
"Migration work must stay free of task boards.",
|
|
236
|
+
"Migration must preserve behavior first and decouple blockers before broad upgrade work.",
|
|
237
|
+
"Lane tie breaker: product uncertainty chooses full, compatibility uncertainty chooses migration, low local uncertainty chooses quick.",
|
|
238
|
+
"Lane Decision Matrix: use examples to choose the lane when wording alone is not enough.",
|
|
239
|
+
"Migration stages: `migration_intake -> migration_baseline -> migration_strategy -> migration_upgrade -> migration_verify -> migration_done`.",
|
|
240
|
+
"Full stages: `full_intake -> full_brief -> full_spec -> full_architecture -> full_plan -> full_implementation -> full_qa -> full_done`.",
|
|
241
|
+
"Quick approvals: `quick_verified`.",
|
|
242
|
+
"Migration approvals: `baseline_to_strategy`, `strategy_to_upgrade`, `upgrade_to_verify`, `migration_verified`.",
|
|
243
|
+
"Full approvals: `pm_to_ba`, `ba_to_architect`, `architect_to_tech_lead`, `tech_lead_to_fullstack`, `fullstack_to_qa`, `qa_to_done`.",
|
|
244
|
+
"Quick artifacts: `task_card`; migration artifacts may include `architecture`, `plan`, `migration_report`; full artifacts: `brief`, `spec`, `architecture`, `plan`, `qa_report`, `adr`.",
|
|
245
|
+
"",
|
|
246
|
+
].join("\n"),
|
|
247
|
+
"utf8",
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
const report = runDoctor(path.join(projectRoot, ".opencode", "workflow-state.json"))
|
|
251
|
+
|
|
252
|
+
assert.ok(report.summary.error > 0)
|
|
253
|
+
assert.ok(
|
|
254
|
+
report.checks.some(
|
|
255
|
+
(check) => check.label === "workflow contract keeps quick lane free of task boards" && check.ok === false,
|
|
256
|
+
),
|
|
257
|
+
)
|
|
258
|
+
assert.ok(
|
|
259
|
+
report.checks.some(
|
|
260
|
+
(check) => check.label === "workflow contract states full delivery owns execution task boards" && check.ok === false,
|
|
261
|
+
),
|
|
262
|
+
)
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
test("contract consistency accepts equivalent quick/task-board guardrail wording", () => {
|
|
266
|
+
const projectRoot = makeTempProject()
|
|
267
|
+
setupTempRuntime(projectRoot)
|
|
268
|
+
|
|
269
|
+
fs.writeFileSync(
|
|
270
|
+
path.join(projectRoot, "context", "core", "workflow.md"),
|
|
271
|
+
[
|
|
272
|
+
"# Workflow",
|
|
273
|
+
"",
|
|
274
|
+
"Quick Task+ remains the active quick semantics and is not a third operating mode.",
|
|
275
|
+
"Runtime modes stay `quick`, `migration`, and `full`.",
|
|
276
|
+
"Migration is the dedicated upgrade and modernization lane.",
|
|
277
|
+
"Migration work must stay free of execution-task-board state.",
|
|
278
|
+
"Migration must preserve behavior first and decouple blockers before broad upgrade work.",
|
|
279
|
+
"Lane tie breaker: product uncertainty chooses full, compatibility uncertainty chooses migration, low local uncertainty chooses quick.",
|
|
280
|
+
"Lane Decision Matrix: use examples to choose the lane when wording alone is not enough.",
|
|
281
|
+
"Execution task boards belong only to Full Delivery work items.",
|
|
282
|
+
"Quick work must stay free of execution-task-board state.",
|
|
283
|
+
"Quick stages: `quick_intake -> quick_plan -> quick_build -> quick_verify -> quick_done`.",
|
|
284
|
+
"Migration stages: `migration_intake -> migration_baseline -> migration_strategy -> migration_upgrade -> migration_verify -> migration_done`.",
|
|
285
|
+
"Full stages: `full_intake -> full_brief -> full_spec -> full_architecture -> full_plan -> full_implementation -> full_qa -> full_done`.",
|
|
286
|
+
"Quick approvals: `quick_verified`.",
|
|
287
|
+
"Migration approvals: `baseline_to_strategy`, `strategy_to_upgrade`, `upgrade_to_verify`, `migration_verified`.",
|
|
288
|
+
"Full approvals: `pm_to_ba`, `ba_to_architect`, `architect_to_tech_lead`, `tech_lead_to_fullstack`, `fullstack_to_qa`, `qa_to_done`.",
|
|
289
|
+
"Quick artifacts: `task_card`; full artifacts: `brief`, `spec`, `architecture`, `plan`, `qa_report`, `adr`.",
|
|
290
|
+
"Routing profile keys: `work_intent`, `behavior_delta`, `dominant_uncertainty`, `scope_shape`, `selection_reason`.",
|
|
291
|
+
"",
|
|
292
|
+
].join("\n"),
|
|
293
|
+
"utf8",
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
const report = runDoctor(path.join(projectRoot, ".opencode", "workflow-state.json"))
|
|
297
|
+
|
|
298
|
+
assert.equal(report.summary.error, 0)
|
|
299
|
+
assert.ok(
|
|
300
|
+
report.checks.some(
|
|
301
|
+
(check) => check.label === "workflow contract keeps quick lane free of task boards" && check.ok === true,
|
|
302
|
+
),
|
|
303
|
+
)
|
|
304
|
+
assert.ok(
|
|
305
|
+
report.checks.some(
|
|
306
|
+
(check) => check.label === "workflow contract keeps migration lane free of task boards" && check.ok === true,
|
|
307
|
+
),
|
|
308
|
+
)
|
|
309
|
+
assert.ok(
|
|
310
|
+
report.checks.some(
|
|
311
|
+
(check) =>
|
|
312
|
+
check.label === "workflow contract states migration preserves behavior and decouples blockers first" &&
|
|
313
|
+
check.ok === true,
|
|
314
|
+
),
|
|
315
|
+
)
|
|
316
|
+
assert.ok(
|
|
317
|
+
report.checks.some(
|
|
318
|
+
(check) => check.label === "workflow contract states full delivery owns execution task boards" && check.ok === true,
|
|
319
|
+
),
|
|
320
|
+
)
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
test("contract consistency accepts equivalent compatibility mirror wording", () => {
|
|
324
|
+
const projectRoot = makeTempProject()
|
|
325
|
+
setupTempRuntime(projectRoot)
|
|
326
|
+
|
|
327
|
+
fs.writeFileSync(
|
|
328
|
+
path.join(projectRoot, "context", "core", "workflow-state-schema.md"),
|
|
329
|
+
[
|
|
330
|
+
"# Workflow State Schema",
|
|
331
|
+
"",
|
|
332
|
+
"Modes: `quick`, `migration`, `full`.",
|
|
333
|
+
"Quick stages: `quick_intake`, `quick_plan`, `quick_build`, `quick_verify`, `quick_done`.",
|
|
334
|
+
"Migration stages: `migration_intake`, `migration_baseline`, `migration_strategy`, `migration_upgrade`, `migration_verify`, `migration_done`.",
|
|
335
|
+
"Full stages: `full_intake`, `full_brief`, `full_spec`, `full_architecture`, `full_plan`, `full_implementation`, `full_qa`, `full_done`.",
|
|
336
|
+
"Artifact keys: `task_card`, `brief`, `spec`, `architecture`, `plan`, `migration_report`, `qa_report`, `adr`.",
|
|
337
|
+
"Routing profile keys: `work_intent`, `behavior_delta`, `dominant_uncertainty`, `scope_shape`, `selection_reason`.",
|
|
338
|
+
"Quick approvals: `quick_verified`.",
|
|
339
|
+
"Migration approvals: `baseline_to_strategy`, `strategy_to_upgrade`, `upgrade_to_verify`, `migration_verified`.",
|
|
340
|
+
"Full approvals: `pm_to_ba`, `ba_to_architect`, `architect_to_tech_lead`, `tech_lead_to_fullstack`, `fullstack_to_qa`, `qa_to_done`.",
|
|
341
|
+
"The active work item still writes through the repo-root state file as a mirrored compatibility surface.",
|
|
342
|
+
"",
|
|
343
|
+
].join("\n"),
|
|
344
|
+
"utf8",
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
const report = runDoctor(path.join(projectRoot, ".opencode", "workflow-state.json"))
|
|
348
|
+
|
|
349
|
+
assert.equal(report.summary.error, 0)
|
|
350
|
+
assert.ok(
|
|
351
|
+
report.checks.some(
|
|
352
|
+
(check) => check.label === "workflow schema documents compatibility mirror behavior" && check.ok === true,
|
|
353
|
+
),
|
|
354
|
+
)
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
test("doctor reports contract consistency failures when schema omits compatibility mirror behavior", () => {
|
|
358
|
+
const projectRoot = makeTempProject()
|
|
359
|
+
setupTempRuntime(projectRoot)
|
|
360
|
+
fs.writeFileSync(
|
|
361
|
+
path.join(projectRoot, "context", "core", "workflow-state-schema.md"),
|
|
362
|
+
[
|
|
363
|
+
"# Workflow State Schema",
|
|
364
|
+
"",
|
|
365
|
+
"Modes: `quick`, `migration`, `full`.",
|
|
366
|
+
"Quick stages: `quick_intake`, `quick_plan`, `quick_build`, `quick_verify`, `quick_done`.",
|
|
367
|
+
"Migration stages: `migration_intake`, `migration_baseline`, `migration_strategy`, `migration_upgrade`, `migration_verify`, `migration_done`.",
|
|
368
|
+
"Full stages: `full_intake`, `full_brief`, `full_spec`, `full_architecture`, `full_plan`, `full_implementation`, `full_qa`, `full_done`.",
|
|
369
|
+
"Artifact keys: `task_card`, `brief`, `spec`, `architecture`, `plan`, `migration_report`, `qa_report`, `adr`.",
|
|
370
|
+
"Routing profile keys: `work_intent`, `behavior_delta`, `dominant_uncertainty`, `scope_shape`, `selection_reason`.",
|
|
371
|
+
"Quick approvals: `quick_verified`.",
|
|
372
|
+
"Migration approvals: `baseline_to_strategy`, `strategy_to_upgrade`, `upgrade_to_verify`, `migration_verified`.",
|
|
373
|
+
"Full approvals: `pm_to_ba`, `ba_to_architect`, `architect_to_tech_lead`, `tech_lead_to_fullstack`, `fullstack_to_qa`, `qa_to_done`.",
|
|
374
|
+
"",
|
|
375
|
+
].join("\n"),
|
|
376
|
+
"utf8",
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
const report = runDoctor(path.join(projectRoot, ".opencode", "workflow-state.json"))
|
|
380
|
+
|
|
381
|
+
assert.ok(report.summary.error > 0)
|
|
382
|
+
assert.ok(
|
|
383
|
+
report.checks.some(
|
|
384
|
+
(check) => check.label === "workflow schema documents compatibility mirror behavior" && check.ok === false,
|
|
385
|
+
),
|
|
386
|
+
)
|
|
387
|
+
})
|