@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.
Files changed (178) hide show
  1. package/.opencode/README.md +47 -0
  2. package/.opencode/install-manifest.json +41 -0
  3. package/.opencode/lib/artifact-scaffolder.js +111 -0
  4. package/.opencode/lib/contract-consistency.js +218 -0
  5. package/.opencode/lib/parallel-execution-rules.js +261 -0
  6. package/.opencode/lib/runtime-paths.js +95 -0
  7. package/.opencode/lib/runtime-summary.js +82 -0
  8. package/.opencode/lib/state-guard.js +99 -0
  9. package/.opencode/lib/task-board-rules.js +375 -0
  10. package/.opencode/lib/work-item-store.js +280 -0
  11. package/.opencode/lib/workflow-state-controller.js +1739 -0
  12. package/.opencode/lib/workflow-state-rules.js +331 -0
  13. package/.opencode/opencode.json +93 -0
  14. package/.opencode/package.json +3 -0
  15. package/.opencode/tests/artifact-scaffolder.test.js +733 -0
  16. package/.opencode/tests/multi-work-item-runtime.test.js +369 -0
  17. package/.opencode/tests/parallel-execution-runtime.test.js +259 -0
  18. package/.opencode/tests/session-start-hook.test.js +357 -0
  19. package/.opencode/tests/state-guard.test.js +124 -0
  20. package/.opencode/tests/task-board-rules.test.js +204 -0
  21. package/.opencode/tests/work-item-store.test.js +380 -0
  22. package/.opencode/tests/workflow-behavior.test.js +149 -0
  23. package/.opencode/tests/workflow-contract-consistency.test.js +387 -0
  24. package/.opencode/tests/workflow-state-cli.test.js +1275 -0
  25. package/.opencode/tests/workflow-state-controller.test.js +1038 -0
  26. package/.opencode/work-items/feature-001/state.json +70 -0
  27. package/.opencode/work-items/index.json +13 -0
  28. package/.opencode/workflow-state.js +489 -0
  29. package/.opencode/workflow-state.json +70 -0
  30. package/AGENTS.md +265 -0
  31. package/README.md +401 -0
  32. package/agents/architect-agent.md +63 -0
  33. package/agents/ba-agent.md +56 -0
  34. package/agents/code-reviewer.md +77 -0
  35. package/agents/fullstack-agent.md +115 -0
  36. package/agents/master-orchestrator.md +60 -0
  37. package/agents/pm-agent.md +56 -0
  38. package/agents/qa-agent.md +124 -0
  39. package/agents/tech-lead-agent.md +60 -0
  40. package/assets/install-bundle/README.md +7 -0
  41. package/assets/install-bundle/opencode/README.md +11 -0
  42. package/assets/install-bundle/opencode/agents/ArchitectAgent.md +63 -0
  43. package/assets/install-bundle/opencode/agents/BAAgent.md +56 -0
  44. package/assets/install-bundle/opencode/agents/CodeReviewer.md +77 -0
  45. package/assets/install-bundle/opencode/agents/FullstackAgent.md +115 -0
  46. package/assets/install-bundle/opencode/agents/MasterOrchestrator.md +60 -0
  47. package/assets/install-bundle/opencode/agents/PMAgent.md +56 -0
  48. package/assets/install-bundle/opencode/agents/QAAgent.md +124 -0
  49. package/assets/install-bundle/opencode/agents/TechLeadAgent.md +60 -0
  50. package/assets/install-bundle/opencode/commands/brainstorm.md +44 -0
  51. package/assets/install-bundle/opencode/commands/delivery.md +45 -0
  52. package/assets/install-bundle/opencode/commands/execute-plan.md +44 -0
  53. package/assets/install-bundle/opencode/commands/migrate.md +61 -0
  54. package/assets/install-bundle/opencode/commands/quick-task.md +45 -0
  55. package/assets/install-bundle/opencode/commands/task.md +46 -0
  56. package/assets/install-bundle/opencode/commands/write-plan.md +50 -0
  57. package/assets/install-bundle/opencode/context/core/lane-selection.md +54 -0
  58. package/assets/install-bundle/opencode/skills/brainstorming/SKILL.md +51 -0
  59. package/assets/install-bundle/opencode/skills/code-review/SKILL.md +48 -0
  60. package/assets/install-bundle/opencode/skills/subagent-driven-development/SKILL.md +79 -0
  61. package/assets/install-bundle/opencode/skills/systematic-debugging/SKILL.md +61 -0
  62. package/assets/install-bundle/opencode/skills/test-driven-development/SKILL.md +48 -0
  63. package/assets/install-bundle/opencode/skills/using-skills/SKILL.md +39 -0
  64. package/assets/install-bundle/opencode/skills/verification-before-completion/SKILL.md +137 -0
  65. package/assets/install-bundle/opencode/skills/writing-plans/SKILL.md +68 -0
  66. package/assets/install-bundle/opencode/skills/writing-specs/SKILL.md +47 -0
  67. package/assets/opencode.json.template +11 -0
  68. package/assets/openkit-install.json.template +19 -0
  69. package/bin/openkit.js +9 -0
  70. package/commands/brainstorm.md +44 -0
  71. package/commands/delivery.md +45 -0
  72. package/commands/execute-plan.md +44 -0
  73. package/commands/migrate.md +61 -0
  74. package/commands/quick-task.md +45 -0
  75. package/commands/task.md +46 -0
  76. package/commands/write-plan.md +50 -0
  77. package/context/core/approval-gates.md +146 -0
  78. package/context/core/code-quality.md +42 -0
  79. package/context/core/issue-routing.md +85 -0
  80. package/context/core/lane-selection.md +54 -0
  81. package/context/core/project-config.md +143 -0
  82. package/context/core/session-resume.md +85 -0
  83. package/context/core/workflow-state-schema.md +224 -0
  84. package/context/core/workflow.md +442 -0
  85. package/context/navigation.md +94 -0
  86. package/docs/adr/README.md +6 -0
  87. package/docs/architecture/2026-03-20-task-intake-dashboard.md +54 -0
  88. package/docs/architecture/README.md +7 -0
  89. package/docs/briefs/2026-03-20-task-intake-dashboard.md +48 -0
  90. package/docs/briefs/README.md +7 -0
  91. package/docs/governance/README.md +25 -0
  92. package/docs/governance/adr-policy.md +27 -0
  93. package/docs/governance/definition-of-done.md +17 -0
  94. package/docs/governance/naming-conventions.md +21 -0
  95. package/docs/governance/severity-levels.md +12 -0
  96. package/docs/maintainer/README.md +51 -0
  97. package/docs/operations/README.md +79 -0
  98. package/docs/operations/internal-records/2026-03-24-release-checklist.md +79 -0
  99. package/docs/operations/internal-records/2026-03-24-simplified-install-ux.md +36 -0
  100. package/docs/operations/internal-records/README.md +18 -0
  101. package/docs/operations/runbooks/README.md +23 -0
  102. package/docs/operations/runbooks/openkit-daily-usage.md +288 -0
  103. package/docs/operations/runbooks/workflow-state-smoke-tests.md +302 -0
  104. package/docs/operator/README.md +50 -0
  105. package/docs/plans/2026-03-20-task-intake-dashboard.md +49 -0
  106. package/docs/plans/2026-03-21-openkit-full-delivery-multi-task-runtime.md +521 -0
  107. package/docs/plans/2026-03-23-openkit-global-install-runtime.md +157 -0
  108. package/docs/plans/README.md +7 -0
  109. package/docs/qa/2026-03-20-task-intake-dashboard.md +41 -0
  110. package/docs/qa/README.md +7 -0
  111. package/docs/specs/2026-03-20-task-intake-dashboard.md +50 -0
  112. package/docs/specs/2026-03-21-openkit-full-delivery-multi-task-runtime.md +462 -0
  113. package/docs/specs/README.md +7 -0
  114. package/docs/templates/README.md +36 -0
  115. package/docs/templates/adr-template.md +18 -0
  116. package/docs/templates/architecture-template.md +31 -0
  117. package/docs/templates/implementation-plan-template.md +32 -0
  118. package/docs/templates/migration-baseline-checklist.md +48 -0
  119. package/docs/templates/migration-plan-template.md +52 -0
  120. package/docs/templates/migration-report-template.md +74 -0
  121. package/docs/templates/migration-verify-checklist.md +39 -0
  122. package/docs/templates/product-brief-template.md +32 -0
  123. package/docs/templates/qa-report-template.md +37 -0
  124. package/docs/templates/quick-task-template.md +36 -0
  125. package/docs/templates/spec-template.md +31 -0
  126. package/hooks/hooks.json +16 -0
  127. package/hooks/session-start +162 -0
  128. package/package.json +24 -0
  129. package/registry.json +328 -0
  130. package/skills/brainstorming/SKILL.md +51 -0
  131. package/skills/code-review/SKILL.md +48 -0
  132. package/skills/subagent-driven-development/SKILL.md +79 -0
  133. package/skills/systematic-debugging/SKILL.md +61 -0
  134. package/skills/test-driven-development/SKILL.md +48 -0
  135. package/skills/using-skills/SKILL.md +39 -0
  136. package/skills/verification-before-completion/SKILL.md +137 -0
  137. package/skills/writing-plans/SKILL.md +68 -0
  138. package/skills/writing-specs/SKILL.md +47 -0
  139. package/src/audit/vietnamese-detection.js +259 -0
  140. package/src/cli/commands/detect-vietnamese.js +24 -0
  141. package/src/cli/commands/doctor.js +33 -0
  142. package/src/cli/commands/help.js +33 -0
  143. package/src/cli/commands/init.js +25 -0
  144. package/src/cli/commands/install-global.js +26 -0
  145. package/src/cli/commands/install.js +25 -0
  146. package/src/cli/commands/run.js +63 -0
  147. package/src/cli/commands/uninstall.js +32 -0
  148. package/src/cli/commands/upgrade.js +25 -0
  149. package/src/cli/conflict-output.js +19 -0
  150. package/src/cli/index.js +56 -0
  151. package/src/global/doctor.js +101 -0
  152. package/src/global/ensure-install.js +32 -0
  153. package/src/global/install-state.js +73 -0
  154. package/src/global/launcher.js +51 -0
  155. package/src/global/materialize.js +123 -0
  156. package/src/global/paths.js +85 -0
  157. package/src/global/uninstall.js +25 -0
  158. package/src/global/workspace-state.js +63 -0
  159. package/src/install/asset-manifest.js +284 -0
  160. package/src/install/conflicts.js +43 -0
  161. package/src/install/discovery.js +138 -0
  162. package/src/install/install-state.js +136 -0
  163. package/src/install/materialize.js +158 -0
  164. package/src/install/merge-policy.js +145 -0
  165. package/src/runtime/doctor.js +281 -0
  166. package/src/runtime/launcher.js +49 -0
  167. package/src/runtime/opencode-layering.js +135 -0
  168. package/src/runtime/openkit-managed-summary.js +27 -0
  169. package/tests/cli/openkit-cli.test.js +417 -0
  170. package/tests/global/doctor.test.js +130 -0
  171. package/tests/global/ensure-install.test.js +105 -0
  172. package/tests/install/discovery.test.js +124 -0
  173. package/tests/install/install-state.test.js +346 -0
  174. package/tests/install/materialize.test.js +244 -0
  175. package/tests/install/merge-policy.test.js +177 -0
  176. package/tests/runtime/doctor.test.js +430 -0
  177. package/tests/runtime/launcher.test.js +230 -0
  178. package/tests/runtime/module-boundary.test.js +16 -0
@@ -0,0 +1,70 @@
1
+ {
2
+ "feature_id": "FEATURE-001",
3
+ "feature_slug": "task-intake-dashboard",
4
+ "mode": "full",
5
+ "mode_reason": "Feature-sized workflow example with full artifact chain and approvals",
6
+ "routing_profile": {
7
+ "work_intent": "feature",
8
+ "behavior_delta": "extend",
9
+ "dominant_uncertainty": "product",
10
+ "scope_shape": "cross_boundary",
11
+ "selection_reason": "Feature-sized workflow example with full artifact chain and approvals"
12
+ },
13
+ "current_stage": "full_done",
14
+ "status": "done",
15
+ "current_owner": "MasterOrchestrator",
16
+ "artifacts": {
17
+ "task_card": null,
18
+ "brief": "docs/briefs/2026-03-20-task-intake-dashboard.md",
19
+ "spec": "docs/specs/2026-03-20-task-intake-dashboard.md",
20
+ "architecture": "docs/architecture/2026-03-20-task-intake-dashboard.md",
21
+ "plan": "docs/plans/2026-03-20-task-intake-dashboard.md",
22
+ "migration_report": null,
23
+ "qa_report": "docs/qa/2026-03-20-task-intake-dashboard.md",
24
+ "adr": []
25
+ },
26
+ "approvals": {
27
+ "pm_to_ba": {
28
+ "status": "approved",
29
+ "approved_by": "user",
30
+ "approved_at": "2026-03-20",
31
+ "notes": "Golden path brief approved"
32
+ },
33
+ "ba_to_architect": {
34
+ "status": "approved",
35
+ "approved_by": "user",
36
+ "approved_at": "2026-03-20",
37
+ "notes": "Golden path spec approved"
38
+ },
39
+ "architect_to_tech_lead": {
40
+ "status": "approved",
41
+ "approved_by": "user",
42
+ "approved_at": "2026-03-20",
43
+ "notes": "Golden path architecture approved"
44
+ },
45
+ "tech_lead_to_fullstack": {
46
+ "status": "approved",
47
+ "approved_by": "user",
48
+ "approved_at": "2026-03-20",
49
+ "notes": "Golden path plan approved"
50
+ },
51
+ "fullstack_to_qa": {
52
+ "status": "approved",
53
+ "approved_by": "system",
54
+ "approved_at": "2026-03-20",
55
+ "notes": "Documentation-only golden path prepared for QA"
56
+ },
57
+ "qa_to_done": {
58
+ "status": "approved",
59
+ "approved_by": "user",
60
+ "approved_at": "2026-03-20",
61
+ "notes": "Golden path QA report passed"
62
+ }
63
+ },
64
+ "issues": [],
65
+ "retry_count": 0,
66
+ "escalated_from": null,
67
+ "escalation_reason": null,
68
+ "updated_at": "2026-03-20",
69
+ "work_item_id": "feature-001"
70
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "active_work_item_id": "feature-001",
3
+ "work_items": [
4
+ {
5
+ "work_item_id": "feature-001",
6
+ "feature_id": "FEATURE-001",
7
+ "feature_slug": "task-intake-dashboard",
8
+ "mode": "full",
9
+ "status": "done",
10
+ "state_path": ".opencode/work-items/feature-001/state.json"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,489 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs")
4
+ const path = require("path")
5
+
6
+ const {
7
+ ESCALATION_RETRY_THRESHOLD,
8
+ advanceStage,
9
+ clearIssues,
10
+ claimTask,
11
+ createTask,
12
+ createWorkItem,
13
+ getProfile,
14
+ getRuntimeStatus,
15
+ getVersionInfo,
16
+ linkArtifact,
17
+ listTasks,
18
+ listWorkItems,
19
+ listProfiles,
20
+ reassignTask,
21
+ recordIssue,
22
+ releaseTask,
23
+ resolveStatePath,
24
+ routeRework,
25
+ runDoctor,
26
+ scaffoldAndLinkArtifact,
27
+ selectActiveWorkItem,
28
+ assignQaOwner,
29
+ setRoutingProfile,
30
+ setTaskStatus,
31
+ setApproval,
32
+ showState,
33
+ showWorkItemState,
34
+ syncInstallManifest,
35
+ startFeature,
36
+ startTask,
37
+ validateWorkItemBoard,
38
+ validateState,
39
+ } = require("./lib/workflow-state-controller")
40
+ const { resolveWorkItemPaths, validateActiveMirror } = require("./lib/work-item-store")
41
+ const { getRuntimeContext } = require("./lib/runtime-summary")
42
+
43
+ function printUsage() {
44
+ console.log(`Usage:
45
+ node .opencode/workflow-state.js [--state <path>] show
46
+ node .opencode/workflow-state.js [--state <path>] status
47
+ node .opencode/workflow-state.js [--state <path>] doctor
48
+ node .opencode/workflow-state.js [--state <path>] version
49
+ node .opencode/workflow-state.js [--state <path>] profiles
50
+ node .opencode/workflow-state.js [--state <path>] show-profile <name>
51
+ node .opencode/workflow-state.js [--state <path>] sync-install-manifest <name>
52
+ node .opencode/workflow-state.js [--state <path>] validate
53
+ node .opencode/workflow-state.js [--state <path>] start-feature <feature_id> <feature_slug>
54
+ node .opencode/workflow-state.js [--state <path>] start-task <mode> <feature_id> <feature_slug> <mode_reason>
55
+ node .opencode/workflow-state.js [--state <path>] create-work-item <mode> <feature_id> <feature_slug> <mode_reason>
56
+ node .opencode/workflow-state.js [--state <path>] list-work-items
57
+ node .opencode/workflow-state.js [--state <path>] show-work-item <work_item_id>
58
+ node .opencode/workflow-state.js [--state <path>] activate-work-item <work_item_id>
59
+ node .opencode/workflow-state.js [--state <path>] advance-stage <stage>
60
+ node .opencode/workflow-state.js [--state <path>] set-approval <gate> <status> [approved_by] [approved_at] [notes]
61
+ node .opencode/workflow-state.js [--state <path>] link-artifact <kind> <path>
62
+ node .opencode/workflow-state.js [--state <path>] scaffold-artifact <task_card|plan|migration_report> <slug>
63
+ node .opencode/workflow-state.js [--state <path>] set-routing-profile <work_intent> <behavior_delta> <dominant_uncertainty> <scope_shape> <selection_reason>
64
+ node .opencode/workflow-state.js [--state <path>] list-tasks <work_item_id>
65
+ node .opencode/workflow-state.js [--state <path>] create-task <work_item_id> <task_id> <title> <kind> [branch] [worktree_path]
66
+ node .opencode/workflow-state.js [--state <path>] claim-task <work_item_id> <task_id> <owner> <requested_by>
67
+ node .opencode/workflow-state.js [--state <path>] release-task <work_item_id> <task_id> <requested_by>
68
+ node .opencode/workflow-state.js [--state <path>] reassign-task <work_item_id> <task_id> <owner> <requested_by>
69
+ node .opencode/workflow-state.js [--state <path>] assign-qa-owner <work_item_id> <task_id> <qa_owner> <requested_by>
70
+ node .opencode/workflow-state.js [--state <path>] set-task-status <work_item_id> <task_id> <status>
71
+ node .opencode/workflow-state.js [--state <path>] validate-work-item-board <work_item_id>
72
+ node .opencode/workflow-state.js [--state <path>] record-issue <issue_id> <title> <type> <severity> <rooted_in> <recommended_owner> <evidence> <artifact_refs>
73
+ node .opencode/workflow-state.js [--state <path>] clear-issues
74
+ node .opencode/workflow-state.js [--state <path>] route-rework <issue_type> [repeat_failed_fix=true|false]`)
75
+ }
76
+
77
+ function parseGlobalFlags(argv) {
78
+ const args = [...argv]
79
+ let statePath = null
80
+
81
+ while (args[0] === "--state") {
82
+ args.shift()
83
+ if (!args[0]) {
84
+ throw new Error("Missing value for --state")
85
+ }
86
+ statePath = args.shift()
87
+ }
88
+
89
+ return { args, statePath }
90
+ }
91
+
92
+ function printState(prefix, result) {
93
+ console.log(prefix)
94
+ console.log(`State file: ${result.statePath}`)
95
+ printRuntimeTaskContext(result.runtimeContext)
96
+ console.log(JSON.stringify(result.state, null, 2))
97
+ }
98
+
99
+ function printRuntimeTaskContext(context) {
100
+ if (!context) {
101
+ return
102
+ }
103
+
104
+ if (context.activeWorkItemId) {
105
+ console.log(`active work item id: ${context.activeWorkItemId}`)
106
+ }
107
+
108
+ if (typeof context.workItemCount === "number") {
109
+ console.log(`work items tracked: ${context.workItemCount}`)
110
+ }
111
+
112
+ if (context.taskBoardSummary) {
113
+ console.log(
114
+ `task board: ${context.taskBoardSummary.total} tasks | ready ${context.taskBoardSummary.ready} | active ${context.taskBoardSummary.active}`,
115
+ )
116
+ if (context.taskBoardSummary.activeTasks.length > 0) {
117
+ console.log(`active tasks: ${context.taskBoardSummary.activeTasks.join("; ")}`)
118
+ }
119
+ }
120
+ }
121
+
122
+ function printRuntimeStatus(runtime) {
123
+ console.log("OpenKit runtime status:")
124
+ console.log(`project root: ${runtime.projectRoot}`)
125
+ console.log(`kit: ${runtime.kitName} v${runtime.kitVersion}`)
126
+ console.log(`entry agent: ${runtime.entryAgent}`)
127
+ console.log(`active profile: ${runtime.activeProfile}`)
128
+ console.log(`registry: ${runtime.registryPath}`)
129
+ console.log(`install manifest: ${runtime.installManifestPath}`)
130
+ console.log(`state file: ${runtime.statePath}`)
131
+ console.log(`mode: ${runtime.state.mode}`)
132
+ console.log(`stage: ${runtime.state.current_stage}`)
133
+ console.log(`status: ${runtime.state.status}`)
134
+ console.log(`owner: ${runtime.state.current_owner}`)
135
+ if (runtime.state.feature_id && runtime.state.feature_slug) {
136
+ console.log(`work item: ${runtime.state.feature_id} (${runtime.state.feature_slug})`)
137
+ }
138
+ printRuntimeTaskContext(runtime.runtimeContext)
139
+ }
140
+
141
+ function printDoctorReport(report) {
142
+ console.log("OpenKit doctor:")
143
+ console.log(`active profile: ${report.runtime.activeProfile}`)
144
+ console.log(`registry: ${report.runtime.registryPath}`)
145
+ console.log(`install manifest: ${report.runtime.installManifestPath}`)
146
+ printRuntimeTaskContext(report.runtime.runtimeContext)
147
+ for (const check of report.checks) {
148
+ console.log(`[${check.ok ? "ok" : "error"}] ${check.label}`)
149
+ }
150
+ console.log(
151
+ `Summary: ${report.summary.ok} ok, ${report.summary.warn} warn, ${report.summary.error} error`,
152
+ )
153
+ }
154
+
155
+ function printProfiles(profiles) {
156
+ console.log("OpenKit profiles:")
157
+ for (const profile of profiles) {
158
+ const marker = profile.defaultForRepository ? "*" : " "
159
+ console.log(`${marker} ${profile.name} - ${profile.description}`)
160
+ }
161
+ }
162
+
163
+ function printProfile(profile) {
164
+ console.log(`Profile: ${profile.name}`)
165
+ console.log(`default: ${profile.defaultForRepository ? "yes" : "no"}`)
166
+ console.log(`components: ${profile.componentRefs.join(", ")}`)
167
+ }
168
+
169
+ function printVersion(info) {
170
+ console.log(`OpenKit version: ${info.kitVersion}`)
171
+ console.log(`active profile: ${info.activeProfile}`)
172
+ }
173
+
174
+ function printWorkItems(result) {
175
+ console.log(`Active work item: ${result.index.active_work_item_id ?? "none"}`)
176
+ for (const item of result.workItems) {
177
+ const marker = item.work_item_id === result.index.active_work_item_id ? "*" : " "
178
+ console.log(`${marker} ${item.work_item_id} | ${item.feature_id} | ${item.mode} | ${item.status}`)
179
+ }
180
+ }
181
+
182
+ function printWorkItem(result) {
183
+ console.log(`Work item: ${result.state.work_item_id}`)
184
+ console.log(`feature: ${result.state.feature_id} (${result.state.feature_slug})`)
185
+ console.log(`mode: ${result.state.mode}`)
186
+ console.log(`stage: ${result.state.current_stage}`)
187
+ console.log(`status: ${result.state.status}`)
188
+ }
189
+
190
+ function printTasks(result) {
191
+ console.log(`Tasks for ${result.workItemId}:`)
192
+ for (const task of result.tasks) {
193
+ console.log(`${task.task_id} | ${task.status} | ${task.kind} | ${task.title}`)
194
+ }
195
+ }
196
+
197
+ function toBoolean(value) {
198
+ return value === "true"
199
+ }
200
+
201
+ function requireArgument(value, placeholder, command) {
202
+ if (typeof value !== "string" || value.length === 0) {
203
+ throw new Error(`${command} requires ${placeholder}`)
204
+ }
205
+
206
+ return value
207
+ }
208
+
209
+ function enrichStateResult(result, statePath) {
210
+ const runtimeRoot = path.dirname(path.dirname(statePath ?? result.statePath))
211
+ return {
212
+ ...result,
213
+ runtimeContext: getRuntimeContext(runtimeRoot, result.state),
214
+ }
215
+ }
216
+
217
+ function extendDoctorReport(report, statePath) {
218
+ const runtimeRoot = path.dirname(path.dirname(statePath))
219
+ const checks = [...report.checks]
220
+ const runtimeContext = getRuntimeContext(runtimeRoot, report.runtime.state)
221
+ const activeWorkItemId = runtimeContext.activeWorkItemId
222
+ const indexPath = path.join(runtimeRoot, ".opencode", "work-items", "index.json")
223
+ const index = fs.existsSync(indexPath) ? JSON.parse(fs.readFileSync(indexPath, "utf8")) : null
224
+ const activeWorkItem = index?.work_items?.find((entry) => entry.work_item_id === activeWorkItemId) ?? null
225
+ let activePointerOk = !index || !activeWorkItemId
226
+ let mirrorOk = !index || !activeWorkItemId
227
+ let boardOk = true
228
+
229
+ if (index && activeWorkItemId) {
230
+ const activeStatePath = resolveWorkItemPaths(runtimeRoot, activeWorkItemId).statePath
231
+ activePointerOk = fs.existsSync(activeStatePath)
232
+
233
+ try {
234
+ validateActiveMirror(runtimeRoot)
235
+ mirrorOk = true
236
+ } catch (_error) {
237
+ mirrorOk = false
238
+ }
239
+ }
240
+
241
+ if (report.runtime.state?.mode === "full" && report.runtime.state?.work_item_id) {
242
+ boardOk = report.runtime.state.current_stage === "full_implementation" || report.runtime.state.current_stage === "full_qa"
243
+ ? runtimeContext.taskBoardPresent
244
+ : true
245
+ } else if (!report.runtime.state && activeWorkItem?.mode === "full") {
246
+ try {
247
+ validateWorkItemBoard(activeWorkItemId, statePath)
248
+ boardOk = true
249
+ } catch (_error) {
250
+ boardOk = false
251
+ }
252
+ }
253
+
254
+ checks.push(
255
+ { label: "active work item pointer resolves to stored state", ok: activePointerOk },
256
+ { label: "compatibility mirror matches active work item state", ok: mirrorOk },
257
+ { label: "active work item task board is valid", ok: boardOk },
258
+ )
259
+
260
+ const summary = checks.reduce(
261
+ (counts, check) => {
262
+ if (check.ok) {
263
+ counts.ok += 1
264
+ } else {
265
+ counts.error += 1
266
+ }
267
+ return counts
268
+ },
269
+ { ok: 0, warn: 0, error: 0 },
270
+ )
271
+
272
+ return {
273
+ ...report,
274
+ runtime: {
275
+ ...report.runtime,
276
+ runtimeContext,
277
+ },
278
+ checks,
279
+ summary,
280
+ }
281
+ }
282
+
283
+ async function main() {
284
+ const { args, statePath } = parseGlobalFlags(process.argv.slice(2))
285
+ const [command, ...rest] = args
286
+
287
+ if (!command) {
288
+ printUsage()
289
+ process.exit(1)
290
+ }
291
+
292
+ let result
293
+ switch (command) {
294
+ case "show":
295
+ result = enrichStateResult(showState(statePath), statePath)
296
+ printState("Workflow state:", result)
297
+ return
298
+ case "status":
299
+ result = getRuntimeStatus(statePath)
300
+ result.runtimeContext = getRuntimeContext(result.runtimeRoot, result.state)
301
+ printRuntimeStatus(result)
302
+ return
303
+ case "doctor":
304
+ result = extendDoctorReport(runDoctor(statePath), resolveStatePath(statePath))
305
+ printDoctorReport(result)
306
+ process.exit(result.summary.error > 0 ? 1 : 0)
307
+ return
308
+ case "version":
309
+ result = getVersionInfo(statePath)
310
+ printVersion(result)
311
+ return
312
+ case "profiles":
313
+ result = listProfiles(statePath)
314
+ printProfiles(result)
315
+ return
316
+ case "show-profile":
317
+ result = getProfile(rest[0], statePath)
318
+ printProfile(result)
319
+ return
320
+ case "sync-install-manifest":
321
+ result = syncInstallManifest(rest[0], statePath)
322
+ console.log(`Updated install manifest profile to '${result.profile.name}'`)
323
+ console.log(`Install manifest: ${result.installManifestPath}`)
324
+ return
325
+ case "validate":
326
+ result = validateState(statePath)
327
+ console.log(`Workflow state is valid: ${result.statePath}`)
328
+ return
329
+ case "start-feature":
330
+ result = startFeature(rest[0], rest[1], statePath)
331
+ console.log(`Started feature ${rest[0]} (${rest[1]})`)
332
+ console.log(`State file: ${result.statePath}`)
333
+ return
334
+ case "start-task":
335
+ result = startTask(rest[0], rest[1], rest[2], rest.slice(3).join(" "), statePath)
336
+ console.log(`Started ${result.state.mode} task ${rest[1]} (${rest[2]})`)
337
+ console.log(`State file: ${result.statePath}`)
338
+ return
339
+ case "create-work-item":
340
+ result = createWorkItem(rest[0], rest[1], rest[2], rest.slice(3).join(" "), statePath)
341
+ console.log(`Created ${result.state.mode} work item ${rest[1]} (${rest[2]})`)
342
+ console.log(`State file: ${result.statePath}`)
343
+ return
344
+ case "list-work-items":
345
+ result = listWorkItems(statePath)
346
+ printWorkItems(result)
347
+ return
348
+ case "show-work-item":
349
+ result = showWorkItemState(rest[0], statePath)
350
+ printWorkItem(result)
351
+ return
352
+ case "activate-work-item":
353
+ result = selectActiveWorkItem(rest[0], statePath)
354
+ console.log(`Activated work item '${result.state.work_item_id}'`)
355
+ console.log(`State file: ${result.statePath}`)
356
+ return
357
+ case "advance-stage":
358
+ result = advanceStage(rest[0], statePath)
359
+ console.log(`Advanced workflow to stage '${result.state.current_stage}'`)
360
+ console.log(`State file: ${result.statePath}`)
361
+ return
362
+ case "set-approval":
363
+ result = setApproval(rest[0], rest[1], rest[2], rest[3], rest[4], statePath)
364
+ console.log(`Updated approval gate '${rest[0]}' to '${rest[1]}'`)
365
+ console.log(`State file: ${result.statePath}`)
366
+ return
367
+ case "link-artifact":
368
+ result = linkArtifact(rest[0], rest[1], statePath)
369
+ console.log(`Linked artifact '${rest[0]}' -> '${rest[1]}'`)
370
+ console.log(`State file: ${result.statePath}`)
371
+ return
372
+ case "scaffold-artifact":
373
+ result = scaffoldAndLinkArtifact(rest[0], rest[1], statePath)
374
+ console.log(`Created artifact '${rest[0]}' at '${result.artifactPath}'`)
375
+ console.log(`State file: ${result.statePath}`)
376
+ return
377
+ case "set-routing-profile":
378
+ result = setRoutingProfile(rest[0], rest[1], rest[2], rest[3], rest.slice(4).join(" "), statePath)
379
+ console.log(`Updated routing profile for mode '${result.state.mode}'`)
380
+ console.log(`State file: ${result.statePath}`)
381
+ return
382
+ case "list-tasks":
383
+ result = listTasks(rest[0], statePath)
384
+ printTasks(result)
385
+ return
386
+ case "create-task":
387
+ result = createTask(
388
+ rest[0],
389
+ {
390
+ task_id: rest[1],
391
+ title: rest[2],
392
+ kind: rest[3],
393
+ ...(rest[4] && rest[5]
394
+ ? {
395
+ worktree_metadata: {
396
+ task_id: rest[1],
397
+ branch: rest[4],
398
+ worktree_path: rest[5],
399
+ },
400
+ }
401
+ : {}),
402
+ },
403
+ statePath,
404
+ )
405
+ console.log(`Created task '${rest[1]}' on work item '${rest[0]}'`)
406
+ console.log(`State file: ${result.statePath}`)
407
+ return
408
+ case "claim-task":
409
+ result = claimTask(rest[0], rest[1], rest[2], statePath, {
410
+ requestedBy: requireArgument(rest[3], "<requested_by>", "claim-task"),
411
+ })
412
+ console.log(`Claimed task '${rest[1]}' for '${rest[2]}'`)
413
+ console.log(`State file: ${result.statePath}`)
414
+ return
415
+ case "release-task":
416
+ result = releaseTask(rest[0], rest[1], statePath, {
417
+ requestedBy: requireArgument(rest[2], "<requested_by>", "release-task"),
418
+ })
419
+ console.log(`Released task '${rest[1]}'`)
420
+ console.log(`State file: ${result.statePath}`)
421
+ return
422
+ case "reassign-task":
423
+ result = reassignTask(rest[0], rest[1], rest[2], statePath, {
424
+ requestedBy: requireArgument(rest[3], "<requested_by>", "reassign-task"),
425
+ })
426
+ console.log(`Reassigned task '${rest[1]}' to '${rest[2]}'`)
427
+ console.log(`State file: ${result.statePath}`)
428
+ return
429
+ case "assign-qa-owner":
430
+ result = assignQaOwner(rest[0], rest[1], rest[2], statePath, {
431
+ requestedBy: requireArgument(rest[3], "<requested_by>", "assign-qa-owner"),
432
+ })
433
+ console.log(`Assigned QA owner '${rest[2]}' to task '${rest[1]}'`)
434
+ console.log(`State file: ${result.statePath}`)
435
+ return
436
+ case "set-task-status":
437
+ result = setTaskStatus(rest[0], rest[1], rest[2], statePath)
438
+ console.log(`Updated task '${rest[1]}' to '${rest[2]}'`)
439
+ console.log(`State file: ${result.statePath}`)
440
+ return
441
+ case "validate-work-item-board":
442
+ result = validateWorkItemBoard(rest[0], statePath)
443
+ console.log(`Task board is valid for work item '${result.workItemId}'`)
444
+ console.log(`State file: ${result.statePath}`)
445
+ return
446
+ case "record-issue":
447
+ result = recordIssue(
448
+ {
449
+ issue_id: rest[0],
450
+ title: rest[1],
451
+ type: rest[2],
452
+ severity: rest[3],
453
+ rooted_in: rest[4],
454
+ recommended_owner: rest[5],
455
+ evidence: rest[6],
456
+ artifact_refs: rest[7],
457
+ },
458
+ statePath,
459
+ )
460
+ console.log(`Recorded issue '${rest[0]}'`)
461
+ console.log(`State file: ${result.statePath}`)
462
+ return
463
+ case "clear-issues":
464
+ result = clearIssues(statePath)
465
+ console.log("Cleared workflow issues")
466
+ console.log(`State file: ${result.statePath}`)
467
+ return
468
+ case "route-rework":
469
+ result = routeRework(rest[0], toBoolean(rest[1] ?? "false"), statePath)
470
+ console.log(`Routed rework for '${rest[0]}' to stage '${result.state.current_stage}'`)
471
+ if (result.state.retry_count >= ESCALATION_RETRY_THRESHOLD) {
472
+ console.log(
473
+ `Escalation threshold reached: retry_count is at or above ${ESCALATION_RETRY_THRESHOLD}`,
474
+ )
475
+ }
476
+ console.log(`State file: ${result.statePath}`)
477
+ return
478
+ case "help":
479
+ printUsage()
480
+ return
481
+ default:
482
+ throw new Error(`Unknown command '${command}'`)
483
+ }
484
+ }
485
+
486
+ main().catch((error) => {
487
+ console.error(error.message)
488
+ process.exit(1)
489
+ })
@@ -0,0 +1,70 @@
1
+ {
2
+ "feature_id": "FEATURE-001",
3
+ "feature_slug": "task-intake-dashboard",
4
+ "mode": "full",
5
+ "mode_reason": "Feature-sized workflow example with full artifact chain and approvals",
6
+ "routing_profile": {
7
+ "work_intent": "feature",
8
+ "behavior_delta": "extend",
9
+ "dominant_uncertainty": "product",
10
+ "scope_shape": "cross_boundary",
11
+ "selection_reason": "Feature-sized workflow example with full artifact chain and approvals"
12
+ },
13
+ "current_stage": "full_done",
14
+ "status": "done",
15
+ "current_owner": "MasterOrchestrator",
16
+ "artifacts": {
17
+ "task_card": null,
18
+ "brief": "docs/briefs/2026-03-20-task-intake-dashboard.md",
19
+ "spec": "docs/specs/2026-03-20-task-intake-dashboard.md",
20
+ "architecture": "docs/architecture/2026-03-20-task-intake-dashboard.md",
21
+ "plan": "docs/plans/2026-03-20-task-intake-dashboard.md",
22
+ "migration_report": null,
23
+ "qa_report": "docs/qa/2026-03-20-task-intake-dashboard.md",
24
+ "adr": []
25
+ },
26
+ "approvals": {
27
+ "pm_to_ba": {
28
+ "status": "approved",
29
+ "approved_by": "user",
30
+ "approved_at": "2026-03-20",
31
+ "notes": "Golden path brief approved"
32
+ },
33
+ "ba_to_architect": {
34
+ "status": "approved",
35
+ "approved_by": "user",
36
+ "approved_at": "2026-03-20",
37
+ "notes": "Golden path spec approved"
38
+ },
39
+ "architect_to_tech_lead": {
40
+ "status": "approved",
41
+ "approved_by": "user",
42
+ "approved_at": "2026-03-20",
43
+ "notes": "Golden path architecture approved"
44
+ },
45
+ "tech_lead_to_fullstack": {
46
+ "status": "approved",
47
+ "approved_by": "user",
48
+ "approved_at": "2026-03-20",
49
+ "notes": "Golden path plan approved"
50
+ },
51
+ "fullstack_to_qa": {
52
+ "status": "approved",
53
+ "approved_by": "system",
54
+ "approved_at": "2026-03-20",
55
+ "notes": "Documentation-only golden path prepared for QA"
56
+ },
57
+ "qa_to_done": {
58
+ "status": "approved",
59
+ "approved_by": "user",
60
+ "approved_at": "2026-03-20",
61
+ "notes": "Golden path QA report passed"
62
+ }
63
+ },
64
+ "issues": [],
65
+ "retry_count": 0,
66
+ "escalated_from": null,
67
+ "escalation_reason": null,
68
+ "updated_at": "2026-03-20",
69
+ "work_item_id": "feature-001"
70
+ }