@aipper/aiws 0.0.29 → 0.0.30

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 (278) hide show
  1. package/bin/aiws.js +2 -2
  2. package/dist/aiws-package.d.ts +4 -0
  3. package/dist/aiws-package.js +11 -0
  4. package/dist/aiws-package.js.map +1 -0
  5. package/dist/aiws-paths.d.ts +48 -0
  6. package/dist/aiws-paths.js +129 -0
  7. package/dist/aiws-paths.js.map +1 -0
  8. package/dist/backup.d.ts +27 -0
  9. package/dist/backup.js +125 -0
  10. package/dist/backup.js.map +1 -0
  11. package/dist/cli.d.ts +1 -0
  12. package/dist/cli.js +773 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/codex-prompts.d.ts +17 -0
  15. package/dist/codex-prompts.js +49 -0
  16. package/dist/codex-prompts.js.map +1 -0
  17. package/dist/codex-skills.d.ts +17 -0
  18. package/dist/codex-skills.js +75 -0
  19. package/dist/codex-skills.js.map +1 -0
  20. package/dist/commands/change-advice.d.ts +25 -0
  21. package/dist/commands/change-advice.js +197 -0
  22. package/dist/commands/change-advice.js.map +1 -0
  23. package/dist/commands/change-evidence-command.d.ts +29 -0
  24. package/dist/commands/change-evidence-command.js +213 -0
  25. package/dist/commands/change-evidence-command.js.map +1 -0
  26. package/dist/commands/change-evidence-entry.d.ts +16 -0
  27. package/dist/commands/change-evidence-entry.js +35 -0
  28. package/dist/commands/change-evidence-entry.js.map +1 -0
  29. package/dist/commands/change-evidence.d.ts +108 -0
  30. package/dist/commands/change-evidence.js +341 -0
  31. package/dist/commands/change-evidence.js.map +1 -0
  32. package/dist/commands/change-finish.d.ts +71 -0
  33. package/dist/commands/change-finish.js +387 -0
  34. package/dist/commands/change-finish.js.map +1 -0
  35. package/dist/commands/change-git-status.d.ts +22 -0
  36. package/dist/commands/change-git-status.js +50 -0
  37. package/dist/commands/change-git-status.js.map +1 -0
  38. package/dist/commands/change-lifecycle-entry.d.ts +29 -0
  39. package/{src → dist}/commands/change-lifecycle-entry.js +21 -28
  40. package/dist/commands/change-lifecycle-entry.js.map +1 -0
  41. package/dist/commands/change-lifecycle.d.ts +56 -0
  42. package/dist/commands/change-lifecycle.js +211 -0
  43. package/dist/commands/change-lifecycle.js.map +1 -0
  44. package/dist/commands/change-metrics-command.d.ts +12 -0
  45. package/dist/commands/change-metrics-command.js +110 -0
  46. package/dist/commands/change-metrics-command.js.map +1 -0
  47. package/dist/commands/change-next-command.d.ts +18 -0
  48. package/dist/commands/change-next-command.js +138 -0
  49. package/dist/commands/change-next-command.js.map +1 -0
  50. package/dist/commands/change-review-gates.d.ts +107 -0
  51. package/dist/commands/change-review-gates.js +329 -0
  52. package/dist/commands/change-review-gates.js.map +1 -0
  53. package/dist/commands/change-scope-gate.d.ts +21 -0
  54. package/dist/commands/change-scope-gate.js +32 -0
  55. package/dist/commands/change-scope-gate.js.map +1 -0
  56. package/dist/commands/change-start.d.ts +30 -0
  57. package/dist/commands/change-start.js +91 -0
  58. package/dist/commands/change-start.js.map +1 -0
  59. package/dist/commands/change-state-command.d.ts +3 -0
  60. package/dist/commands/change-state-command.js +32 -0
  61. package/dist/commands/change-state-command.js.map +1 -0
  62. package/dist/commands/change-status-command.d.ts +13 -0
  63. package/dist/commands/change-status-command.js +126 -0
  64. package/dist/commands/change-status-command.js.map +1 -0
  65. package/dist/commands/change-status-context.d.ts +58 -0
  66. package/dist/commands/change-status-context.js +166 -0
  67. package/dist/commands/change-status-context.js.map +1 -0
  68. package/dist/commands/change-task-stats.d.ts +24 -0
  69. package/dist/commands/change-task-stats.js +66 -0
  70. package/dist/commands/change-task-stats.js.map +1 -0
  71. package/dist/commands/change-validate-entry.d.ts +17 -0
  72. package/dist/commands/change-validate-entry.js +44 -0
  73. package/dist/commands/change-validate-entry.js.map +1 -0
  74. package/dist/commands/change-validate.d.ts +32 -0
  75. package/dist/commands/change-validate.js +128 -0
  76. package/dist/commands/change-validate.js.map +1 -0
  77. package/dist/commands/change.d.ts +322 -0
  78. package/dist/commands/change.js +1731 -0
  79. package/dist/commands/change.js.map +1 -0
  80. package/dist/commands/codex-install-prompts.d.ts +4 -0
  81. package/dist/commands/codex-install-prompts.js +68 -0
  82. package/dist/commands/codex-install-prompts.js.map +1 -0
  83. package/dist/commands/codex-install-skills.d.ts +4 -0
  84. package/dist/commands/codex-install-skills.js +74 -0
  85. package/dist/commands/codex-install-skills.js.map +1 -0
  86. package/dist/commands/codex-status-prompts.d.ts +4 -0
  87. package/dist/commands/codex-status-prompts.js +44 -0
  88. package/dist/commands/codex-status-prompts.js.map +1 -0
  89. package/dist/commands/codex-status-skills.d.ts +4 -0
  90. package/dist/commands/codex-status-skills.js +54 -0
  91. package/dist/commands/codex-status-skills.js.map +1 -0
  92. package/dist/commands/codex-uninstall-prompts.d.ts +4 -0
  93. package/dist/commands/codex-uninstall-prompts.js +51 -0
  94. package/dist/commands/codex-uninstall-prompts.js.map +1 -0
  95. package/dist/commands/codex-uninstall-skills.d.ts +4 -0
  96. package/dist/commands/codex-uninstall-skills.js +59 -0
  97. package/dist/commands/codex-uninstall-skills.js.map +1 -0
  98. package/dist/commands/dashboard.d.ts +222 -0
  99. package/dist/commands/dashboard.js +193 -0
  100. package/dist/commands/dashboard.js.map +1 -0
  101. package/dist/commands/hooks-install.d.ts +4 -0
  102. package/dist/commands/hooks-install.js +90 -0
  103. package/dist/commands/hooks-install.js.map +1 -0
  104. package/dist/commands/hooks-status.d.ts +4 -0
  105. package/dist/commands/hooks-status.js +89 -0
  106. package/dist/commands/hooks-status.js.map +1 -0
  107. package/dist/commands/init.d.ts +4 -0
  108. package/dist/commands/init.js +100 -0
  109. package/dist/commands/init.js.map +1 -0
  110. package/dist/commands/opencode-auto.d.ts +11 -0
  111. package/dist/commands/opencode-auto.js +158 -0
  112. package/dist/commands/opencode-auto.js.map +1 -0
  113. package/dist/commands/opencode-status.d.ts +4 -0
  114. package/dist/commands/opencode-status.js +75 -0
  115. package/dist/commands/opencode-status.js.map +1 -0
  116. package/dist/commands/opencode-supervise.d.ts +24 -0
  117. package/dist/commands/opencode-supervise.js +188 -0
  118. package/dist/commands/opencode-supervise.js.map +1 -0
  119. package/dist/commands/rollback.d.ts +4 -0
  120. package/dist/commands/rollback.js +12 -0
  121. package/dist/commands/rollback.js.map +1 -0
  122. package/dist/commands/update.d.ts +4 -0
  123. package/dist/commands/update.js +212 -0
  124. package/dist/commands/update.js.map +1 -0
  125. package/dist/commands/validate.d.ts +4 -0
  126. package/dist/commands/validate.js +222 -0
  127. package/dist/commands/validate.js.map +1 -0
  128. package/dist/commands/ws-commit.d.ts +5 -0
  129. package/dist/commands/ws-commit.js +39 -0
  130. package/dist/commands/ws-commit.js.map +1 -0
  131. package/dist/commands/ws-deliver.d.ts +5 -0
  132. package/dist/commands/ws-deliver.js +59 -0
  133. package/dist/commands/ws-deliver.js.map +1 -0
  134. package/dist/commands/ws-finish.d.ts +5 -0
  135. package/dist/commands/ws-finish.js +142 -0
  136. package/dist/commands/ws-finish.js.map +1 -0
  137. package/dist/commands/ws-handoff.d.ts +5 -0
  138. package/dist/commands/ws-handoff.js +35 -0
  139. package/dist/commands/ws-handoff.js.map +1 -0
  140. package/dist/commands/ws-migrate.d.ts +5 -0
  141. package/dist/commands/ws-migrate.js +41 -0
  142. package/dist/commands/ws-migrate.js.map +1 -0
  143. package/dist/commands/ws-plan-verify.d.ts +5 -0
  144. package/dist/commands/ws-plan-verify.js +38 -0
  145. package/dist/commands/ws-plan-verify.js.map +1 -0
  146. package/dist/commands/ws-pull.d.ts +5 -0
  147. package/dist/commands/ws-pull.js +26 -0
  148. package/dist/commands/ws-pull.js.map +1 -0
  149. package/dist/commands/ws-push.d.ts +5 -0
  150. package/dist/commands/ws-push.js +68 -0
  151. package/dist/commands/ws-push.js.map +1 -0
  152. package/dist/commands/ws-submodule-setup.d.ts +5 -0
  153. package/dist/commands/ws-submodule-setup.js +55 -0
  154. package/dist/commands/ws-submodule-setup.js.map +1 -0
  155. package/dist/commands/ws-verify-before-complete.d.ts +5 -0
  156. package/dist/commands/ws-verify-before-complete.js +35 -0
  157. package/dist/commands/ws-verify-before-complete.js.map +1 -0
  158. package/dist/dashboard/app.d.ts +1 -0
  159. package/dist/dashboard/app.js +370 -0
  160. package/dist/dashboard/app.js.map +1 -0
  161. package/dist/delegation/cli.d.ts +6 -0
  162. package/dist/delegation/cli.js +14 -0
  163. package/dist/delegation/cli.js.map +1 -0
  164. package/dist/delegation/index.d.ts +35 -0
  165. package/dist/delegation/index.js +118 -0
  166. package/dist/delegation/index.js.map +1 -0
  167. package/dist/errors.d.ts +8 -0
  168. package/dist/errors.js +11 -0
  169. package/dist/errors.js.map +1 -0
  170. package/dist/exec.d.ts +9 -0
  171. package/dist/exec.js +22 -0
  172. package/dist/exec.js.map +1 -0
  173. package/dist/fs.d.ts +9 -0
  174. package/dist/fs.js +62 -0
  175. package/dist/fs.js.map +1 -0
  176. package/dist/governance.d.ts +10 -0
  177. package/dist/governance.js +135 -0
  178. package/dist/governance.js.map +1 -0
  179. package/dist/hash.d.ts +3 -0
  180. package/dist/hash.js +13 -0
  181. package/dist/hash.js.map +1 -0
  182. package/dist/hooks/deploy-claude.d.ts +13 -0
  183. package/dist/hooks/deploy-claude.js +67 -0
  184. package/dist/hooks/deploy-claude.js.map +1 -0
  185. package/dist/journal.d.ts +22 -0
  186. package/dist/journal.js +112 -0
  187. package/dist/journal.js.map +1 -0
  188. package/dist/json-schema-lite.d.ts +22 -0
  189. package/dist/json-schema-lite.js +148 -0
  190. package/dist/json-schema-lite.js.map +1 -0
  191. package/dist/managed-blocks.d.ts +24 -0
  192. package/dist/managed-blocks.js +84 -0
  193. package/dist/managed-blocks.js.map +1 -0
  194. package/dist/manifest.d.ts +24 -0
  195. package/dist/manifest.js +145 -0
  196. package/dist/manifest.js.map +1 -0
  197. package/dist/opencode-env.d.ts +62 -0
  198. package/dist/opencode-env.js +178 -0
  199. package/dist/opencode-env.js.map +1 -0
  200. package/dist/path-utils.d.ts +2 -0
  201. package/dist/path-utils.js +8 -0
  202. package/dist/path-utils.js.map +1 -0
  203. package/dist/spec.d.ts +17 -0
  204. package/dist/spec.js +174 -0
  205. package/dist/spec.js.map +1 -0
  206. package/dist/template.d.ts +20 -0
  207. package/dist/template.js +123 -0
  208. package/dist/template.js.map +1 -0
  209. package/dist/workspace.d.ts +4 -0
  210. package/dist/workspace.js +19 -0
  211. package/dist/workspace.js.map +1 -0
  212. package/package.json +11 -3
  213. package/src/aiws-package.js +0 -15
  214. package/src/backup.js +0 -149
  215. package/src/cli.js +0 -760
  216. package/src/codex-prompts.js +0 -74
  217. package/src/codex-skills.js +0 -111
  218. package/src/commands/change-advice.js +0 -181
  219. package/src/commands/change-evidence-command.js +0 -242
  220. package/src/commands/change-evidence-entry.js +0 -40
  221. package/src/commands/change-evidence.js +0 -340
  222. package/src/commands/change-finish.js +0 -413
  223. package/src/commands/change-git-status.js +0 -53
  224. package/src/commands/change-lifecycle.js +0 -236
  225. package/src/commands/change-metrics-command.js +0 -110
  226. package/src/commands/change-next-command.js +0 -133
  227. package/src/commands/change-review-gates.js +0 -331
  228. package/src/commands/change-scope-gate.js +0 -34
  229. package/src/commands/change-start.js +0 -85
  230. package/src/commands/change-state-command.js +0 -40
  231. package/src/commands/change-status-command.js +0 -125
  232. package/src/commands/change-status-context.js +0 -173
  233. package/src/commands/change-task-stats.js +0 -64
  234. package/src/commands/change-validate-entry.js +0 -45
  235. package/src/commands/change-validate.js +0 -127
  236. package/src/commands/change.js +0 -1829
  237. package/src/commands/codex-install-prompts.js +0 -68
  238. package/src/commands/codex-install-skills.js +0 -74
  239. package/src/commands/codex-status-prompts.js +0 -55
  240. package/src/commands/codex-status-skills.js +0 -63
  241. package/src/commands/codex-uninstall-prompts.js +0 -55
  242. package/src/commands/codex-uninstall-skills.js +0 -62
  243. package/src/commands/dashboard.js +0 -205
  244. package/src/commands/hooks-install.js +0 -92
  245. package/src/commands/hooks-status.js +0 -95
  246. package/src/commands/init.js +0 -101
  247. package/src/commands/opencode-auto.js +0 -167
  248. package/src/commands/opencode-status.js +0 -103
  249. package/src/commands/opencode-supervise.js +0 -200
  250. package/src/commands/rollback.js +0 -13
  251. package/src/commands/update.js +0 -145
  252. package/src/commands/validate.js +0 -228
  253. package/src/commands/ws-commit.js +0 -44
  254. package/src/commands/ws-deliver.js +0 -67
  255. package/src/commands/ws-finish.js +0 -83
  256. package/src/commands/ws-handoff.js +0 -40
  257. package/src/commands/ws-migrate.js +0 -41
  258. package/src/commands/ws-plan-verify.js +0 -44
  259. package/src/commands/ws-pull.js +0 -30
  260. package/src/commands/ws-push.js +0 -71
  261. package/src/commands/ws-submodule-setup.js +0 -65
  262. package/src/commands/ws-verify-before-complete.js +0 -39
  263. package/src/dashboard/app.js +0 -371
  264. package/src/errors.js +0 -15
  265. package/src/exec.js +0 -34
  266. package/src/fs.js +0 -91
  267. package/src/governance.js +0 -159
  268. package/src/hash.js +0 -25
  269. package/src/json-schema-lite.js +0 -164
  270. package/src/managed-blocks.js +0 -131
  271. package/src/manifest.js +0 -177
  272. package/src/opencode-env.js +0 -208
  273. package/src/path-utils.js +0 -20
  274. package/src/spec.js +0 -195
  275. package/src/template.js +0 -187
  276. package/src/workspace.js +0 -23
  277. /package/{src → dist}/dashboard/index.html +0 -0
  278. /package/{src → dist}/dashboard/style.css +0 -0
package/src/manifest.js DELETED
@@ -1,177 +0,0 @@
1
- import path from "node:path";
2
- import { normalizeNewlines, sha256FileText, sha256Text } from "./hash.js";
3
- import { joinRel, normalizeRel } from "./path-utils.js";
4
- import { pathExists, readText, writeText } from "./fs.js";
5
- import { findManagedBlock } from "./managed-blocks.js";
6
- import { UserError } from "./errors.js";
7
-
8
- /**
9
- * Detect an older AIWS workspace that predates `.aiws/manifest.json`.
10
- *
11
- * Current migration only recognizes the built-in `workspace` template.
12
- *
13
- * @param {string} workspaceRoot
14
- * @returns {Promise<string | null>}
15
- */
16
- export async function detectLegacyWorkspaceTemplateId(workspaceRoot) {
17
- const requiredSignals = [
18
- "AI_PROJECT.md",
19
- "REQUIREMENTS.md",
20
- "AI_WORKSPACE.md",
21
- "tools/ws_change_check.py",
22
- "tools/requirements_contract.py",
23
- ];
24
-
25
- for (const rel of requiredSignals) {
26
- const abs = joinRel(workspaceRoot, rel);
27
- if (!(await pathExists(abs))) return null;
28
- }
29
-
30
- return "workspace";
31
- }
32
-
33
- /**
34
- * @param {any} manifest
35
- */
36
- export function isPlaceholderManifest(manifest) {
37
- if (!manifest || typeof manifest !== "object") return true;
38
- if (manifest.installed_at === "1970-01-01T00:00:00Z" || manifest.updated_at === "1970-01-01T00:00:00Z") return true;
39
-
40
- const managed = Array.isArray(manifest.managed) ? manifest.managed : [];
41
- for (const m of managed) {
42
- if (!m || typeof m !== "object") continue;
43
- if (typeof m.sha256 === "string" && m.sha256.includes("<sha256>")) return true;
44
- if (m.blocks && typeof m.blocks === "object") {
45
- for (const v of Object.values(m.blocks)) {
46
- if (typeof v === "string" && v.includes("<sha256>")) return true;
47
- }
48
- }
49
- }
50
- return false;
51
- }
52
-
53
- /**
54
- * @param {{ workspaceRoot: string, templateId: string, specVersion: string, aiwsVersion: string, installedAt: string, updatedAt: string, tools: string[], templateManifest: any }} options
55
- */
56
- export async function writeWorkspaceManifest(options) {
57
- const managed = await computeManagedState({
58
- workspaceRoot: options.workspaceRoot,
59
- templateManifest: options.templateManifest,
60
- });
61
-
62
- const obj = {
63
- manifest_version: 1,
64
- template_id: options.templateId,
65
- spec_version: options.specVersion,
66
- aiws_version: options.aiwsVersion,
67
- installed_at: options.installedAt,
68
- updated_at: options.updatedAt,
69
- tools: options.tools,
70
- managed,
71
- };
72
-
73
- const outPath = path.join(options.workspaceRoot, ".aiws", "manifest.json");
74
- await writeText(outPath, JSON.stringify(obj, null, 2) + "\n");
75
- return obj;
76
- }
77
-
78
- /**
79
- * Compute managed hashes for the current workspace.
80
- *
81
- * Note: `.aiws/manifest.json` is intentionally excluded from `managed` to avoid self-hashing.
82
- *
83
- * @param {{ workspaceRoot: string, templateManifest: any }} options
84
- */
85
- export async function computeManagedState(options) {
86
- const update = options.templateManifest?.update || {};
87
- const replaceFiles = Array.isArray(update.replace_file) ? update.replace_file : [];
88
- const managedBlocks = update.managed_blocks && typeof update.managed_blocks === "object" ? update.managed_blocks : {};
89
-
90
- /** @type {any[]} */
91
- const out = [];
92
-
93
- for (const relRaw of replaceFiles) {
94
- const rel = normalizeRel(relRaw);
95
- if (!rel || rel === ".aiws/manifest.json") continue;
96
- const abs = joinRel(options.workspaceRoot, rel);
97
- if (!(await pathExists(abs))) throw new UserError(`Missing required managed file: ${rel}`);
98
- out.push({ path: rel, mode: "replace_file", sha256: await sha256FileText(abs) });
99
- }
100
-
101
- for (const [fileRelRaw, blockIdsRaw] of Object.entries(managedBlocks)) {
102
- const fileRel = normalizeRel(fileRelRaw);
103
- if (!fileRel) continue;
104
- const abs = joinRel(options.workspaceRoot, fileRel);
105
- if (!(await pathExists(abs))) throw new UserError(`Missing required managed file: ${fileRel}`);
106
- const text = normalizeNewlines(await readText(abs));
107
- /** @type {Record<string, string>} */
108
- const blocks = {};
109
- const ids = Array.isArray(blockIdsRaw) ? blockIdsRaw : [];
110
- for (const idRaw of ids) {
111
- const id = String(idRaw);
112
- const found = findManagedBlock(text, id);
113
- if (!found) throw new UserError(`Missing managed block: ${id}`, { details: `File: ${fileRel}` });
114
- blocks[id] = sha256Text(found.innerText);
115
- }
116
- out.push({ path: fileRel, mode: "managed_blocks", blocks });
117
- }
118
-
119
- out.sort((a, b) => String(a.path).localeCompare(String(b.path)));
120
- return out;
121
- }
122
-
123
- /**
124
- * Validate current workspace against the stored `.aiws/manifest.json` and template contract.
125
- *
126
- * @param {{ workspaceRoot: string, storedManifest: any, templateManifest: any }} options
127
- */
128
- export async function validateDrift(options) {
129
- const stored = options.storedManifest;
130
- if (isPlaceholderManifest(stored)) {
131
- throw new UserError("Workspace manifest is placeholder/uninitialized.", {
132
- details: "Run `aiws init` to generate a real .aiws/manifest.json.",
133
- });
134
- }
135
-
136
- const expected = await computeManagedState({ workspaceRoot: options.workspaceRoot, templateManifest: options.templateManifest });
137
- const currentByPath = new Map(expected.map((e) => [e.path, e]));
138
-
139
- const managed = Array.isArray(stored.managed) ? stored.managed : [];
140
- const storedByPath = new Map(managed.map((e) => [String(e.path || ""), e]));
141
-
142
- /** @type {string[]} */
143
- const problems = [];
144
-
145
- for (const [p, cur] of currentByPath.entries()) {
146
- const s = storedByPath.get(p);
147
- if (!s) {
148
- problems.push(`missing manifest entry: ${p}`);
149
- continue;
150
- }
151
- if (cur.mode !== s.mode) {
152
- problems.push(`mode mismatch: ${p} (expected ${cur.mode}, got ${s.mode})`);
153
- continue;
154
- }
155
- if (cur.mode === "replace_file") {
156
- if (cur.sha256 !== s.sha256) {
157
- problems.push(`sha256 mismatch: ${p}`);
158
- }
159
- continue;
160
- }
161
- if (cur.mode === "managed_blocks") {
162
- const curBlocks = cur.blocks || {};
163
- const sBlocks = s.blocks || {};
164
- for (const [bid, curSha] of Object.entries(curBlocks)) {
165
- if (!sBlocks[bid]) {
166
- problems.push(`missing block in manifest: ${p} (${bid})`);
167
- } else if (sBlocks[bid] !== curSha) {
168
- problems.push(`block sha256 mismatch: ${p} (${bid})`);
169
- }
170
- }
171
- }
172
- }
173
-
174
- if (problems.length > 0) {
175
- throw new UserError("Workspace drift detected.", { details: problems.join("\n") });
176
- }
177
- }
@@ -1,208 +0,0 @@
1
- import path from "node:path";
2
- import { pathExists, readText } from "./fs.js";
3
-
4
- const OPENCODE_AGENT_NAMES = ["planner-sisyphus", "librarian", "explore", "oracle"];
5
- const SAFE_READ_ONLY_COMMANDS = new Set(["rg", "cat", "sed", "ls", "find", "git status", "git diff"]);
6
- const REQUIRED_WRITE_ALLOW_PATHS = [".agentdocs/tmp/", "changes/*/analysis/", "changes/*/review/", "changes/*/evidence/"];
7
- const REQUIRED_DENY_PATHS = ["secrets/", ".env*"];
8
- const REQUIRED_DENY_COMMANDS = ["rm", "mv", "git commit", "git push", "npm publish"];
9
-
10
- /**
11
- * @param {string} value
12
- */
13
- function relativeOrDot(value) {
14
- return value ? value.replaceAll(path.sep, "/") : ".";
15
- }
16
-
17
- /**
18
- * @param {any} raw
19
- * @param {string} agentName
20
- */
21
- function readAgentState(raw, agentName) {
22
- const agents = raw && typeof raw === "object" && raw.agents && typeof raw.agents === "object" ? raw.agents : {};
23
- const entry = agents[agentName];
24
- return {
25
- present: !!entry && typeof entry === "object",
26
- enabled: !!(entry && typeof entry === "object" && entry.enabled === true),
27
- replacePlan: entry && typeof entry === "object" && typeof entry.replace_plan === "boolean" ? entry.replace_plan : null,
28
- promptAppendConfigured: !!(
29
- entry &&
30
- typeof entry === "object" &&
31
- typeof entry.prompt_append === "string" &&
32
- entry.prompt_append.trim().length > 0
33
- ),
34
- };
35
- }
36
-
37
- /**
38
- * @param {any} raw
39
- */
40
- function readApprovalWhitelistState(raw) {
41
- const policy =
42
- raw &&
43
- typeof raw === "object" &&
44
- raw.aiws &&
45
- typeof raw.aiws === "object" &&
46
- raw.aiws.autonomy &&
47
- typeof raw.aiws.autonomy === "object" &&
48
- raw.aiws.autonomy.approval_whitelist &&
49
- typeof raw.aiws.autonomy.approval_whitelist === "object"
50
- ? raw.aiws.autonomy.approval_whitelist
51
- : null;
52
- const readOnlyCommands = Array.isArray(policy?.read_only_commands)
53
- ? policy.read_only_commands.filter((value) => typeof value === "string" && value.trim().length > 0)
54
- : [];
55
- const writeAllowPaths = Array.isArray(policy?.write_allow_paths)
56
- ? policy.write_allow_paths.filter((value) => typeof value === "string" && value.trim().length > 0)
57
- : [];
58
- const denyPaths = Array.isArray(policy?.deny_paths)
59
- ? policy.deny_paths.filter((value) => typeof value === "string" && value.trim().length > 0)
60
- : [];
61
- const denyCommands = Array.isArray(policy?.deny_commands)
62
- ? policy.deny_commands.filter((value) => typeof value === "string" && value.trim().length > 0)
63
- : [];
64
- const mode = typeof policy?.mode === "string" && policy.mode.trim().length > 0 ? policy.mode : "";
65
- const hostPermissionMode =
66
- typeof policy?.host_permission_mode === "string" && policy.host_permission_mode.trim().length > 0
67
- ? policy.host_permission_mode
68
- : "";
69
- const enabled = policy?.enabled === true;
70
- const safeReadOnlyCommands = readOnlyCommands.every((value) => SAFE_READ_ONLY_COMMANDS.has(value));
71
- const requiredWritePathsPresent = REQUIRED_WRITE_ALLOW_PATHS.every((value) => writeAllowPaths.includes(value));
72
- const requiredDenyPathsPresent = REQUIRED_DENY_PATHS.every((value) => denyPaths.includes(value));
73
- const requiredDenyCommandsPresent = REQUIRED_DENY_COMMANDS.every((value) => denyCommands.includes(value));
74
- const modeValid = mode === "assist-only";
75
-
76
- return {
77
- present: !!policy,
78
- enabled,
79
- mode,
80
- hostPermissionMode,
81
- readOnlyCommands,
82
- writeAllowPaths,
83
- denyPaths,
84
- denyCommands,
85
- configured:
86
- enabled &&
87
- modeValid &&
88
- safeReadOnlyCommands &&
89
- readOnlyCommands.length > 0 &&
90
- requiredWritePathsPresent &&
91
- requiredDenyPathsPresent &&
92
- requiredDenyCommandsPresent &&
93
- hostPermissionMode === "manual-only",
94
- };
95
- }
96
-
97
- /**
98
- * @param {string} workspaceRoot
99
- */
100
- export async function detectOpenCodeEnvironment(workspaceRoot) {
101
- const opencodeDir = path.join(workspaceRoot, ".opencode");
102
- const configPath = path.join(opencodeDir, "oh-my-opencode.json");
103
- const examplePath = path.join(opencodeDir, "oh-my-opencode.json.example");
104
- const opencodeDirExists = await pathExists(opencodeDir);
105
- const configExists = await pathExists(configPath);
106
- const exampleExists = await pathExists(examplePath);
107
-
108
- /** @type {any} */
109
- let config = null;
110
- let configStatus = "missing";
111
- let configError = "";
112
- if (configExists) {
113
- try {
114
- config = JSON.parse(await readText(configPath));
115
- configStatus = "loaded";
116
- } catch (error) {
117
- configStatus = "invalid";
118
- configError = error instanceof Error ? error.message : String(error);
119
- }
120
- }
121
-
122
- const agents = Object.fromEntries(OPENCODE_AGENT_NAMES.map((name) => [name, readAgentState(config, name)]));
123
- const enabledAgents = OPENCODE_AGENT_NAMES.filter((name) => agents[name]?.enabled === true);
124
- const recommendedAgentsReady = ["planner-sisyphus", "librarian", "explore", "oracle"].every((name) => agents[name]?.enabled === true);
125
- const backgroundTasksConfigured = !!(config && typeof config === "object" && config.backgroundTasks && typeof config.backgroundTasks === "object");
126
- const autoResumeEnabled = !!(
127
- config &&
128
- typeof config === "object" &&
129
- config.experimental &&
130
- typeof config.experimental === "object" &&
131
- config.experimental.auto_resume === true
132
- );
133
- const approvalWhitelist = readApprovalWhitelistState(config);
134
- const claudeSettingsExamplePath = path.join(workspaceRoot, ".claude", "settings.json.example");
135
- const approvalWhitelistHelperPath = path.join(opencodeDir, "helpers", "approval-whitelist-check.sh");
136
- const approvalWhitelistRunnerPath = path.join(opencodeDir, "helpers", "approval-whitelist-run.sh");
137
- const approvalWhitelistWatchdogPath = path.join(opencodeDir, "helpers", "approval-whitelist-watchdog.sh");
138
- const tmuxScanHelperPath = path.join(opencodeDir, "helpers", "tmux-swarm-scan.sh");
139
- const tmuxRescueHelperPath = path.join(opencodeDir, "helpers", "tmux-swarm-rescue.sh");
140
- const claudeSettingsExampleExists = await pathExists(claudeSettingsExamplePath);
141
- const approvalWhitelistHelperExists = await pathExists(approvalWhitelistHelperPath);
142
- const approvalWhitelistRunnerExists = await pathExists(approvalWhitelistRunnerPath);
143
- const approvalWhitelistWatchdogExists = await pathExists(approvalWhitelistWatchdogPath);
144
- const tmuxScanHelperExists = await pathExists(tmuxScanHelperPath);
145
- const tmuxRescueHelperExists = await pathExists(tmuxRescueHelperPath);
146
- const watchdogSuperviseReady =
147
- configStatus === "loaded" &&
148
- approvalWhitelist.configured &&
149
- approvalWhitelistHelperExists &&
150
- approvalWhitelistRunnerExists &&
151
- approvalWhitelistWatchdogExists;
152
- const autonomyReady =
153
- configStatus === "loaded" &&
154
- agents["planner-sisyphus"]?.promptAppendConfigured === true &&
155
- backgroundTasksConfigured &&
156
- autoResumeEnabled &&
157
- approvalWhitelist.configured &&
158
- claudeSettingsExampleExists &&
159
- approvalWhitelistHelperExists &&
160
- approvalWhitelistRunnerExists &&
161
- approvalWhitelistWatchdogExists &&
162
- tmuxScanHelperExists &&
163
- tmuxRescueHelperExists;
164
-
165
- return {
166
- workspaceRoot,
167
- opencodeDir,
168
- opencodeDirExists,
169
- configPath,
170
- configExists,
171
- configStatus,
172
- configError,
173
- examplePath,
174
- exampleExists,
175
- mode: configStatus === "loaded" ? "oMo-enabled" : "standard-opencode",
176
- recommendedAgentsReady,
177
- enabledAgents,
178
- agents,
179
- backgroundTasksConfigured,
180
- autoResumeEnabled,
181
- approvalWhitelist,
182
- watchdogSuperviseReady,
183
- autonomyReady,
184
- claudeSettingsExamplePath,
185
- claudeSettingsExampleExists,
186
- approvalWhitelistHelperPath,
187
- approvalWhitelistHelperExists,
188
- approvalWhitelistRunnerPath,
189
- approvalWhitelistRunnerExists,
190
- approvalWhitelistWatchdogPath,
191
- approvalWhitelistWatchdogExists,
192
- tmuxScanHelperPath,
193
- tmuxScanHelperExists,
194
- tmuxRescueHelperPath,
195
- tmuxRescueHelperExists,
196
- rel: {
197
- opencodeDir: relativeOrDot(path.relative(workspaceRoot, opencodeDir)),
198
- configPath: relativeOrDot(path.relative(workspaceRoot, configPath)),
199
- examplePath: relativeOrDot(path.relative(workspaceRoot, examplePath)),
200
- claudeSettingsExamplePath: relativeOrDot(path.relative(workspaceRoot, claudeSettingsExamplePath)),
201
- approvalWhitelistHelperPath: relativeOrDot(path.relative(workspaceRoot, approvalWhitelistHelperPath)),
202
- approvalWhitelistRunnerPath: relativeOrDot(path.relative(workspaceRoot, approvalWhitelistRunnerPath)),
203
- approvalWhitelistWatchdogPath: relativeOrDot(path.relative(workspaceRoot, approvalWhitelistWatchdogPath)),
204
- tmuxScanHelperPath: relativeOrDot(path.relative(workspaceRoot, tmuxScanHelperPath)),
205
- tmuxRescueHelperPath: relativeOrDot(path.relative(workspaceRoot, tmuxRescueHelperPath)),
206
- },
207
- };
208
- }
package/src/path-utils.js DELETED
@@ -1,20 +0,0 @@
1
- import path from "node:path";
2
-
3
- /**
4
- * Join a POSIX-style relative path (with `/`) onto an absolute root.
5
- *
6
- * @param {string} rootDir
7
- * @param {string} relPosix
8
- */
9
- export function joinRel(rootDir, relPosix) {
10
- return path.join(rootDir, ...String(relPosix).split("/"));
11
- }
12
-
13
- /**
14
- * Normalize a relative path from manifest (always forward slashes).
15
- *
16
- * @param {string} rel
17
- */
18
- export function normalizeRel(rel) {
19
- return String(rel).replaceAll("\\", "/").replaceAll(/\/+/g, "/").replace(/^\/+/, "");
20
- }
package/src/spec.js DELETED
@@ -1,195 +0,0 @@
1
- import path from "node:path";
2
- import fs from "node:fs/promises";
3
- import { createRequire } from "node:module";
4
- import { fileURLToPath } from "node:url";
5
- import { pathExists, readText } from "./fs.js";
6
- import { UserError } from "./errors.js";
7
- import { validateJsonSchemaLite } from "./json-schema-lite.js";
8
-
9
- const specJsonDocCache = new Map();
10
-
11
- /**
12
- * @returns {Promise<{ rootDir: string, version: string }>}
13
- */
14
- export async function loadSpecPackage() {
15
- const require = createRequire(import.meta.url);
16
-
17
- /** @type {string | null} */
18
- let pkgJsonPath = null;
19
- try {
20
- pkgJsonPath = require.resolve("@aipper/aiws-spec/package.json");
21
- } catch {
22
- pkgJsonPath = null;
23
- }
24
-
25
- /** @type {string} */
26
- let rootDir;
27
- if (pkgJsonPath) {
28
- rootDir = path.dirname(pkgJsonPath);
29
- } else {
30
- const here = fileURLToPath(import.meta.url);
31
- rootDir = path.resolve(path.dirname(here), "../../spec");
32
- const fallbackPkg = path.join(rootDir, "package.json");
33
- if (!(await pathExists(fallbackPkg))) {
34
- throw new UserError("Cannot locate @aipper/aiws-spec. Install it or run inside the monorepo.", {
35
- exitCode: 1,
36
- });
37
- }
38
- }
39
-
40
- const pkg = JSON.parse(await readText(path.join(rootDir, "package.json")));
41
- const version = String(pkg.version || "").trim() || "0.0.0";
42
- return { rootDir, version };
43
- }
44
-
45
- /**
46
- * @param {string} templateId
47
- */
48
- export async function loadTemplate(templateId) {
49
- if (!templateId || templateId.includes("..") || templateId.includes("/") || templateId.includes("\\")) {
50
- throw new UserError(`Invalid template id: ${templateId}`);
51
- }
52
-
53
- const spec = await loadSpecPackage();
54
- const templateDir = path.join(spec.rootDir, "templates", templateId);
55
- const manifestPath = path.join(templateDir, "manifest.json");
56
-
57
- try {
58
- await fs.access(manifestPath);
59
- } catch {
60
- throw new UserError(`Template not found: ${templateId}`, {
61
- details: `Missing: ${manifestPath}`,
62
- });
63
- }
64
-
65
- const manifest = JSON.parse(await readText(manifestPath));
66
- return { templateId, templateDir, manifest, specVersion: spec.version };
67
- }
68
-
69
- /**
70
- * @param {string} relPath
71
- */
72
- async function loadSpecJsonDoc(relPath) {
73
- const spec = await loadSpecPackage();
74
- const absPath = path.join(spec.rootDir, relPath);
75
- const cacheKey = `${spec.rootDir}:${relPath}`;
76
- if (specJsonDocCache.has(cacheKey)) {
77
- return { spec, data: specJsonDocCache.get(cacheKey), absPath };
78
- }
79
- const raw = await readText(absPath);
80
- let data;
81
- try {
82
- data = JSON.parse(raw);
83
- } catch (error) {
84
- throw new UserError(`Invalid JSON in spec doc: ${relPath}`, {
85
- details: error instanceof Error ? error.message : String(error),
86
- });
87
- }
88
- specJsonDocCache.set(cacheKey, data);
89
- return { spec, data, absPath };
90
- }
91
-
92
- async function loadValidatedSpecJsonDoc(relPath, schemaRelPath) {
93
- const loaded = await loadSpecJsonDoc(relPath);
94
- const { data: schema } = await loadSpecJsonDoc(schemaRelPath);
95
- validateJsonSchemaLite(loaded.data, schema, { source: loaded.absPath });
96
- return loaded;
97
- }
98
-
99
- export async function loadWorkflowGovernanceRules() {
100
- const relPath = path.join("docs", "workflow-governance-rules.json");
101
- const schemaRelPath = path.join("docs", "workflow-governance-rules.schema.json");
102
- const { spec, data } = await loadValidatedSpecJsonDoc(relPath, schemaRelPath);
103
- const governanceRules = data.governanceRules;
104
- const guidanceRules = data.guidanceRules;
105
- return {
106
- ok: true,
107
- source: "@aipper/aiws-spec/docs/workflow-governance-rules.json",
108
- specVersion: spec.version,
109
- version: Number(data?.version || 1),
110
- description: String(data?.description || ""),
111
- governanceRules,
112
- guidanceRules,
113
- };
114
- }
115
-
116
- export async function loadWorkflowStageContracts() {
117
- const relPath = path.join("docs", "workflow-stage-contracts.json");
118
- const schemaRelPath = path.join("docs", "workflow-stage-contracts.schema.json");
119
- const { spec, data } = await loadValidatedSpecJsonDoc(relPath, schemaRelPath);
120
- const stages = data.stages;
121
- return {
122
- ok: true,
123
- source: "@aipper/aiws-spec/docs/workflow-stage-contracts.json",
124
- specVersion: spec.version,
125
- version: Number(data?.version || 1),
126
- description: String(data?.description || ""),
127
- standardChain: Array.isArray(data?.standardChain) ? data.standardChain : [],
128
- notes: Array.isArray(data?.notes) ? data.notes : [],
129
- stages,
130
- };
131
- }
132
-
133
- export async function loadWorkflowRouterRules() {
134
- const relPath = path.join("docs", "workflow-router-rules.json");
135
- const schemaRelPath = path.join("docs", "workflow-router-rules.schema.json");
136
- const { spec, data } = await loadValidatedSpecJsonDoc(relPath, schemaRelPath);
137
- return {
138
- ok: true,
139
- source: "@aipper/aiws-spec/docs/workflow-router-rules.json",
140
- specVersion: spec.version,
141
- version: Number(data?.version || 1),
142
- title: String(data?.title || ""),
143
- description: String(data?.description || ""),
144
- truthFiles: Array.isArray(data?.truthFiles) ? data.truthFiles : [],
145
- bootstrapEntry: data.bootstrapEntry,
146
- universalSequence: Array.isArray(data?.universalSequence) ? data.universalSequence : [],
147
- routingRules: Array.isArray(data?.routingRules) ? data.routingRules : [],
148
- routeCases: Array.isArray(data?.routeCases) ? data.routeCases : [],
149
- clarificationTriggers: Array.isArray(data?.clarificationTriggers) ? data.clarificationTriggers : [],
150
- universalRules: Array.isArray(data?.universalRules) ? data.universalRules : [],
151
- notes: Array.isArray(data?.notes) ? data.notes : [],
152
- };
153
- }
154
-
155
- export async function loadWorkflowReviewGates() {
156
- const relPath = path.join("docs", "workflow-review-gates.json");
157
- const schemaRelPath = path.join("docs", "workflow-review-gates.schema.json");
158
- const { spec, data } = await loadValidatedSpecJsonDoc(relPath, schemaRelPath);
159
- return {
160
- ok: true,
161
- source: "@aipper/aiws-spec/docs/workflow-review-gates.json",
162
- specVersion: spec.version,
163
- version: Number(data?.version || 1),
164
- title: String(data?.title || ""),
165
- description: String(data?.description || ""),
166
- gates: Array.isArray(data?.gates) ? data.gates : [],
167
- unifiedRules: Array.isArray(data?.unifiedRules) ? data.unifiedRules : [],
168
- evidence: Array.isArray(data?.evidence) ? data.evidence : [],
169
- notes: Array.isArray(data?.notes) ? data.notes : [],
170
- };
171
- }
172
-
173
- export async function loadWorkflowDelegationContracts() {
174
- const relPath = path.join("docs", "workflow-delegation-contracts.json");
175
- const schemaRelPath = path.join("docs", "workflow-delegation-contracts.schema.json");
176
- const { spec, data } = await loadValidatedSpecJsonDoc(relPath, schemaRelPath);
177
- return {
178
- ok: true,
179
- source: "@aipper/aiws-spec/docs/workflow-delegation-contracts.json",
180
- specVersion: spec.version,
181
- version: Number(data?.version || 1),
182
- title: String(data?.title || ""),
183
- description: String(data?.description || ""),
184
- purpose: Array.isArray(data?.purpose) ? data.purpose : [],
185
- truthFiles: Array.isArray(data?.truthFiles) ? data.truthFiles : [],
186
- delegationFlow: Array.isArray(data?.delegationFlow) ? data.delegationFlow : [],
187
- roleTypes: Array.isArray(data?.roleTypes) ? data.roleTypes : [],
188
- artifactTargets: Array.isArray(data?.artifactTargets) ? data.artifactTargets : [],
189
- reviewConvergence: data?.reviewConvergence || {},
190
- fallbackMode: data?.fallbackMode || {},
191
- toolCapabilityMatrix: Array.isArray(data?.toolCapabilityMatrix) ? data.toolCapabilityMatrix : [],
192
- universalRules: Array.isArray(data?.universalRules) ? data.universalRules : [],
193
- notes: Array.isArray(data?.notes) ? data.notes : [],
194
- };
195
- }