@entelligentsia/forgecli 0.8.4 → 0.9.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 (169) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/bin/argv.d.ts +2 -2
  3. package/dist/bin/argv.js +17 -0
  4. package/dist/bin/argv.js.map +1 -1
  5. package/dist/bin/config.d.ts +69 -0
  6. package/dist/bin/config.js +315 -0
  7. package/dist/bin/config.js.map +1 -0
  8. package/dist/bin/doctor.d.ts +1 -0
  9. package/dist/bin/doctor.js +12 -0
  10. package/dist/bin/doctor.js.map +1 -1
  11. package/dist/bin/forge.js +7 -0
  12. package/dist/bin/forge.js.map +1 -1
  13. package/dist/extensions/forgecli/config-command.d.ts +8 -0
  14. package/dist/extensions/forgecli/config-command.js +66 -0
  15. package/dist/extensions/forgecli/config-command.js.map +1 -0
  16. package/dist/extensions/forgecli/config-layer.d.ts +38 -0
  17. package/dist/extensions/forgecli/config-layer.js +68 -0
  18. package/dist/extensions/forgecli/config-layer.js.map +1 -0
  19. package/dist/extensions/forgecli/config-tui/component.d.ts +35 -0
  20. package/dist/extensions/forgecli/config-tui/component.js +236 -0
  21. package/dist/extensions/forgecli/config-tui/component.js.map +1 -0
  22. package/dist/extensions/forgecli/config-tui/handler.d.ts +40 -0
  23. package/dist/extensions/forgecli/config-tui/handler.js +240 -0
  24. package/dist/extensions/forgecli/config-tui/handler.js.map +1 -0
  25. package/dist/extensions/forgecli/config-tui/index.d.ts +5 -0
  26. package/dist/extensions/forgecli/config-tui/index.js +5 -0
  27. package/dist/extensions/forgecli/config-tui/index.js.map +1 -0
  28. package/dist/extensions/forgecli/config-tui/keys.d.ts +26 -0
  29. package/dist/extensions/forgecli/config-tui/keys.js +33 -0
  30. package/dist/extensions/forgecli/config-tui/keys.js.map +1 -0
  31. package/dist/extensions/forgecli/config-tui/plugin-config-reader.d.ts +23 -0
  32. package/dist/extensions/forgecli/config-tui/plugin-config-reader.js +58 -0
  33. package/dist/extensions/forgecli/config-tui/plugin-config-reader.js.map +1 -0
  34. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.d.ts +7 -0
  35. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js +83 -0
  36. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js.map +1 -0
  37. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.d.ts +11 -0
  38. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js +54 -0
  39. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js.map +1 -0
  40. package/dist/extensions/forgecli/config-tui/screens/override-editor.d.ts +11 -0
  41. package/dist/extensions/forgecli/config-tui/screens/override-editor.js +233 -0
  42. package/dist/extensions/forgecli/config-tui/screens/override-editor.js.map +1 -0
  43. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.d.ts +7 -0
  44. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js +91 -0
  45. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js.map +1 -0
  46. package/dist/extensions/forgecli/config-tui/screens/overrides-list.d.ts +7 -0
  47. package/dist/extensions/forgecli/config-tui/screens/overrides-list.js +71 -0
  48. package/dist/extensions/forgecli/config-tui/screens/overrides-list.js.map +1 -0
  49. package/dist/extensions/forgecli/config-tui/screens/persona-editor.d.ts +10 -0
  50. package/dist/extensions/forgecli/config-tui/screens/persona-editor.js +182 -0
  51. package/dist/extensions/forgecli/config-tui/screens/persona-editor.js.map +1 -0
  52. package/dist/extensions/forgecli/config-tui/screens/persona-picker.d.ts +7 -0
  53. package/dist/extensions/forgecli/config-tui/screens/persona-picker.js +76 -0
  54. package/dist/extensions/forgecli/config-tui/screens/persona-picker.js.map +1 -0
  55. package/dist/extensions/forgecli/config-tui/screens/personas-list.d.ts +7 -0
  56. package/dist/extensions/forgecli/config-tui/screens/personas-list.js +98 -0
  57. package/dist/extensions/forgecli/config-tui/screens/personas-list.js.map +1 -0
  58. package/dist/extensions/forgecli/config-tui/screens/shared.d.ts +29 -0
  59. package/dist/extensions/forgecli/config-tui/screens/shared.js +100 -0
  60. package/dist/extensions/forgecli/config-tui/screens/shared.js.map +1 -0
  61. package/dist/extensions/forgecli/config-tui/screens/show-resolved.d.ts +23 -0
  62. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js +128 -0
  63. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js.map +1 -0
  64. package/dist/extensions/forgecli/config-tui/screens/tier-menu.d.ts +7 -0
  65. package/dist/extensions/forgecli/config-tui/screens/tier-menu.js +135 -0
  66. package/dist/extensions/forgecli/config-tui/screens/tier-menu.js.map +1 -0
  67. package/dist/extensions/forgecli/config-tui/screens/tier-picker.d.ts +9 -0
  68. package/dist/extensions/forgecli/config-tui/screens/tier-picker.js +122 -0
  69. package/dist/extensions/forgecli/config-tui/screens/tier-picker.js.map +1 -0
  70. package/dist/extensions/forgecli/config-tui/screens/types.d.ts +24 -0
  71. package/dist/extensions/forgecli/config-tui/screens/types.js +5 -0
  72. package/dist/extensions/forgecli/config-tui/screens/types.js.map +1 -0
  73. package/dist/extensions/forgecli/config-tui/screens.d.ts +24 -0
  74. package/dist/extensions/forgecli/config-tui/screens.js +78 -0
  75. package/dist/extensions/forgecli/config-tui/screens.js.map +1 -0
  76. package/dist/extensions/forgecli/config-tui/state/buffer.d.ts +11 -0
  77. package/dist/extensions/forgecli/config-tui/state/buffer.js +91 -0
  78. package/dist/extensions/forgecli/config-tui/state/buffer.js.map +1 -0
  79. package/dist/extensions/forgecli/config-tui/state/constants.d.ts +4 -0
  80. package/dist/extensions/forgecli/config-tui/state/constants.js +14 -0
  81. package/dist/extensions/forgecli/config-tui/state/constants.js.map +1 -0
  82. package/dist/extensions/forgecli/config-tui/state/index.d.ts +6 -0
  83. package/dist/extensions/forgecli/config-tui/state/index.js +9 -0
  84. package/dist/extensions/forgecli/config-tui/state/index.js.map +1 -0
  85. package/dist/extensions/forgecli/config-tui/state/init.d.ts +2 -0
  86. package/dist/extensions/forgecli/config-tui/state/init.js +30 -0
  87. package/dist/extensions/forgecli/config-tui/state/init.js.map +1 -0
  88. package/dist/extensions/forgecli/config-tui/state/model.d.ts +192 -0
  89. package/dist/extensions/forgecli/config-tui/state/model.js +4 -0
  90. package/dist/extensions/forgecli/config-tui/state/model.js.map +1 -0
  91. package/dist/extensions/forgecli/config-tui/state/reducer.d.ts +2 -0
  92. package/dist/extensions/forgecli/config-tui/state/reducer.js +212 -0
  93. package/dist/extensions/forgecli/config-tui/state/reducer.js.map +1 -0
  94. package/dist/extensions/forgecli/config-tui/state/selectors.d.ts +91 -0
  95. package/dist/extensions/forgecli/config-tui/state/selectors.js +231 -0
  96. package/dist/extensions/forgecli/config-tui/state/selectors.js.map +1 -0
  97. package/dist/extensions/forgecli/config-tui/state.d.ts +6 -0
  98. package/dist/extensions/forgecli/config-tui/state.js +11 -0
  99. package/dist/extensions/forgecli/config-tui/state.js.map +1 -0
  100. package/dist/extensions/forgecli/config-tui/theme.d.ts +37 -0
  101. package/dist/extensions/forgecli/config-tui/theme.js +88 -0
  102. package/dist/extensions/forgecli/config-tui/theme.js.map +1 -0
  103. package/dist/extensions/forgecli/config-tui/tier-meta.d.ts +28 -0
  104. package/dist/extensions/forgecli/config-tui/tier-meta.js +69 -0
  105. package/dist/extensions/forgecli/config-tui/tier-meta.js.map +1 -0
  106. package/dist/extensions/forgecli/config-writer.d.ts +16 -0
  107. package/dist/extensions/forgecli/config-writer.js +63 -0
  108. package/dist/extensions/forgecli/config-writer.js.map +1 -0
  109. package/dist/extensions/forgecli/fix-bug.js +85 -1
  110. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  111. package/dist/extensions/forgecli/forge-cli-schema.json +54 -0
  112. package/dist/extensions/forgecli/forge-commands.js +3 -8
  113. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  114. package/dist/extensions/forgecli/forge-subagent.d.ts +13 -0
  115. package/dist/extensions/forgecli/forge-subagent.js +19 -0
  116. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  117. package/dist/extensions/forgecli/index.js +16 -0
  118. package/dist/extensions/forgecli/index.js.map +1 -1
  119. package/dist/extensions/forgecli/input-router.d.ts +33 -0
  120. package/dist/extensions/forgecli/input-router.js +133 -0
  121. package/dist/extensions/forgecli/input-router.js.map +1 -0
  122. package/dist/extensions/forgecli/model-resolver.d.ts +32 -0
  123. package/dist/extensions/forgecli/model-resolver.js +65 -0
  124. package/dist/extensions/forgecli/model-resolver.js.map +1 -0
  125. package/dist/extensions/forgecli/model-validator.d.ts +29 -0
  126. package/dist/extensions/forgecli/model-validator.js +107 -0
  127. package/dist/extensions/forgecli/model-validator.js.map +1 -0
  128. package/dist/extensions/forgecli/run-sprint.js +59 -0
  129. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  130. package/dist/extensions/forgecli/run-task.js +93 -1
  131. package/dist/extensions/forgecli/run-task.js.map +1 -1
  132. package/dist/extensions/forgecli/thread-switcher.js +5 -2
  133. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  134. package/dist/extensions/forgecli/whats-new-widget.js +5 -2
  135. package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
  136. package/package.json +11 -3
  137. package/dist/extensions/forgecli/review-command.d.ts +0 -2
  138. package/dist/extensions/forgecli/review-command.js +0 -184
  139. package/dist/extensions/forgecli/review-command.js.map +0 -1
  140. package/dist/forge-payload/.tools/banners.cjs +0 -435
  141. package/dist/forge-payload/.tools/build-context-pack.cjs +0 -290
  142. package/dist/forge-payload/.tools/build-init-context.cjs +0 -322
  143. package/dist/forge-payload/.tools/build-overlay.cjs +0 -326
  144. package/dist/forge-payload/.tools/build-persona-pack.cjs +0 -226
  145. package/dist/forge-payload/.tools/collate.cjs +0 -1041
  146. package/dist/forge-payload/.tools/generation-manifest.cjs +0 -311
  147. package/dist/forge-payload/.tools/lib/forge-root.cjs +0 -59
  148. package/dist/forge-payload/.tools/lib/paths.cjs +0 -29
  149. package/dist/forge-payload/.tools/lib/pricing.cjs +0 -165
  150. package/dist/forge-payload/.tools/lib/project-root.cjs +0 -32
  151. package/dist/forge-payload/.tools/lib/result.js +0 -40
  152. package/dist/forge-payload/.tools/lib/store-facade.cjs +0 -162
  153. package/dist/forge-payload/.tools/lib/store-nlp.cjs +0 -250
  154. package/dist/forge-payload/.tools/lib/store-query-exec.cjs +0 -272
  155. package/dist/forge-payload/.tools/lib/validate.js +0 -141
  156. package/dist/forge-payload/.tools/manage-config.cjs +0 -340
  157. package/dist/forge-payload/.tools/manage-versions.cjs +0 -365
  158. package/dist/forge-payload/.tools/package.json +0 -3
  159. package/dist/forge-payload/.tools/parse-gates.cjs +0 -151
  160. package/dist/forge-payload/.tools/parse-verdict.cjs +0 -67
  161. package/dist/forge-payload/.tools/preflight-gate.cjs +0 -350
  162. package/dist/forge-payload/.tools/prompts/sprint-plan-prompt.md +0 -70
  163. package/dist/forge-payload/.tools/schemas/task-list.schema.json +0 -53
  164. package/dist/forge-payload/.tools/seed-store.cjs +0 -237
  165. package/dist/forge-payload/.tools/store-cli.cjs +0 -1226
  166. package/dist/forge-payload/.tools/store-query.cjs +0 -319
  167. package/dist/forge-payload/.tools/store.cjs +0 -315
  168. package/dist/forge-payload/.tools/substitute-placeholders.cjs +0 -625
  169. package/dist/forge-payload/.tools/validate-store.cjs +0 -593
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@entelligentsia/forgecli",
3
- "version": "0.8.4",
3
+ "version": "0.9.0",
4
4
  "description": "Forge SDLC ported onto @earendil-works/pi-coding-agent — production launcher with three bin aliases (forge/forgecli/4ge). Bundles a curated fork of pi-coding-agent vendored under earendil-works names.",
5
5
  "license": "MIT",
6
6
  "author": "Entelligentsia",
@@ -70,10 +70,11 @@
70
70
  "js-yaml"
71
71
  ],
72
72
  "dependencies": {
73
- "@earendil-works/pi-coding-agent": "file:./vendor-pi/earendil-works-pi-coding-agent-0.75.1-forge.4.tgz",
74
73
  "@earendil-works/pi-agent-core": "file:./vendor-pi/earendil-works-pi-agent-core-0.75.1.tgz",
75
74
  "@earendil-works/pi-ai": "file:./vendor-pi/earendil-works-pi-ai-0.75.1.tgz",
75
+ "@earendil-works/pi-coding-agent": "0.75.1-forge.4",
76
76
  "@earendil-works/pi-tui": "file:./vendor-pi/earendil-works-pi-tui-0.75.1.tgz",
77
+ "ajv": "^8.20.0",
77
78
  "js-yaml": "^4.1.0",
78
79
  "typebox": "^1.1.24"
79
80
  },
@@ -89,5 +90,12 @@
89
90
  },
90
91
  "engines": {
91
92
  "node": ">=20.6.0"
92
- }
93
+ },
94
+ "bundleDependencies": [
95
+ "@earendil-works/pi-coding-agent",
96
+ "@earendil-works/pi-agent-core",
97
+ "@earendil-works/pi-ai",
98
+ "@earendil-works/pi-tui",
99
+ "js-yaml"
100
+ ]
93
101
  }
@@ -1,2 +0,0 @@
1
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
- export declare function registerReviewCommand(pi: ExtensionAPI, forgeRoot: string | null): void;
@@ -1,184 +0,0 @@
1
- import * as fs from "node:fs/promises";
2
- import * as fsSync from "node:fs";
3
- import * as path from "node:path";
4
- import { execFile } from "node:child_process";
5
- import { promisify } from "node:util";
6
- import { startReviewServer } from "./review-server.js";
7
- const execFileAsync = promisify(execFile);
8
- function resolveToolDir(forgeRoot) {
9
- const nested = path.join(forgeRoot, "tools");
10
- try {
11
- if (fsSync.statSync(nested).isDirectory())
12
- return nested;
13
- }
14
- catch {
15
- // nested missing — fall through to flat
16
- }
17
- return forgeRoot;
18
- }
19
- async function runStoreCli(toolDir, argv, cwd) {
20
- const toolPath = path.join(toolDir, "store-cli.cjs");
21
- const result = await execFileAsync("node", [toolPath, ...argv], {
22
- cwd,
23
- encoding: "utf8",
24
- timeout: 10_000,
25
- });
26
- return JSON.parse(result.stdout);
27
- }
28
- /**
29
- * Resolution cascade:
30
- * 1. @path → use the path directly as artifact directory
31
- * 2. Task ID → store-query query --task <id>
32
- * 3. Bug ID → store-query query --bug <id>
33
- * 4. Feature ID → store-query query --feature <id>
34
- * 5. Sprint ID → store-query query --sprint <id>
35
- * 6. NLP → store-query nlp "<query>"
36
- */
37
- async function resolveArg(arg, toolDir, cwd, ctx) {
38
- // ── 1. @path ──────────────────────────────────────────────────────────────
39
- if (arg.startsWith("@")) {
40
- const rawPath = arg.slice(1).trim();
41
- const resolved = path.isAbsolute(rawPath) ? rawPath : path.join(cwd, rawPath);
42
- return { dir: resolved };
43
- }
44
- const taskIdRe = /^([A-Z0-9]+-)?S\d+-T\d+$/i;
45
- const sprintIdRe = /^([A-Z0-9]+-)?S\d+$/i;
46
- const bugIdRe = /^([A-Z0-9]+-)?B\d+$/i;
47
- const featureIdRe = /^([A-Z0-9]+-)?F\d+$/i;
48
- // ── 2-5. Structured ID → store-query query flags ─────────────────────────
49
- let structuredResult = null;
50
- try {
51
- if (taskIdRe.test(arg)) {
52
- ctx.ui.setStatus("forge:review", `Looking up task ${arg}…`);
53
- structuredResult = await runStoreCli(toolDir, ["query", "--task", arg], cwd);
54
- }
55
- else if (bugIdRe.test(arg)) {
56
- ctx.ui.setStatus("forge:review", `Looking up bug ${arg}…`);
57
- structuredResult = await runStoreCli(toolDir, ["query", "--bug", arg], cwd);
58
- }
59
- else if (featureIdRe.test(arg)) {
60
- ctx.ui.setStatus("forge:review", `Looking up feature ${arg}…`);
61
- structuredResult = await runStoreCli(toolDir, ["query", "--feature", arg], cwd);
62
- }
63
- else if (sprintIdRe.test(arg)) {
64
- ctx.ui.setStatus("forge:review", `Looking up sprint ${arg}…`);
65
- structuredResult = await runStoreCli(toolDir, ["query", "--sprint", arg], cwd);
66
- }
67
- }
68
- catch {
69
- // structured query failed — fall through to NLP
70
- }
71
- if (structuredResult?.results?.length > 0) {
72
- return pickFromResults(structuredResult.results, arg, ctx);
73
- }
74
- // ── 6. NLP fallback ───────────────────────────────────────────────────────
75
- ctx.ui.setStatus("forge:review", `Searching Forge store: "${arg}"…`);
76
- const nlpResult = await runStoreCli(toolDir, ["nlp", arg], cwd);
77
- const items = (nlpResult.results || []).filter((r) => ["task", "sprint", "bug", "feature"].includes(r.type));
78
- if (items.length === 0) {
79
- ctx.ui.setStatus("forge:review", undefined);
80
- ctx.ui.notify(`No records found matching "${arg}"`, "warning");
81
- return null;
82
- }
83
- return pickFromResults(items, arg, ctx);
84
- }
85
- async function pickFromResults(items, arg, ctx) {
86
- if (items.length === 1) {
87
- return { item: items[0] };
88
- }
89
- ctx.ui.setStatus("forge:review", undefined);
90
- const options = items.map((t) => `${t.id} (${t.type}): ${t.title}`);
91
- const selection = await ctx.ui.select(`Multiple records found for "${arg}". Select one:`, options);
92
- if (!selection)
93
- return null;
94
- const selectedId = selection.split(" ")[0].trim();
95
- return { item: items.find((t) => t.id === selectedId) };
96
- }
97
- export function registerReviewCommand(pi, forgeRoot) {
98
- pi.registerCommand("forge:review", {
99
- description: "Review a Forge artifact in the browser and provide inline feedback",
100
- async handler(args, ctx) {
101
- if (!forgeRoot) {
102
- ctx.ui.notify("forge:review — no Forge project at cwd; run /forge:init to bootstrap", "warning");
103
- return;
104
- }
105
- const arg = args.trim();
106
- if (!arg) {
107
- ctx.ui.notify("Usage: /forge:review <task-id|sprint-id|@path|natural language>\n" +
108
- "Examples: /forge:review S01-T01 | /forge:review S01 | " +
109
- "/forge:review @engineering/sprints/HELLO-S01/HELLO-S01-T01 | " +
110
- "/forge:review the i18n task", "error");
111
- return;
112
- }
113
- const toolDir = resolveToolDir(forgeRoot);
114
- const resolved = await resolveArg(arg, toolDir, ctx.cwd, ctx).catch((err) => {
115
- ctx.ui.setStatus("forge:review", undefined);
116
- ctx.ui.notify(`Store query failed: ${err.message}`, "error");
117
- return null;
118
- });
119
- if (!resolved)
120
- return;
121
- // Determine artifact directory and display label
122
- let taskDir;
123
- let label;
124
- if ("dir" in resolved) {
125
- taskDir = resolved.dir;
126
- label = path.basename(taskDir);
127
- }
128
- else {
129
- const item = resolved.item;
130
- if (!item.fileRefs?.md) {
131
- ctx.ui.notify(`No markdown index found for ${item.id}`, "error");
132
- return;
133
- }
134
- taskDir = path.dirname(path.join(ctx.cwd, item.fileRefs.md));
135
- label = `${item.id} — ${item.title}`;
136
- ctx.ui.notify(`Resolved to ${item.type}: ${item.id} (${item.title})`, "info");
137
- }
138
- // List markdown files in artifact directory
139
- let files;
140
- try {
141
- files = await fs.readdir(taskDir);
142
- }
143
- catch {
144
- ctx.ui.notify(`No artifacts found at ${taskDir}`, "warning");
145
- return;
146
- }
147
- const mdFiles = files.filter(f => f.endsWith(".md"));
148
- if (mdFiles.length === 0) {
149
- ctx.ui.notify(`No markdown artifacts found at ${taskDir}`, "info");
150
- return;
151
- }
152
- const selectedFile = await ctx.ui.select(`Select artifact to review for ${label}:`, mdFiles);
153
- if (!selectedFile)
154
- return;
155
- const artifactPath = path.join(taskDir, selectedFile);
156
- ctx.ui.notify(`Starting local review server for ${selectedFile}…`, "info");
157
- ctx.ui.setStatus("forge:review", "Waiting for browser review…");
158
- try {
159
- const feedback = await startReviewServer(artifactPath, `${label} — ${selectedFile}`);
160
- ctx.ui.setStatus("forge:review", undefined);
161
- if (feedback && feedback.length > 0) {
162
- ctx.ui.notify(`Received ${feedback.length} feedback item(s). Sending to Forge…`, "info");
163
- const itemType = "item" in resolved ? resolved.item.type : "artifact";
164
- const itemId = "item" in resolved ? resolved.item.id : label;
165
- let promptText = `I have reviewed the artifact \`${selectedFile}\` for ${itemType} ${itemId}. Here is my inline feedback:\n\n`;
166
- for (const fb of feedback) {
167
- promptText += `> **Text:** "${fb.selectedText}"\n`;
168
- promptText += `> **Feedback:** ${fb.comment}\n\n`;
169
- }
170
- promptText += `Please process this feedback and update the artifact accordingly.`;
171
- await pi.sendUserMessage(promptText);
172
- }
173
- else {
174
- ctx.ui.notify("Review completed with no feedback submitted.", "info");
175
- }
176
- }
177
- catch (err) {
178
- ctx.ui.setStatus("forge:review", undefined);
179
- ctx.ui.notify(`forge:review error: ${err.message}`, "error");
180
- }
181
- },
182
- });
183
- }
184
- //# sourceMappingURL=review-command.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"review-command.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/review-command.ts"],"names":[],"mappings":"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"}
@@ -1,435 +0,0 @@
1
- 'use strict';
2
-
3
- // Forge Banner Library
4
- // Reusable agent identity display for tools, hooks, and skills.
5
- //
6
- // Render modes:
7
- // render(name) — full ASCII art block + emoji + name + tagline
8
- // badge(name) — single line: emoji + bold name + dim tagline
9
- // mark(name) — emoji only (for use alongside 〇△× status marks)
10
- // progressBar(n,total,opt) — unicode block bar with optional gradient + label
11
- // subtitle(text, opts) — dim italic line for under-banner taglines
12
- // phaseHeader(...) — convenience: badge + em-dash banner + progress bar
13
- //
14
- // Plain mode: ANSI escapes are stripped when any of these is true:
15
- // - env FORGE_BANNERS_PLAIN is set to a non-empty value
16
- // - env NO_COLOR is set to a non-empty value
17
- // - process.stdout.isTTY === false
18
- // - CLI flag --plain is passed
19
- //
20
- // Usage (module):
21
- // const banners = require('./banners.cjs');
22
- // console.log(banners.render('forge'));
23
- // console.log(banners.progressBar(5, 12, { label: 'Templates', color: [255,208,122] }));
24
- //
25
- // Usage (CLI):
26
- // node banners.cjs forge
27
- // node banners.cjs --badge north
28
- // node banners.cjs --mark tide
29
- // node banners.cjs --gallery
30
- // node banners.cjs --list
31
- // node banners.cjs --plain forge
32
- // node banners.cjs --subtitle "Forging your SDLC"
33
- // node banners.cjs --progress 5 12 "Templates"
34
- // node banners.cjs --phase 7 12 "Workflows" ember fast
35
-
36
- // ─── Plain-mode detection ─────────────────────────────────────────────────────
37
- // Resolved at call-time so tests can flip env vars dynamically.
38
- function isPlain() {
39
- if (process.env.FORGE_BANNERS_PLAIN) return true;
40
- if (process.env.NO_COLOR) return true;
41
- if (process.stdout && process.stdout.isTTY === false) return true;
42
- return false;
43
- }
44
-
45
- // Strip ANSI escape sequences (CSI). Conservative — matches \x1b[...m and friends.
46
- const ANSI_RE = /\x1b\[[0-9;]*[A-Za-z]/g;
47
- function stripAnsi(s) {
48
- return String(s).replace(ANSI_RE, '');
49
- }
50
-
51
- // Soft override — set by `--plain` CLI flag to force plain mode for one run.
52
- let FORCE_PLAIN = false;
53
-
54
- // ─── ANSI helpers ─────────────────────────────────────────────────────────────
55
- const R = '\x1b[0m';
56
- const B = '\x1b[1m';
57
- const D = '\x1b[2m';
58
- const I = '\x1b[3m';
59
- const f = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
60
-
61
- // ─── Mode tints ───────────────────────────────────────────────────────────────
62
- // Mode-aware accent colour for progress bars and subtitles. Used by phaseHeader.
63
- const MODE_TINTS = {
64
- fast: [255, 208, 122], // lantern yellow
65
- full: [255, 138, 60], // ember orange
66
- };
67
-
68
- // ─── Zen blue ─────────────────────────────────────────────────────────────────
69
- // System-wide horizontal-rule tint. Applied to em-dash separators in
70
- // phaseHeader, ruleLine, and ensure-ready.cjs --announce framing. Picked to
71
- // read calm and cool without competing with banner colours.
72
- const ZEN_BLUE = [100, 140, 200];
73
-
74
- // ─── Banner registry ───────────────────────────────────────────────────────────
75
- const BANNERS = {
76
-
77
- ember: {
78
- emoji: '🔥',
79
- tagline: 'heat · ignition · drive',
80
- name: 'EMBER',
81
- kanji: '炎',
82
- color: [255, 170, 60],
83
- art: ` ${f(255,240,100)}) ${f(255,200,50)}) ${f(255,140,20)}(${f(230,80,10)}🔥${f(255,140,20)}) ${f(230,80,10)}~∿~ ${f(170,30,5)}≋≋≋`,
84
- },
85
-
86
- tide: {
87
- emoji: '🌊',
88
- tagline: 'rhythm · pull · depth',
89
- name: 'TIDE',
90
- kanji: '潮',
91
- color: [110, 200, 255],
92
- art: ` ${f(210,240,255)}∿ ${f(130,200,245)}≋≋≋ ${f(60,140,210)}≋≋≋ ${f(25,85,175)}▓▓▓ ${f(10,45,130)}▓▓▓`,
93
- },
94
-
95
- oracle: {
96
- emoji: '🌕',
97
- tagline: 'sight · pattern · knowing',
98
- name: 'ORACLE',
99
- kanji: '神託',
100
- color: [210, 160, 255],
101
- art: ` ${f(160,80,240)}· ◌ ${f(190,110,255)}◎ ${f(255,220,100)}◉ ${f(190,110,255)}◎ ${f(160,80,240)}◌ ·`,
102
- },
103
-
104
- rift: {
105
- emoji: '⚡',
106
- tagline: 'edge · fracture · crossing',
107
- name: 'RIFT',
108
- kanji: '裂',
109
- color: [100, 255, 240],
110
- art: ` ${f(0,240,230)}▓▒░ ${f(180,0,220)}╲ ${f(0,255,240)}⚡${f(180,0,220)} ╱ ${f(0,240,230)}░▒▓`,
111
- },
112
-
113
- bloom: {
114
- emoji: '🌸',
115
- tagline: 'growth · opening · becoming',
116
- name: 'BLOOM',
117
- kanji: '開花',
118
- color: [255, 160, 190],
119
- art: ` ${f(255,160,200)}✿ ✿ ${f(255,120,170)}✾ ${f(255,220,100)}✽ ${f(255,120,170)}✾ ${f(255,160,200)}✿ ✿`,
120
- },
121
-
122
- north: {
123
- emoji: '🧭',
124
- tagline: 'direction · clarity · cold',
125
- name: 'NORTH',
126
- kanji: '北',
127
- color: [190, 225, 255],
128
- art: ` ${f(200,230,255)}✦ ${f(150,195,240)}╱ ${f(100,160,230)}◈ ${f(150,195,240)}╲ ${f(200,230,255)}✦`,
129
- },
130
-
131
- lumen: {
132
- emoji: '✨',
133
- tagline: 'light · warmth · clarity',
134
- name: 'LUMEN',
135
- kanji: '光',
136
- color: [255, 245, 150],
137
- art: ` ${f(255,255,200)}✧ ${f(255,245,160)}── ${f(255,255,255)}◉ ${f(255,245,160)}── ${f(255,255,200)}✧`,
138
- },
139
-
140
- forge: {
141
- emoji: '🔨',
142
- tagline: 'making · heat · craft',
143
- name: 'FORGE',
144
- kanji: '鍛冶',
145
- color: [255, 160, 40],
146
- art: ` ${f(255,230,80)}✦ ${f(200,80,20)}▄${f(230,100,30)}▓▓▓▓▓${f(200,80,20)}▄ ${f(255,160,40)}≋ ≋ ≋`,
147
- },
148
-
149
- drift: {
150
- emoji: '🍃',
151
- tagline: 'ease · letting go · flow',
152
- name: 'DRIFT',
153
- kanji: '漂流',
154
- color: [150, 200, 165],
155
- art: ` ${f(160,200,170)}· ${f(140,180,155)}· ${f(120,165,140)}· ${f(100,150,125)}· ${f(80,135,110)}·`,
156
- },
157
-
158
- void: {
159
- emoji: '🌑',
160
- tagline: 'depth · silence · potential',
161
- name: 'VOID',
162
- kanji: '虚空',
163
- color: [130, 100, 200],
164
- art: ` ${f(30,20,60)} · ${f(70,50,120)}◌ ${f(50,35,90)}· `,
165
- },
166
-
167
- entelligentsia: {
168
- emoji: '🔗',
169
- tagline: 'linked · intellect · becoming',
170
- name: 'ENTELLIGENTSIA',
171
- kanji: '知性',
172
- color: [140, 200, 60],
173
- art: ` ${f(110,110,115)}╭──╯ ${f(140,200,60)}─╮ ╭─ ${f(110,110,115)}╰──╮`,
174
- },
175
-
176
- };
177
-
178
- // ─── Render helpers ────────────────────────────────────────────────────────────
179
-
180
- /** Dim dot rule — use between banners in a gallery */
181
- function rule() {
182
- return ` ${f(45,45,65)}${'·'.repeat(32)}${R}`;
183
- }
184
-
185
- /**
186
- * Full banner: ASCII art block + emoji + name + tagline.
187
- * @param {string} name Banner key (case-insensitive).
188
- * @returns {string}
189
- */
190
- function render(name) {
191
- const b = _get(name);
192
- const [r, g, bl] = b.color;
193
- const kanji = b.kanji ? ` ${D}${f(r,g,bl)}${b.kanji}${R}` : '';
194
- const label = ` ${b.emoji} ${B}${f(r,g,bl)}${b.name}${R}${kanji} ${D}${f(r,g,bl)}${b.tagline}${R}`;
195
- const out = '\n' + b.art + R + '\n' + label + '\n';
196
- return _maybePlain(out);
197
- }
198
-
199
- /**
200
- * Badge: single line — emoji + bold name + dim tagline.
201
- * Fits inline in status output or skill headers.
202
- * @param {string} name
203
- * @returns {string}
204
- */
205
- function badge(name) {
206
- const b = _get(name);
207
- const [r, g, bl] = b.color;
208
- const kanji = b.kanji ? ` ${D}${f(r,g,bl)}${b.kanji}${R}` : '';
209
- return _maybePlain(`${b.emoji} ${B}${f(r,g,bl)}${b.name}${R}${kanji} ${D}${f(r,g,bl)}${b.tagline}${R}`);
210
- }
211
-
212
- /**
213
- * Mark: emoji only.
214
- * Use alongside 〇△× status marks for agent attribution.
215
- * @param {string} name
216
- * @returns {string}
217
- */
218
- function mark(name) {
219
- return _get(name).emoji;
220
- }
221
-
222
- /**
223
- * Progress bar: unicode block bar with optional gradient tint and label.
224
- * ▰▰▰▰▰▱▱▱▱▱▱▱ Phase 5/12 · Templates
225
- *
226
- * @param {number} n Filled cells (clamped to [0, total])
227
- * @param {number} total Total cells across the bar's logical range
228
- * @param {object} [opts]
229
- * @param {number} [opts.width=12] Cells in the bar (independent of n/total)
230
- * @param {number[]} [opts.color] [r,g,b] tint for filled segment
231
- * @param {string} [opts.label] Trailing label after the bar
232
- * @param {string} [opts.fillGlyph='▰'] Override filled cell glyph
233
- * @param {string} [opts.emptyGlyph='▱'] Override empty cell glyph
234
- * @returns {string}
235
- */
236
- function progressBar(n, total, opts) {
237
- const o = opts || {};
238
- const width = Math.max(1, o.width || 12);
239
- const fillGlyph = o.fillGlyph || '▰';
240
- const emptyGlyph = o.emptyGlyph || '▱';
241
- const safeTotal = Math.max(1, total || 1);
242
- const safeN = Math.max(0, Math.min(n || 0, safeTotal));
243
- const filledCells = Math.round((safeN / safeTotal) * width);
244
- const emptyCells = width - filledCells;
245
-
246
- let bar = '';
247
- if (filledCells > 0) {
248
- const tint = Array.isArray(o.color) ? f(o.color[0], o.color[1], o.color[2]) : '';
249
- const reset = tint ? R : '';
250
- bar += `${tint}${fillGlyph.repeat(filledCells)}${reset}`;
251
- }
252
- if (emptyCells > 0) {
253
- bar += `${D}${emptyGlyph.repeat(emptyCells)}${R}`;
254
- }
255
-
256
- const counter = ` ${safeN}/${safeTotal}`;
257
- const label = o.label ? ` ${D}·${R} ${o.label}` : '';
258
- return _maybePlain(bar + counter + label);
259
- }
260
-
261
- /**
262
- * Subtitle: dim italic line under a banner. Single line.
263
- *
264
- * @param {string} text
265
- * @param {object} [opts]
266
- * @param {number[]} [opts.color] Optional tint
267
- * @returns {string}
268
- */
269
- function subtitle(text, opts) {
270
- const o = opts || {};
271
- const tint = Array.isArray(o.color) ? f(o.color[0], o.color[1], o.color[2]) : '';
272
- return _maybePlain(` ${D}${I}${tint}${text}${R}`);
273
- }
274
-
275
- /**
276
- * Em-dash rule line, tinted zen blue by default.
277
- * ━━━ {text} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
278
- *
279
- * Use as a horizontal section separator anywhere in the system. Calling
280
- * with no text produces a plain rule (just em-dashes, no label).
281
- *
282
- * @param {string} [text] Optional label to embed in the rule
283
- * @param {object} [opts]
284
- * @param {number} [opts.width=65] Total line width
285
- * @param {number[]} [opts.color] [r,g,b] override tint; defaults to ZEN_BLUE
286
- * @returns {string}
287
- */
288
- function ruleLine(text, opts) {
289
- const o = opts || {};
290
- const width = o.width || 65;
291
- const color = Array.isArray(o.color) ? o.color : ZEN_BLUE;
292
- const tint = f(color[0], color[1], color[2]);
293
-
294
- let line;
295
- if (text && text.length > 0) {
296
- const head = `━━━ ${text} `;
297
- const padCount = Math.max(3, width - head.length);
298
- line = head + '━'.repeat(padCount);
299
- } else {
300
- line = '━'.repeat(width);
301
- }
302
- return _maybePlain(`${tint}${line}${R}`);
303
- }
304
-
305
- /**
306
- * Phase header: multi-line — badge, em-dash banner, progress bar.
307
- * Concatenates with newlines so a single println prints all three.
308
- *
309
- * @param {number} n Phase number (1-based)
310
- * @param {number} total Total phases
311
- * @param {string} name Phase display name
312
- * @param {string} bannerKey Banner registry key (e.g. 'north', 'forge')
313
- * @param {object|string} [opts]
314
- * Pass a string to use as the mode tint key ('fast' | 'full'),
315
- * or an opts object with { mode, color, width }.
316
- * @returns {string}
317
- */
318
- function phaseHeader(n, total, name, bannerKey, opts) {
319
- let o = {};
320
- if (typeof opts === 'string') {
321
- o = { mode: opts };
322
- } else if (opts) {
323
- o = opts;
324
- }
325
- const tint = o.color || (o.mode && MODE_TINTS[o.mode.toLowerCase()]) || null;
326
-
327
- const bar = progressBar(n, total, {
328
- width: o.width || 12,
329
- color: tint,
330
- label: name,
331
- });
332
-
333
- // Em-dash banner — match the existing format used across all forge commands,
334
- // tinted zen blue for system-wide visual consistency on horizontal rules.
335
- const emBanner = ruleLine(`Phase ${n}/${total} — ${name}`);
336
-
337
- const lines = [
338
- badge(bannerKey),
339
- emBanner,
340
- bar,
341
- ];
342
- return lines.join('\n');
343
- }
344
-
345
- /**
346
- * All available banner names.
347
- * @returns {string[]}
348
- */
349
- function list() {
350
- return Object.keys(BANNERS);
351
- }
352
-
353
- /**
354
- * Full gallery of all banners separated by rules.
355
- * @returns {string}
356
- */
357
- function gallery() {
358
- return list().map((name, i) => {
359
- const sep = i > 0 ? '\n' + rule() + '\n' : '';
360
- return sep + render(name);
361
- }).join('');
362
- }
363
-
364
- // ─── Internal ──────────────────────────────────────────────────────────────────
365
-
366
- function _get(name) {
367
- const b = BANNERS[name.toLowerCase()];
368
- if (!b) {
369
- throw new Error(`Unknown banner "${name}". Available: ${list().join(', ')}`);
370
- }
371
- return b;
372
- }
373
-
374
- function _maybePlain(s) {
375
- return (FORCE_PLAIN || isPlain()) ? stripAnsi(s) : s;
376
- }
377
-
378
- // ─── CLI ───────────────────────────────────────────────────────────────────────
379
- // node banners.cjs [<name>] [--gallery] [--badge <name>] [--mark <name>] [--list]
380
-
381
- if (require.main === module) {
382
- let args = process.argv.slice(2);
383
-
384
- // --plain may appear anywhere; consume it first.
385
- const plainIdx = args.indexOf('--plain');
386
- if (plainIdx !== -1) {
387
- FORCE_PLAIN = true;
388
- args = args.slice(0, plainIdx).concat(args.slice(plainIdx + 1));
389
- }
390
-
391
- try {
392
- if (!args.length || args[0] === '--gallery') {
393
- process.stdout.write(gallery() + '\n');
394
- } else if (args[0] === '--list') {
395
- console.log(list().map(n => {
396
- const b = BANNERS[n];
397
- return `${b.emoji} ${n.padEnd(8)} — ${b.tagline}`;
398
- }).join('\n'));
399
- } else if (args[0] === '--badge') {
400
- console.log(badge(args[1] || ''));
401
- } else if (args[0] === '--mark') {
402
- console.log(mark(args[1] || ''));
403
- } else if (args[0] === '--subtitle') {
404
- console.log(subtitle(args.slice(1).join(' ')));
405
- } else if (args[0] === '--progress') {
406
- const n = Number(args[1]);
407
- const total = Number(args[2]);
408
- const label = args.slice(3).join(' ') || undefined;
409
- console.log(progressBar(n, total, { label }));
410
- } else if (args[0] === '--phase') {
411
- const n = Number(args[1]);
412
- const total = Number(args[2]);
413
- const name = args[3] || '';
414
- const bannerKey = args[4] || 'forge';
415
- const mode = args[5]; // optional 'fast' | 'full'
416
- console.log(phaseHeader(n, total, name, bannerKey, mode ? { mode } : undefined));
417
- } else if (args[0] === '--rule') {
418
- // --rule [text] Zen-blue em-dash horizontal rule (with optional label)
419
- const text = args.slice(1).join(' ') || undefined;
420
- console.log(ruleLine(text));
421
- } else {
422
- process.stdout.write(render(args[0]) + '\n');
423
- }
424
- } catch (e) {
425
- console.error(e.message);
426
- process.exit(1);
427
- }
428
- }
429
-
430
- // ─── Exports ───────────────────────────────────────────────────────────────────
431
- module.exports = {
432
- render, badge, mark, list, gallery, rule, BANNERS,
433
- progressBar, subtitle, phaseHeader, ruleLine,
434
- isPlain, stripAnsi, MODE_TINTS, ZEN_BLUE,
435
- };