@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,280 @@
1
+ const fs = require("fs")
2
+ const path = require("path")
3
+
4
+ function fail(message) {
5
+ const error = new Error(message)
6
+ error.isWorkItemStoreError = true
7
+ throw error
8
+ }
9
+
10
+ function ensureDir(dirPath) {
11
+ fs.mkdirSync(dirPath, { recursive: true })
12
+ }
13
+
14
+ function readJson(filePath, missingMessage) {
15
+ let raw
16
+ try {
17
+ raw = fs.readFileSync(filePath, "utf8")
18
+ } catch (error) {
19
+ if (error.code === "ENOENT" && missingMessage) {
20
+ fail(missingMessage)
21
+ }
22
+ fail(`Unable to read JSON at '${filePath}': ${error.message}`)
23
+ }
24
+
25
+ try {
26
+ return JSON.parse(raw)
27
+ } catch (error) {
28
+ fail(`Malformed JSON at '${filePath}': ${error.message}`)
29
+ }
30
+ }
31
+
32
+ function writeJson(filePath, value) {
33
+ ensureDir(path.dirname(filePath))
34
+ fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8")
35
+ }
36
+
37
+ function sortJsonValue(value) {
38
+ if (Array.isArray(value)) {
39
+ return value.map(sortJsonValue)
40
+ }
41
+
42
+ if (value && typeof value === "object") {
43
+ return Object.keys(value)
44
+ .sort()
45
+ .reduce((sorted, key) => {
46
+ sorted[key] = sortJsonValue(value[key])
47
+ return sorted
48
+ }, {})
49
+ }
50
+
51
+ return value
52
+ }
53
+
54
+ function slugify(value) {
55
+ return String(value)
56
+ .trim()
57
+ .toLowerCase()
58
+ .replace(/[^a-z0-9]+/g, "-")
59
+ .replace(/^-+|-+$/g, "")
60
+ }
61
+
62
+ function deriveWorkItemId(state) {
63
+ if (state && typeof state.work_item_id === "string" && state.work_item_id.length > 0) {
64
+ return state.work_item_id
65
+ }
66
+
67
+ if (!state || typeof state.feature_id !== "string" || state.feature_id.length === 0) {
68
+ fail("work item state must include a non-empty feature_id")
69
+ }
70
+
71
+ return slugify(state.feature_id)
72
+ }
73
+
74
+ function resolvePaths(projectRoot) {
75
+ const opencodeDir = path.join(projectRoot, ".opencode")
76
+ const workItemsDir = path.join(opencodeDir, "work-items")
77
+
78
+ return {
79
+ opencodeDir,
80
+ workflowStatePath: path.join(opencodeDir, "workflow-state.json"),
81
+ workItemsDir,
82
+ indexPath: path.join(workItemsDir, "index.json"),
83
+ }
84
+ }
85
+
86
+ function resolveWorkItemPaths(projectRoot, workItemId) {
87
+ const paths = resolvePaths(projectRoot)
88
+ const workItemDir = path.join(paths.workItemsDir, workItemId)
89
+
90
+ return {
91
+ ...paths,
92
+ workItemDir,
93
+ statePath: path.join(workItemDir, "state.json"),
94
+ relativeStatePath: path.posix.join(".opencode", "work-items", workItemId, "state.json"),
95
+ }
96
+ }
97
+
98
+ function createEmptyIndex() {
99
+ return {
100
+ active_work_item_id: null,
101
+ work_items: [],
102
+ }
103
+ }
104
+
105
+ function bootstrapRuntimeStore(runtimeRoot) {
106
+ const paths = resolvePaths(runtimeRoot)
107
+
108
+ ensureDir(paths.workItemsDir)
109
+
110
+ if (fs.existsSync(paths.indexPath)) {
111
+ return readWorkItemIndex(runtimeRoot)
112
+ }
113
+
114
+ if (fs.existsSync(paths.workflowStatePath)) {
115
+ bootstrapLegacyWorkflowState(runtimeRoot)
116
+ return readWorkItemIndex(runtimeRoot)
117
+ }
118
+
119
+ const index = createEmptyIndex()
120
+ writeWorkItemIndex(runtimeRoot, index)
121
+ return index
122
+ }
123
+
124
+ function readWorkItemIndex(projectRoot) {
125
+ const { indexPath } = resolvePaths(projectRoot)
126
+ return readJson(indexPath, `Work-item index missing at '${indexPath}'`)
127
+ }
128
+
129
+ function writeWorkItemIndex(projectRoot, index) {
130
+ const { indexPath } = resolvePaths(projectRoot)
131
+ writeJson(indexPath, index)
132
+ return index
133
+ }
134
+
135
+ function readWorkItemState(projectRoot, workItemId) {
136
+ const { statePath } = resolveWorkItemPaths(projectRoot, workItemId)
137
+ return readJson(statePath, `Work-item state missing at '${statePath}'`)
138
+ }
139
+
140
+ function writeWorkItemState(projectRoot, workItemId, state) {
141
+ const { statePath } = resolveWorkItemPaths(projectRoot, workItemId)
142
+ const nextState = {
143
+ ...state,
144
+ work_item_id: deriveWorkItemId({
145
+ ...state,
146
+ work_item_id: workItemId,
147
+ }),
148
+ }
149
+
150
+ writeJson(statePath, nextState)
151
+ return nextState
152
+ }
153
+
154
+ function upsertIndexEntry(index, state, workItemId, relativeStatePath) {
155
+ const nextEntry = {
156
+ work_item_id: workItemId,
157
+ feature_id: state.feature_id,
158
+ feature_slug: state.feature_slug,
159
+ mode: state.mode,
160
+ status: state.status,
161
+ state_path: relativeStatePath,
162
+ }
163
+
164
+ const existingIndex = index.work_items.findIndex((entry) => entry.work_item_id === workItemId)
165
+ if (existingIndex === -1) {
166
+ index.work_items.push(nextEntry)
167
+ } else {
168
+ index.work_items[existingIndex] = nextEntry
169
+ }
170
+
171
+ return nextEntry
172
+ }
173
+
174
+ function readLegacyWorkflowState(projectRoot) {
175
+ const { workflowStatePath } = resolvePaths(projectRoot)
176
+ return readJson(workflowStatePath, `Compatibility workflow state missing at '${workflowStatePath}'`)
177
+ }
178
+
179
+ function refreshCompatibilityMirror(projectRoot) {
180
+ const { workflowStatePath } = resolvePaths(projectRoot)
181
+ const index = readWorkItemIndex(projectRoot)
182
+
183
+ if (!index.active_work_item_id) {
184
+ fail("Cannot refresh compatibility mirror without an active work item")
185
+ }
186
+
187
+ const activeState = readWorkItemState(projectRoot, index.active_work_item_id)
188
+ writeJson(workflowStatePath, activeState)
189
+
190
+ return activeState
191
+ }
192
+
193
+ function writeCompatibilityMirror(projectRoot, state) {
194
+ const { workflowStatePath } = resolvePaths(projectRoot)
195
+ writeJson(workflowStatePath, state)
196
+ return state
197
+ }
198
+
199
+ function bootstrapLegacyWorkflowState(projectRoot) {
200
+ const legacyState = readLegacyWorkflowState(projectRoot)
201
+ const workItemId = deriveWorkItemId(legacyState)
202
+ const workItemPaths = resolveWorkItemPaths(projectRoot, workItemId)
203
+
204
+ const index = fs.existsSync(workItemPaths.indexPath)
205
+ ? readWorkItemIndex(projectRoot)
206
+ : createEmptyIndex()
207
+
208
+ const nextState = {
209
+ ...legacyState,
210
+ work_item_id: workItemId,
211
+ }
212
+
213
+ writeWorkItemState(projectRoot, workItemId, nextState)
214
+ upsertIndexEntry(index, nextState, workItemId, workItemPaths.relativeStatePath)
215
+ index.active_work_item_id = workItemId
216
+ writeWorkItemIndex(projectRoot, index)
217
+ refreshCompatibilityMirror(projectRoot)
218
+
219
+ return {
220
+ workItemId,
221
+ index,
222
+ state: nextState,
223
+ }
224
+ }
225
+
226
+ function setActiveWorkItem(projectRoot, workItemId) {
227
+ const index = readWorkItemIndex(projectRoot)
228
+ const entry = index.work_items.find((item) => item.work_item_id === workItemId)
229
+
230
+ if (!entry) {
231
+ fail(`Unknown work item '${workItemId}'`)
232
+ }
233
+
234
+ readWorkItemState(projectRoot, workItemId)
235
+
236
+ index.active_work_item_id = workItemId
237
+ writeWorkItemIndex(projectRoot, index)
238
+
239
+ return index
240
+ }
241
+
242
+ function validateActiveMirror(projectRoot) {
243
+ const { workflowStatePath } = resolvePaths(projectRoot)
244
+ const index = readWorkItemIndex(projectRoot)
245
+
246
+ if (!index.active_work_item_id) {
247
+ fail("Active work item pointer missing")
248
+ }
249
+
250
+ if (!fs.existsSync(workflowStatePath)) {
251
+ fail("Compatibility mirror missing")
252
+ }
253
+
254
+ const mirrorState = readJson(workflowStatePath)
255
+ const activeState = readWorkItemState(projectRoot, index.active_work_item_id)
256
+
257
+ if (JSON.stringify(sortJsonValue(mirrorState)) !== JSON.stringify(sortJsonValue(activeState))) {
258
+ fail("Compatibility mirror diverged from active work item state")
259
+ }
260
+
261
+ return {
262
+ active_work_item_id: index.active_work_item_id,
263
+ mirror_state_path: workflowStatePath,
264
+ }
265
+ }
266
+
267
+ module.exports = {
268
+ bootstrapRuntimeStore,
269
+ bootstrapLegacyWorkflowState,
270
+ deriveWorkItemId,
271
+ readWorkItemIndex,
272
+ readWorkItemState,
273
+ refreshCompatibilityMirror,
274
+ resolveWorkItemPaths,
275
+ setActiveWorkItem,
276
+ validateActiveMirror,
277
+ writeCompatibilityMirror,
278
+ writeWorkItemIndex,
279
+ writeWorkItemState,
280
+ }