@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
@@ -1,68 +0,0 @@
1
- import path from "node:path";
2
- import { loadTemplate } from "../spec.js";
3
- import { UserError } from "../errors.js";
4
- import { copyFile, ensureDir, pathExists, readText, writeText } from "../fs.js";
5
- import { normalizeNewlines } from "../hash.js";
6
- import { findManagedBlock, upsertManagedBlock } from "../managed-blocks.js";
7
- import { codexBackupPathFor, codexBackupStamp, listTemplateCodexPrompts, resolveCodexPromptsDir } from "../codex-prompts.js";
8
-
9
- /**
10
- * @param {{ templateId: string, promptsDir?: string, force?: boolean, dryRun?: boolean }} options
11
- */
12
- export async function codexInstallPromptsCommand(options) {
13
- const templateId = String(options.templateId || "workspace");
14
- const tpl = await loadTemplate(templateId);
15
-
16
- const promptsDir = resolveCodexPromptsDir(options.promptsDir);
17
- const dryRun = options.dryRun === true;
18
- if (!dryRun) await ensureDir(promptsDir);
19
-
20
- const promptFiles = await listTemplateCodexPrompts(tpl);
21
-
22
- /** @type {string[]} */
23
- const created = [];
24
- /** @type {string[]} */
25
- const updated = [];
26
- /** @type {string[]} */
27
- const overwritten = [];
28
- let backupStamp = "";
29
-
30
- for (const pf of promptFiles) {
31
- const { filename, blockId, templateText, innerText } = pf;
32
- const destAbs = path.join(promptsDir, filename);
33
- if (!(await pathExists(destAbs))) {
34
- if (!dryRun) await writeText(destAbs, templateText);
35
- created.push(filename);
36
- continue;
37
- }
38
-
39
- const currentText = normalizeNewlines(await readText(destAbs));
40
- const existingBlock = findManagedBlock(currentText, blockId);
41
- if (!existingBlock) {
42
- if (!options.force) {
43
- throw new UserError("Codex prompt file exists and is not AIWS-managed; refusing to overwrite.", {
44
- details: `File: ${destAbs}\nHint: re-run with --force to overwrite (a backup will be created).`,
45
- });
46
- }
47
- if (!backupStamp) backupStamp = codexBackupStamp();
48
- const backup = codexBackupPathFor(promptsDir, filename, backupStamp);
49
- if (!dryRun) {
50
- await copyFile(destAbs, backup);
51
- await writeText(destAbs, templateText);
52
- }
53
- overwritten.push(filename);
54
- continue;
55
- }
56
-
57
- const res = upsertManagedBlock(currentText, blockId, innerText, { insertIfMissing: false });
58
- if (res.changed) {
59
- if (!dryRun) await writeText(destAbs, res.nextText);
60
- updated.push(filename);
61
- }
62
- }
63
-
64
- console.log(`${dryRun ? "✓ (dry-run)" : "✓"} aiws codex install-prompts: ${promptsDir}`);
65
- if (created.length > 0) console.log(`created: ${created.join(", ")}`);
66
- if (updated.length > 0) console.log(`updated: ${updated.join(", ")}`);
67
- if (overwritten.length > 0) console.log(`overwritten: ${overwritten.join(", ")}`);
68
- }
@@ -1,74 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { loadTemplate } from "../spec.js";
4
- import { UserError } from "../errors.js";
5
- import { copyFile, ensureDir, pathExists, readText, writeText } from "../fs.js";
6
- import { normalizeNewlines } from "../hash.js";
7
- import { findManagedBlock, upsertManagedBlock } from "../managed-blocks.js";
8
- import { codexSkillsBackupPathFor, codexSkillsBackupStamp, listTemplateCodexSkills, resolveCodexSkillsDir } from "../codex-skills.js";
9
-
10
- /**
11
- * @param {{ templateId: string, skillsDir?: string, force?: boolean, dryRun?: boolean }} options
12
- */
13
- export async function codexInstallSkillsCommand(options) {
14
- const templateId = String(options.templateId || "workspace");
15
- const tpl = await loadTemplate(templateId);
16
-
17
- const skillsDir = resolveCodexSkillsDir(options.skillsDir);
18
- const dryRun = options.dryRun === true;
19
- if (!dryRun) await ensureDir(skillsDir);
20
- const skillsDirIsSymlink = await fs
21
- .lstat(skillsDir)
22
- .then((st) => st.isSymbolicLink())
23
- .catch(() => false);
24
- const skillsDirReal = skillsDirIsSymlink ? await fs.realpath(skillsDir).catch(() => skillsDir) : skillsDir;
25
-
26
- const skillFiles = await listTemplateCodexSkills(tpl);
27
-
28
- /** @type {string[]} */
29
- const created = [];
30
- /** @type {string[]} */
31
- const updated = [];
32
- /** @type {string[]} */
33
- const overwritten = [];
34
- let backupStamp = "";
35
-
36
- for (const sf of skillFiles) {
37
- const destAbs = path.join(skillsDir, sf.skillName, "SKILL.md");
38
- if (!(await pathExists(destAbs))) {
39
- if (!dryRun) await writeText(destAbs, sf.managedText);
40
- created.push(sf.skillName);
41
- continue;
42
- }
43
-
44
- const currentText = normalizeNewlines(await readText(destAbs));
45
- const existingBlock = findManagedBlock(currentText, sf.blockId);
46
- if (!existingBlock) {
47
- if (!options.force) {
48
- throw new UserError("Codex skill exists and is not AIWS-managed; refusing to overwrite.", {
49
- details: `File: ${destAbs}\nHint: re-run with --force to overwrite (a backup will be created).`,
50
- });
51
- }
52
- if (!backupStamp) backupStamp = codexSkillsBackupStamp();
53
- const backup = codexSkillsBackupPathFor(skillsDir, sf.skillName, backupStamp);
54
- if (!dryRun) {
55
- await copyFile(destAbs, backup);
56
- await writeText(destAbs, sf.managedText);
57
- }
58
- overwritten.push(sf.skillName);
59
- continue;
60
- }
61
-
62
- const res = upsertManagedBlock(currentText, sf.blockId, sf.innerText, { insertIfMissing: false });
63
- if (res.changed) {
64
- if (!dryRun) await writeText(destAbs, res.nextText);
65
- updated.push(sf.skillName);
66
- }
67
- }
68
-
69
- const header = skillsDirIsSymlink && skillsDirReal !== skillsDir ? `${skillsDir} -> ${skillsDirReal}` : skillsDir;
70
- console.log(`${dryRun ? "✓ (dry-run)" : "✓"} aiws codex install-skills: ${header}`);
71
- if (created.length > 0) console.log(`created: ${created.join(", ")}`);
72
- if (updated.length > 0) console.log(`updated: ${updated.join(", ")}`);
73
- if (overwritten.length > 0) console.log(`overwritten: ${overwritten.join(", ")}`);
74
- }
@@ -1,55 +0,0 @@
1
- import path from "node:path";
2
- import { loadTemplate } from "../spec.js";
3
- import { normalizeNewlines } from "../hash.js";
4
- import { findManagedBlock } from "../managed-blocks.js";
5
- import { pathExists, readText } from "../fs.js";
6
- import { listTemplateCodexPrompts, resolveCodexPromptsDir } from "../codex-prompts.js";
7
-
8
- /**
9
- * @param {{ templateId: string, promptsDir?: string }} options
10
- */
11
- export async function codexStatusPromptsCommand(options) {
12
- const templateId = String(options.templateId || "workspace");
13
- const tpl = await loadTemplate(templateId);
14
-
15
- const promptsDir = resolveCodexPromptsDir(options.promptsDir);
16
- const promptFiles = await listTemplateCodexPrompts(tpl);
17
-
18
- /** @type {Array<{ filename: string, status: "ok" | "missing" | "unmanaged" | "outdated" }>} */
19
- const rows = [];
20
-
21
- for (const pf of promptFiles) {
22
- const destAbs = path.join(promptsDir, pf.filename);
23
- if (!(await pathExists(destAbs))) {
24
- rows.push({ filename: pf.filename, status: "missing" });
25
- continue;
26
- }
27
-
28
- const currentText = normalizeNewlines(await readText(destAbs));
29
- const block = findManagedBlock(currentText, pf.blockId);
30
- if (!block) {
31
- rows.push({ filename: pf.filename, status: "unmanaged" });
32
- continue;
33
- }
34
-
35
- rows.push({ filename: pf.filename, status: block.innerText === pf.innerText ? "ok" : "outdated" });
36
- }
37
-
38
- const counts = rows.reduce(
39
- (acc, r) => {
40
- acc[r.status]++;
41
- return acc;
42
- },
43
- /** @type {{ ok: number, missing: number, unmanaged: number, outdated: number }} */ ({ ok: 0, missing: 0, unmanaged: 0, outdated: 0 }),
44
- );
45
-
46
- console.log(`✓ aiws codex status: ${promptsDir}`);
47
- console.log(`ok=${counts.ok} missing=${counts.missing} unmanaged=${counts.unmanaged} outdated=${counts.outdated}`);
48
- for (const r of rows) {
49
- console.log(`${r.status}\t${r.filename}`);
50
- }
51
- if (counts.missing > 0 || counts.outdated > 0) {
52
- console.log("Next: aiws codex install-prompts");
53
- }
54
- }
55
-
@@ -1,63 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { loadTemplate } from "../spec.js";
4
- import { normalizeNewlines } from "../hash.js";
5
- import { findManagedBlock } from "../managed-blocks.js";
6
- import { pathExists, readText } from "../fs.js";
7
- import { listTemplateCodexSkills, resolveCodexSkillsDir } from "../codex-skills.js";
8
-
9
- /**
10
- * @param {{ templateId: string, skillsDir?: string }} options
11
- */
12
- export async function codexStatusSkillsCommand(options) {
13
- const templateId = String(options.templateId || "workspace");
14
- const tpl = await loadTemplate(templateId);
15
-
16
- const skillsDir = resolveCodexSkillsDir(options.skillsDir);
17
- const skillsDirIsSymlink = await fs
18
- .lstat(skillsDir)
19
- .then((st) => st.isSymbolicLink())
20
- .catch(() => false);
21
- const skillsDirReal = skillsDirIsSymlink ? await fs.realpath(skillsDir).catch(() => skillsDir) : skillsDir;
22
- const skillFiles = await listTemplateCodexSkills(tpl);
23
-
24
- /** @type {Array<{ name: string, status: "ok" | "missing" | "unmanaged" | "outdated" }>} */
25
- const rows = [];
26
-
27
- for (const sf of skillFiles) {
28
- const destAbs = path.join(skillsDir, sf.skillName, "SKILL.md");
29
- if (!(await pathExists(destAbs))) {
30
- rows.push({ name: sf.skillName, status: "missing" });
31
- continue;
32
- }
33
-
34
- const currentText = normalizeNewlines(await readText(destAbs));
35
- const block = findManagedBlock(currentText, sf.blockId);
36
- if (!block) {
37
- rows.push({ name: sf.skillName, status: "unmanaged" });
38
- continue;
39
- }
40
- rows.push({ name: sf.skillName, status: block.innerText === sf.innerText ? "ok" : "outdated" });
41
- }
42
-
43
- const counts = rows.reduce(
44
- (acc, r) => {
45
- acc[r.status]++;
46
- return acc;
47
- },
48
- /** @type {{ ok: number, missing: number, unmanaged: number, outdated: number }} */ ({ ok: 0, missing: 0, unmanaged: 0, outdated: 0 }),
49
- );
50
-
51
- const header = skillsDirIsSymlink && skillsDirReal !== skillsDir ? `${skillsDir} -> ${skillsDirReal}` : skillsDir;
52
- console.log(`✓ aiws codex status-skills: ${header}`);
53
- console.log(`ok=${counts.ok} missing=${counts.missing} unmanaged=${counts.unmanaged} outdated=${counts.outdated}`);
54
- for (const r of rows) {
55
- console.log(`${r.status}\t${r.name}`);
56
- }
57
- if (counts.ok === 0 && counts.missing === rows.length && skillsDirIsSymlink) {
58
- console.log("Note: skills dir is a symlink; if you installed to a different dir, pass --dir (or set CODEX_HOME).");
59
- }
60
- if (counts.missing > 0 || counts.outdated > 0) {
61
- console.log("Next: aiws codex install-skills");
62
- }
63
- }
@@ -1,55 +0,0 @@
1
- import path from "node:path";
2
- import fs from "node:fs/promises";
3
- import { loadTemplate } from "../spec.js";
4
- import { normalizeNewlines } from "../hash.js";
5
- import { findManagedBlock } from "../managed-blocks.js";
6
- import { copyFile, pathExists, readText } from "../fs.js";
7
- import { codexBackupPathFor, codexBackupStamp, listTemplateCodexPrompts, resolveCodexPromptsDir } from "../codex-prompts.js";
8
-
9
- /**
10
- * @param {{ templateId: string, promptsDir?: string }} options
11
- */
12
- export async function codexUninstallPromptsCommand(options) {
13
- const templateId = String(options.templateId || "workspace");
14
- const tpl = await loadTemplate(templateId);
15
-
16
- const promptsDir = resolveCodexPromptsDir(options.promptsDir);
17
- const promptFiles = await listTemplateCodexPrompts(tpl);
18
-
19
- const backupStamp = codexBackupStamp();
20
- const backupDir = path.join(promptsDir, ".aiws", "backups", "codex-prompts", backupStamp);
21
-
22
- /** @type {string[]} */
23
- const removed = [];
24
- /** @type {string[]} */
25
- const skippedUnmanaged = [];
26
- /** @type {string[]} */
27
- const missing = [];
28
-
29
- for (const pf of promptFiles) {
30
- const destAbs = path.join(promptsDir, pf.filename);
31
- if (!(await pathExists(destAbs))) {
32
- missing.push(pf.filename);
33
- continue;
34
- }
35
-
36
- const currentText = normalizeNewlines(await readText(destAbs));
37
- const block = findManagedBlock(currentText, pf.blockId);
38
- if (!block) {
39
- skippedUnmanaged.push(pf.filename);
40
- continue;
41
- }
42
-
43
- const backup = codexBackupPathFor(promptsDir, pf.filename, backupStamp);
44
- await copyFile(destAbs, backup);
45
- await fs.unlink(destAbs);
46
- removed.push(pf.filename);
47
- }
48
-
49
- console.log(`✓ aiws codex uninstall-prompts: ${promptsDir}`);
50
- if (removed.length > 0) console.log(`removed: ${removed.join(", ")}`);
51
- if (removed.length > 0) console.log(`backup: ${backupDir}`);
52
- if (skippedUnmanaged.length > 0) console.log(`skipped (unmanaged): ${skippedUnmanaged.join(", ")}`);
53
- if (missing.length > 0) console.log(`missing: ${missing.join(", ")}`);
54
- }
55
-
@@ -1,62 +0,0 @@
1
- import path from "node:path";
2
- import fs from "node:fs/promises";
3
- import { loadTemplate } from "../spec.js";
4
- import { normalizeNewlines } from "../hash.js";
5
- import { findManagedBlock } from "../managed-blocks.js";
6
- import { copyFile, pathExists, readText } from "../fs.js";
7
- import { codexSkillsBackupPathFor, codexSkillsBackupStamp, listTemplateCodexSkills, resolveCodexSkillsDir } from "../codex-skills.js";
8
-
9
- /**
10
- * @param {{ templateId: string, skillsDir?: string }} options
11
- */
12
- export async function codexUninstallSkillsCommand(options) {
13
- const templateId = String(options.templateId || "workspace");
14
- const tpl = await loadTemplate(templateId);
15
-
16
- const skillsDir = resolveCodexSkillsDir(options.skillsDir);
17
- const skillFiles = await listTemplateCodexSkills(tpl);
18
-
19
- const backupStamp = codexSkillsBackupStamp();
20
- const backupDir = path.join(skillsDir, ".aiws", "backups", "codex-skills", backupStamp);
21
-
22
- /** @type {string[]} */
23
- const removed = [];
24
- /** @type {string[]} */
25
- const skippedUnmanaged = [];
26
- /** @type {string[]} */
27
- const missing = [];
28
-
29
- for (const sf of skillFiles) {
30
- const destDir = path.join(skillsDir, sf.skillName);
31
- const destAbs = path.join(destDir, "SKILL.md");
32
- if (!(await pathExists(destAbs))) {
33
- missing.push(sf.skillName);
34
- continue;
35
- }
36
-
37
- const currentText = normalizeNewlines(await readText(destAbs));
38
- const block = findManagedBlock(currentText, sf.blockId);
39
- if (!block) {
40
- skippedUnmanaged.push(sf.skillName);
41
- continue;
42
- }
43
-
44
- const backup = codexSkillsBackupPathFor(skillsDir, sf.skillName, backupStamp);
45
- await copyFile(destAbs, backup);
46
- await fs.unlink(destAbs);
47
- // Only remove the directory if it's empty after removing SKILL.md.
48
- try {
49
- await fs.rmdir(destDir);
50
- } catch {
51
- // ignore
52
- }
53
- removed.push(sf.skillName);
54
- }
55
-
56
- console.log(`✓ aiws codex uninstall-skills: ${skillsDir}`);
57
- if (removed.length > 0) console.log(`removed: ${removed.join(", ")}`);
58
- if (removed.length > 0) console.log(`backup: ${backupDir}`);
59
- if (skippedUnmanaged.length > 0) console.log(`skipped (unmanaged): ${skippedUnmanaged.join(", ")}`);
60
- if (missing.length > 0) console.log(`missing: ${missing.join(", ")}`);
61
- }
62
-
@@ -1,205 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import http from "node:http";
3
- import path from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import { UserError } from "../errors.js";
6
- import { runCommand } from "../exec.js";
7
- import { pathExists } from "../fs.js";
8
- import { loadWorkflowStageContracts as loadWorkflowStageContractsSpec } from "../spec.js";
9
- import { computeChangeNextAdvice, computeChangeStatus, validateChangeArtifacts } from "./change.js";
10
-
11
- const __filename = fileURLToPath(import.meta.url);
12
- const __dirname = path.dirname(__filename);
13
-
14
- function send(res, status, headers, body) {
15
- res.writeHead(status, headers);
16
- res.end(body);
17
- }
18
-
19
- function sendJson(res, status, obj) {
20
- send(res, status, { "content-type": "application/json; charset=utf-8" }, JSON.stringify(obj, null, 2));
21
- }
22
-
23
- function guessContentType(p) {
24
- const ext = path.extname(p).toLowerCase();
25
- if (ext === ".html") return "text/html; charset=utf-8";
26
- if (ext === ".css") return "text/css; charset=utf-8";
27
- if (ext === ".js") return "text/javascript; charset=utf-8";
28
- if (ext === ".json") return "application/json; charset=utf-8";
29
- return "application/octet-stream";
30
- }
31
-
32
- function safeJoin(baseDir, rel) {
33
- const abs = path.resolve(baseDir, rel);
34
- const baseAbs = path.resolve(baseDir);
35
- if (!abs.startsWith(baseAbs + path.sep) && abs !== baseAbs) {
36
- throw new UserError("Invalid path.", { exitCode: 1 });
37
- }
38
- return abs;
39
- }
40
-
41
- /**
42
- * @param {string} absPath
43
- */
44
- async function resolveGitRoot(absPath) {
45
- let res;
46
- try {
47
- res = await runCommand("git", ["rev-parse", "--show-toplevel"], { cwd: absPath });
48
- } catch (e) {
49
- throw new UserError("git is required for aiws dashboard commands.", { details: e instanceof Error ? e.message : String(e) });
50
- }
51
- if (res.code !== 0) {
52
- throw new UserError("Not a git repository.", { details: res.stderr || res.stdout });
53
- }
54
- const root = String(res.stdout || "").trim();
55
- if (!root) throw new UserError("Failed to resolve git repository root.");
56
- return root;
57
- }
58
-
59
- /**
60
- * @param {string} gitRoot
61
- */
62
- async function ensureTruthFiles(gitRoot) {
63
- const required = ["AI_PROJECT.md", "AI_WORKSPACE.md", "REQUIREMENTS.md"];
64
- const missing = [];
65
- for (const f of required) {
66
- if (!(await pathExists(path.join(gitRoot, f)))) missing.push(f);
67
- }
68
- if (missing.length > 0) {
69
- throw new UserError("AI Workspace truth files missing.", {
70
- details: `Root: ${gitRoot}\nMissing:\n${missing.map((m) => `- ${m}`).join("\n")}\n\nHint: run \`aiws init .\` (new) or \`aiws update .\` (migrate).`,
71
- exitCode: 1,
72
- });
73
- }
74
- }
75
-
76
- async function listChangeIds(gitRoot) {
77
- const dir = path.join(gitRoot, "changes");
78
- try {
79
- const entries = await fs.readdir(dir, { withFileTypes: true });
80
- return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
81
- } catch {
82
- return [];
83
- }
84
- }
85
-
86
- export async function loadWorkflowStageContracts() {
87
- return loadWorkflowStageContractsSpec();
88
- }
89
-
90
- /**
91
- * @param {string} gitRoot
92
- */
93
- export async function collectDashboardChanges(gitRoot) {
94
- const ids = await listChangeIds(gitRoot);
95
- const changes = [];
96
- for (const id of ids) {
97
- try {
98
- const st = await computeChangeStatus(gitRoot, id);
99
- const nextAdvice = await computeChangeNextAdvice(gitRoot, id);
100
- changes.push({
101
- ...st,
102
- collaboration: st.collaboration?.counts || null,
103
- nextAdvice,
104
- governance: st.governance || null,
105
- });
106
- } catch (e) {
107
- changes.push({ changeId: id, ok: false, error: e instanceof Error ? e.message : String(e) });
108
- }
109
- }
110
- return changes;
111
- }
112
-
113
- function parseUrl(reqUrl) {
114
- const u = new URL(reqUrl || "/", "http://127.0.0.1");
115
- return { pathname: u.pathname, searchParams: u.searchParams };
116
- }
117
-
118
- export async function dashboardServeCommand(options) {
119
- const gitRoot = await resolveGitRoot(process.cwd());
120
- await ensureTruthFiles(gitRoot);
121
-
122
- const host = String(options.host || "127.0.0.1").trim() || "127.0.0.1";
123
- const port = Number.isFinite(options.port) ? options.port : Number.parseInt(String(options.port || "3456"), 10);
124
- if (!Number.isFinite(port) || port < 0 || port > 65535) {
125
- throw new UserError(`Invalid --port: ${options.port}`, { exitCode: 1 });
126
- }
127
-
128
- const dashboardDir = path.join(__dirname, "..", "dashboard");
129
- const assetsDir = path.join(dashboardDir);
130
-
131
- const server = http.createServer(async (req, res) => {
132
- try {
133
- const { pathname, searchParams } = parseUrl(req.url || "/");
134
- if ((req.method || "GET") !== "GET") {
135
- sendJson(res, 405, { ok: false, error: "method not allowed" });
136
- return;
137
- }
138
-
139
- if (pathname === "/api/changes") {
140
- const changes = await collectDashboardChanges(gitRoot);
141
- sendJson(res, 200, { ok: true, changes });
142
- return;
143
- }
144
-
145
- if (pathname === "/api/workflow-stages") {
146
- const stages = await loadWorkflowStageContracts();
147
- sendJson(res, 200, stages);
148
- return;
149
- }
150
-
151
- const m = pathname.match(/^\/api\/change\/([^/]+)\/validate$/);
152
- if (m) {
153
- const changeId = decodeURIComponent(m[1] || "");
154
- const strict = searchParams.get("strict") === "1" || searchParams.get("strict") === "true";
155
- const allowTruthDrift = searchParams.get("allow_truth_drift") === "1" || searchParams.get("allow_truth_drift") === "true";
156
- const checkScope = searchParams.get("check_scope") === "1" || searchParams.get("check_scope") === "true";
157
- const result = await validateChangeArtifacts(gitRoot, changeId, { strict, allowTruthDrift, checkScope });
158
- sendJson(res, 200, result);
159
- return;
160
- }
161
-
162
- if (pathname === "/" || pathname === "/index.html") {
163
- const p = path.join(dashboardDir, "index.html");
164
- const text = await fs.readFile(p);
165
- send(res, 200, { "content-type": "text/html; charset=utf-8" }, text);
166
- return;
167
- }
168
-
169
- if (pathname.startsWith("/assets/")) {
170
- const rel = pathname.replace(/^\/assets\//, "");
171
- const p = safeJoin(assetsDir, rel);
172
- const buf = await fs.readFile(p);
173
- send(res, 200, { "content-type": guessContentType(p) }, buf);
174
- return;
175
- }
176
-
177
- sendJson(res, 404, { ok: false, error: "not found" });
178
- } catch (e) {
179
- sendJson(res, 500, { ok: false, error: e instanceof Error ? e.message : String(e) });
180
- }
181
- });
182
-
183
- await new Promise((resolve, reject) => {
184
- server.once("error", reject);
185
- server.listen({ host, port }, () => resolve());
186
- });
187
-
188
- const addr = server.address();
189
- const realPort = addr && typeof addr === "object" ? addr.port : port;
190
- console.log(`✓ aiws dashboard serve`);
191
- console.log(`root: ${gitRoot}`);
192
- console.log(`url: http://${host}:${realPort}/`);
193
- console.log("note: press Ctrl+C to stop");
194
-
195
- await new Promise((resolve) => {
196
- let stopping = false;
197
- const stop = () => {
198
- if (stopping) return;
199
- stopping = true;
200
- server.close(() => resolve());
201
- };
202
- process.once("SIGINT", stop);
203
- process.once("SIGTERM", stop);
204
- });
205
- }
@@ -1,92 +0,0 @@
1
- import path from "node:path";
2
- import fs from "node:fs/promises";
3
- import { resolveWorkspaceRoot } from "../workspace.js";
4
- import { runCommand } from "../exec.js";
5
- import { pathExists, readText } from "../fs.js";
6
- import { UserError } from "../errors.js";
7
- import { loadTemplate } from "../spec.js";
8
- import { copyTemplateFileToWorkspace } from "../template.js";
9
-
10
- /**
11
- * @param {string} absPath
12
- */
13
- async function resolveGitRoot(absPath) {
14
- let res;
15
- try {
16
- res = await runCommand("git", ["rev-parse", "--show-toplevel"], { cwd: absPath });
17
- } catch (e) {
18
- throw new UserError("git is required for hooks commands.", { details: e instanceof Error ? e.message : String(e) });
19
- }
20
- if (res.code !== 0) {
21
- throw new UserError("Not a git repository.", { details: res.stderr || res.stdout });
22
- }
23
- const root = String(res.stdout || "").trim();
24
- if (!root) throw new UserError("Failed to resolve git repository root.");
25
- return root;
26
- }
27
-
28
- /**
29
- * @param {fs.Stats} st
30
- */
31
- function isExecutable(st) {
32
- return (st.mode & 0o111) !== 0;
33
- }
34
-
35
- /**
36
- * Resolve template id for a repo:
37
- * - Prefer `.aiws/manifest.json` if present.
38
- * - Else default to `workspace`.
39
- *
40
- * @param {string} gitRoot
41
- */
42
- async function resolveTemplateIdForRepo(gitRoot) {
43
- const manifestPath = path.join(gitRoot, ".aiws", "manifest.json");
44
- if (!(await pathExists(manifestPath))) return "workspace";
45
- try {
46
- const stored = JSON.parse(await readText(manifestPath));
47
- const templateId = String(stored.template_id || "").trim();
48
- return templateId || "workspace";
49
- } catch {
50
- return "workspace";
51
- }
52
- }
53
-
54
- /**
55
- * @param {{ targetPath: string }} options
56
- */
57
- export async function hooksInstallCommand(options) {
58
- const workspaceRoot = await resolveWorkspaceRoot(options.targetPath, { create: false });
59
- const gitRoot = await resolveGitRoot(workspaceRoot);
60
-
61
- const templateId = await resolveTemplateIdForRepo(gitRoot);
62
- const tpl = await loadTemplate(templateId);
63
-
64
- const hookFiles = [".githooks/commit-msg", ".githooks/pre-commit", ".githooks/pre-push"];
65
- /** @type {string[]} */
66
- const created = [];
67
- /** @type {string[]} */
68
- const chmodded = [];
69
-
70
- for (const rel of hookFiles) {
71
- const abs = path.join(gitRoot, ...rel.split("/"));
72
- if (!(await pathExists(abs))) {
73
- await copyTemplateFileToWorkspace({ templateDir: tpl.templateDir, workspaceRoot: gitRoot, relPosix: rel, chmod: 0o755 });
74
- created.push(rel);
75
- continue;
76
- }
77
- const st = await fs.stat(abs);
78
- if (!isExecutable(st)) {
79
- await fs.chmod(abs, 0o755);
80
- chmodded.push(rel);
81
- }
82
- }
83
-
84
- const setRes = await runCommand("git", ["config", "core.hooksPath", ".githooks"], { cwd: gitRoot });
85
- if (setRes.code !== 0) {
86
- throw new UserError("Failed to set git core.hooksPath.", { details: setRes.stderr || setRes.stdout });
87
- }
88
-
89
- console.log(`✓ aiws hooks install: ${gitRoot}`);
90
- if (created.length > 0) console.log(`created: ${created.join(", ")}`);
91
- if (chmodded.length > 0) console.log(`chmod: ${chmodded.join(", ")}`);
92
- }