@entelligentsia/forgecli 0.10.0 → 0.11.2
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.
- package/CHANGELOG.md +95 -0
- package/README.md +21 -3
- package/dist/CHANGELOG-forge-plugin.md +90 -0
- package/dist/bin/config.js +6 -0
- package/dist/bin/config.js.map +1 -1
- package/dist/extensions/forgecli/add-pipeline.d.ts +19 -0
- package/dist/extensions/forgecli/add-pipeline.js +143 -0
- package/dist/extensions/forgecli/add-pipeline.js.map +1 -0
- package/dist/extensions/forgecli/add-task.d.ts +20 -0
- package/dist/extensions/forgecli/add-task.js +154 -0
- package/dist/extensions/forgecli/add-task.js.map +1 -0
- package/dist/extensions/forgecli/calibrate.d.ts +61 -0
- package/dist/extensions/forgecli/calibrate.js +488 -0
- package/dist/extensions/forgecli/calibrate.js.map +1 -0
- package/dist/extensions/forgecli/fix-bug.d.ts +9 -1
- package/dist/extensions/forgecli/fix-bug.js +155 -45
- package/dist/extensions/forgecli/fix-bug.js.map +1 -1
- package/dist/extensions/forgecli/forge-commands.js +15 -22
- package/dist/extensions/forgecli/forge-commands.js.map +1 -1
- package/dist/extensions/forgecli/forge-subagent.d.ts +16 -1
- package/dist/extensions/forgecli/forge-subagent.js +45 -8
- package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
- package/dist/extensions/forgecli/forge-update-command.d.ts +9 -0
- package/dist/extensions/forgecli/forge-update-command.js +106 -7
- package/dist/extensions/forgecli/forge-update-command.js.map +1 -1
- package/dist/extensions/forgecli/health-check.d.ts +22 -1
- package/dist/extensions/forgecli/health-check.js +177 -4
- package/dist/extensions/forgecli/health-check.js.map +1 -1
- package/dist/extensions/forgecli/hook-dispatcher.d.ts +25 -1
- package/dist/extensions/forgecli/hook-dispatcher.js +104 -9
- package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
- package/dist/extensions/forgecli/hooks/check-update.d.ts +81 -0
- package/dist/extensions/forgecli/hooks/check-update.js +308 -0
- package/dist/extensions/forgecli/hooks/check-update.js.map +1 -0
- package/dist/extensions/forgecli/hooks/forge-permissions.d.ts +32 -0
- package/dist/extensions/forgecli/hooks/forge-permissions.js +119 -0
- package/dist/extensions/forgecli/hooks/forge-permissions.js.map +1 -0
- package/dist/extensions/forgecli/hooks/triage-error.d.ts +23 -0
- package/dist/extensions/forgecli/hooks/triage-error.js +62 -0
- package/dist/extensions/forgecli/hooks/triage-error.js.map +1 -0
- package/dist/extensions/forgecli/hooks/write-guard.d.ts +28 -0
- package/dist/extensions/forgecli/hooks/write-guard.js +225 -0
- package/dist/extensions/forgecli/hooks/write-guard.js.map +1 -0
- package/dist/extensions/forgecli/index.js +60 -0
- package/dist/extensions/forgecli/index.js.map +1 -1
- package/dist/extensions/forgecli/init-context.d.ts +1 -1
- package/dist/extensions/forgecli/init-context.js +21 -6
- package/dist/extensions/forgecli/init-context.js.map +1 -1
- package/dist/extensions/forgecli/materialize.d.ts +16 -0
- package/dist/extensions/forgecli/materialize.js +195 -0
- package/dist/extensions/forgecli/materialize.js.map +1 -0
- package/dist/extensions/forgecli/migrate.d.ts +19 -0
- package/dist/extensions/forgecli/migrate.js +258 -0
- package/dist/extensions/forgecli/migrate.js.map +1 -0
- package/dist/extensions/forgecli/migration-engine.d.ts +111 -0
- package/dist/extensions/forgecli/migration-engine.js +533 -0
- package/dist/extensions/forgecli/migration-engine.js.map +1 -0
- package/dist/extensions/forgecli/quiz-agent.d.ts +17 -0
- package/dist/extensions/forgecli/quiz-agent.js +98 -0
- package/dist/extensions/forgecli/quiz-agent.js.map +1 -0
- package/dist/extensions/forgecli/remove-command.d.ts +17 -0
- package/dist/extensions/forgecli/remove-command.js +124 -0
- package/dist/extensions/forgecli/remove-command.js.map +1 -0
- package/dist/extensions/forgecli/report-bug.d.ts +25 -0
- package/dist/extensions/forgecli/report-bug.js +159 -0
- package/dist/extensions/forgecli/report-bug.js.map +1 -0
- package/dist/extensions/forgecli/retrospective.d.ts +19 -0
- package/dist/extensions/forgecli/retrospective.js +156 -0
- package/dist/extensions/forgecli/retrospective.js.map +1 -0
- package/dist/extensions/forgecli/run-sprint.js +36 -3
- package/dist/extensions/forgecli/run-sprint.js.map +1 -1
- package/dist/extensions/forgecli/run-task.d.ts +9 -1
- package/dist/extensions/forgecli/run-task.js +66 -13
- package/dist/extensions/forgecli/run-task.js.map +1 -1
- package/dist/extensions/forgecli/session-registry.d.ts +40 -2
- package/dist/extensions/forgecli/session-registry.js +71 -1
- package/dist/extensions/forgecli/session-registry.js.map +1 -1
- package/dist/extensions/forgecli/status-command.d.ts +19 -0
- package/dist/extensions/forgecli/status-command.js +140 -0
- package/dist/extensions/forgecli/status-command.js.map +1 -0
- package/dist/extensions/forgecli/store-query.d.ts +22 -0
- package/dist/extensions/forgecli/store-query.js +107 -0
- package/dist/extensions/forgecli/store-query.js.map +1 -0
- package/dist/extensions/forgecli/store-repair.d.ts +17 -0
- package/dist/extensions/forgecli/store-repair.js +123 -0
- package/dist/extensions/forgecli/store-repair.js.map +1 -0
- package/dist/extensions/forgecli/test-orchestrate.js +1 -0
- package/dist/extensions/forgecli/test-orchestrate.js.map +1 -1
- package/dist/extensions/forgecli/thread-switcher.js +286 -41
- package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
- package/dist/extensions/forgecli/transition-guard.js +7 -2
- package/dist/extensions/forgecli/transition-guard.js.map +1 -1
- package/dist/extensions/forgecli/update-tools.d.ts +23 -0
- package/dist/extensions/forgecli/update-tools.js +136 -0
- package/dist/extensions/forgecli/update-tools.js.map +1 -0
- package/dist/extensions/forgecli/viewport-events.js +10 -0
- package/dist/extensions/forgecli/viewport-events.js.map +1 -1
- package/dist/extensions/forgecli/viewport-renderer.d.ts +18 -0
- package/dist/extensions/forgecli/viewport-renderer.js +27 -0
- package/dist/extensions/forgecli/viewport-renderer.js.map +1 -1
- package/dist/extensions/forgecli/viewport-theme.js +4 -0
- package/dist/extensions/forgecli/viewport-theme.js.map +1 -1
- package/dist/extensions/forgecli/whats-new-widget.d.ts +13 -8
- package/dist/extensions/forgecli/whats-new-widget.js +111 -42
- package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
- package/dist/forge-payload/.base-pack/workflows/architect_approve.md +29 -3
- package/dist/forge-payload/.base-pack/workflows/commit_task.md +15 -8
- package/dist/forge-payload/.base-pack/workflows/fix_bug.md +327 -185
- package/dist/forge-payload/.base-pack/workflows/implement_plan.md +18 -10
- package/dist/forge-payload/.base-pack/workflows/plan_task.md +15 -9
- package/dist/forge-payload/.base-pack/workflows/review_code.md +14 -6
- package/dist/forge-payload/.base-pack/workflows/review_plan.md +18 -10
- package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
- package/dist/forge-payload/.schemas/bug.schema.json +3 -2
- package/dist/forge-payload/.schemas/config.schema.json +83 -0
- package/dist/forge-payload/.schemas/migrations.json +2049 -0
- package/dist/forge-payload/commands/regenerate.md +17 -1
- package/dist/forge-payload/meta/personas/README.md +16 -0
- package/dist/forge-payload/meta/personas/meta-architect.md +70 -0
- package/dist/forge-payload/meta/personas/meta-bug-fixer.md +73 -0
- package/dist/forge-payload/meta/personas/meta-collator.md +72 -0
- package/dist/forge-payload/meta/personas/meta-engineer.md +70 -0
- package/dist/forge-payload/meta/personas/meta-orchestrator.md +71 -0
- package/dist/forge-payload/meta/personas/meta-product-manager.md +82 -0
- package/dist/forge-payload/meta/personas/meta-qa-engineer.md +91 -0
- package/dist/forge-payload/meta/personas/meta-supervisor.md +92 -0
- package/dist/forge-payload/meta/skill-recommendations.md +154 -0
- package/dist/forge-payload/meta/skills/meta-architect-skills.md +43 -0
- package/dist/forge-payload/meta/skills/meta-bug-fixer-skills.md +43 -0
- package/dist/forge-payload/meta/skills/meta-collator-skills.md +41 -0
- package/dist/forge-payload/meta/skills/meta-engineer-skills.md +43 -0
- package/dist/forge-payload/meta/skills/meta-generic-skills.md +58 -0
- package/dist/forge-payload/meta/skills/meta-qa-engineer-skills.md +46 -0
- package/dist/forge-payload/meta/skills/meta-supervisor-skills.md +43 -0
- package/dist/forge-payload/meta/store-schema/bug.schema.md +71 -0
- package/dist/forge-payload/meta/store-schema/event.schema.md +76 -0
- package/dist/forge-payload/meta/store-schema/feature.schema.md +65 -0
- package/dist/forge-payload/meta/store-schema/sprint.schema.md +64 -0
- package/dist/forge-payload/meta/store-schema/task.schema.md +78 -0
- package/dist/forge-payload/meta/templates/meta-code-review.md +26 -0
- package/dist/forge-payload/meta/templates/meta-plan-review.md +28 -0
- package/dist/forge-payload/meta/templates/meta-plan.md +28 -0
- package/dist/forge-payload/meta/templates/meta-progress.md +25 -0
- package/dist/forge-payload/meta/templates/meta-retrospective.md +28 -0
- package/dist/forge-payload/meta/templates/meta-sprint-manifest.md +26 -0
- package/dist/forge-payload/meta/templates/meta-sprint-requirements.md +91 -0
- package/dist/forge-payload/meta/templates/meta-task-prompt.md +26 -0
- package/dist/forge-payload/meta/tool-specs/collate.spec.md +88 -0
- package/dist/forge-payload/meta/tool-specs/generation-manifest.spec.md +139 -0
- package/dist/forge-payload/meta/tool-specs/manage-config.spec.md +143 -0
- package/dist/forge-payload/meta/tool-specs/seed-store.spec.md +91 -0
- package/dist/forge-payload/meta/tool-specs/store-cli.spec.md +328 -0
- package/dist/forge-payload/meta/tool-specs/validate-store.spec.md +191 -0
- package/dist/forge-payload/meta/workflows/_fragments/context-injection.md +75 -0
- package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +73 -0
- package/dist/forge-payload/meta/workflows/_fragments/finalize.md +13 -0
- package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +73 -0
- package/dist/forge-payload/meta/workflows/_fragments/progress-reporting.md +38 -0
- package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +39 -0
- package/dist/forge-payload/meta/workflows/meta-approve.md +119 -0
- package/dist/forge-payload/meta/workflows/meta-collate.md +89 -0
- package/dist/forge-payload/meta/workflows/meta-commit.md +93 -0
- package/dist/forge-payload/meta/workflows/meta-enhance.md +286 -0
- package/dist/forge-payload/meta/workflows/meta-fix-bug.md +501 -0
- package/dist/forge-payload/meta/workflows/meta-implement.md +132 -0
- package/dist/forge-payload/meta/workflows/meta-migrate.md +455 -0
- package/dist/forge-payload/meta/workflows/meta-orchestrate.md +993 -0
- package/dist/forge-payload/meta/workflows/meta-plan-task.md +133 -0
- package/dist/forge-payload/meta/workflows/meta-quiz-agent.md +135 -0
- package/dist/forge-payload/meta/workflows/meta-retrospective.md +65 -0
- package/dist/forge-payload/meta/workflows/meta-review-implementation.md +119 -0
- package/dist/forge-payload/meta/workflows/meta-review-plan.md +108 -0
- package/dist/forge-payload/meta/workflows/meta-review-sprint-completion.md +65 -0
- package/dist/forge-payload/meta/workflows/meta-sprint-intake.md +76 -0
- package/dist/forge-payload/meta/workflows/meta-sprint-plan.md +147 -0
- package/dist/forge-payload/meta/workflows/meta-update-implementation.md +76 -0
- package/dist/forge-payload/meta/workflows/meta-update-plan.md +76 -0
- package/dist/forge-payload/meta/workflows/meta-validate.md +111 -0
- package/dist/forge-payload/tools/check-structure.cjs +344 -0
- package/dist/forge-payload/tools/collate.cjs +34 -9
- package/dist/forge-payload/tools/list-skills.js +76 -0
- package/dist/forge-payload/tools/parse-gates.cjs +8 -2
- package/dist/forge-payload/tools/store-cli.cjs +56 -11
- package/dist/forge-payload/tools/store.cjs +61 -0
- package/dist/forge-payload/tools/substitute-placeholders.cjs +60 -8
- package/dist/forge-payload/tools/validate-store.cjs +6 -2
- package/dist/forge-payload/tools/verify-integrity.cjs +86 -0
- package/package.json +2 -2
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// forge:quiz-agent — native kickoff handler (FORGE-S23-T11).
|
|
2
|
+
//
|
|
3
|
+
// Replaces the auto-generated stub previously installed by
|
|
4
|
+
// registerAllForgeCommands (forge-commands.ts). Kickoff Shim archetype
|
|
5
|
+
// (Pack-04 + Pack-06): single LLM handoff in current context, no fork.
|
|
6
|
+
//
|
|
7
|
+
// Ultra-thin shim: reads commands/quiz-agent.md and dispatches.
|
|
8
|
+
// Optional topic seed or @<file> narrows the quiz scope.
|
|
9
|
+
//
|
|
10
|
+
// Workflow source: <forgeRoot>/commands/quiz-agent.md (command file).
|
|
11
|
+
// Note: quiz_agent.md also exists in .forge/workflows/ but lacks 3 of
|
|
12
|
+
// 4 Pack-06 markers. Using the command file for consistency with the
|
|
13
|
+
// other 5 handlers in this batch. Follow-up task can upgrade to read
|
|
14
|
+
// from .forge/workflows/quiz_agent.md when it has all markers.
|
|
15
|
+
//
|
|
16
|
+
// File-existence check only — command files lack Pack-06 workflow markers.
|
|
17
|
+
//
|
|
18
|
+
// Iron Laws:
|
|
19
|
+
// IL1 — code only under forge-cli/src/extensions/forgecli/.
|
|
20
|
+
// IL4 — no JSON.stringify-into-subagent dispatch.
|
|
21
|
+
// IL6 — no shell-string interpolation; no spawn calls here.
|
|
22
|
+
// IL7 — every failure path emits ctx.ui.notify and returns; no silent
|
|
23
|
+
// continuation.
|
|
24
|
+
import * as fs from "node:fs";
|
|
25
|
+
import * as path from "node:path";
|
|
26
|
+
import { sendKickoff } from "./kickoff.js";
|
|
27
|
+
export function parseQuizAgentArgs(rawArgs, cwd) {
|
|
28
|
+
const trimmed = (rawArgs ?? "").trim();
|
|
29
|
+
if (!trimmed) {
|
|
30
|
+
return { mode: "empty", topicSeed: "", sourceLabel: "(no topic — full KB quiz)" };
|
|
31
|
+
}
|
|
32
|
+
if (trimmed.startsWith("@")) {
|
|
33
|
+
const ref = trimmed.slice(1).trim();
|
|
34
|
+
const filePath = path.isAbsolute(ref) ? ref : path.resolve(cwd, ref);
|
|
35
|
+
const topicSeed = fs.readFileSync(filePath, "utf8");
|
|
36
|
+
return { mode: "file", topicSeed, sourceLabel: `(topic from file: ${ref})` };
|
|
37
|
+
}
|
|
38
|
+
return { mode: "text", topicSeed: trimmed, sourceLabel: "(topic from inline text)" };
|
|
39
|
+
}
|
|
40
|
+
export function composeQuizAgentKickoff(opts) {
|
|
41
|
+
const { commandMd, parsed } = opts;
|
|
42
|
+
const sections = ["# /forge:quiz-agent", ""];
|
|
43
|
+
sections.push("## Dispatch", "");
|
|
44
|
+
sections.push("Run the quiz-agent workflow below to verify this agent has read and understood the project knowledge base. " +
|
|
45
|
+
"Ask factual questions about the project's architecture, entity model, and sprint conventions — do not accept vague answers. " +
|
|
46
|
+
"Report pass/fail with specific evidence.");
|
|
47
|
+
sections.push("", "---", "", "## Command", "", commandMd.trim(), "", "---");
|
|
48
|
+
if (parsed.mode === "empty") {
|
|
49
|
+
sections.push("", "## Topic", "", "(no topic specified — quiz the full KB scope)");
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
sections.push("", `## Topic — ${parsed.sourceLabel}`, "", parsed.topicSeed.trim());
|
|
53
|
+
}
|
|
54
|
+
return sections.join("\n");
|
|
55
|
+
}
|
|
56
|
+
// ── Registration ──────────────────────────────────────────────────────────
|
|
57
|
+
const COMMAND_NAME = "quiz-agent";
|
|
58
|
+
export function registerQuizAgent(pi, options) {
|
|
59
|
+
pi.registerCommand("forge:quiz-agent", {
|
|
60
|
+
description: "Verify an agent has loaded and understood the project knowledge base — run a short factual quiz. " +
|
|
61
|
+
"Usage: /forge:quiz-agent [@<file> | <topic>]. Empty args run a full KB quiz.",
|
|
62
|
+
async handler(args, ctx) {
|
|
63
|
+
const { forgeRoot } = options;
|
|
64
|
+
const cwd = options.cwd ?? process.cwd();
|
|
65
|
+
if (!forgeRoot) {
|
|
66
|
+
ctx.ui.notify("× forge:quiz-agent — no Forge project at cwd; run /forge:init to bootstrap", "warning");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const commandPath = path.join(forgeRoot, "commands", `${COMMAND_NAME}.md`);
|
|
70
|
+
let commandMd;
|
|
71
|
+
try {
|
|
72
|
+
commandMd = fs.readFileSync(commandPath, "utf8");
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const e = err;
|
|
76
|
+
if (e.code === "ENOENT") {
|
|
77
|
+
ctx.ui.notify(`× forge:quiz-agent — command file not found at commands/${COMMAND_NAME}.md; run /forge:init or /forge:regenerate first.`, "error");
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
ctx.ui.notify(`× forge:quiz-agent — failed to read command file: ${e.message ?? "unknown error"}`, "error");
|
|
81
|
+
}
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
let parsed;
|
|
85
|
+
try {
|
|
86
|
+
parsed = parseQuizAgentArgs(args, cwd);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
const e = err;
|
|
90
|
+
ctx.ui.notify(`× forge:quiz-agent — failed to parse args: ${e.message ?? "unknown"}`, "error");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const kickoff = composeQuizAgentKickoff({ commandMd, parsed });
|
|
94
|
+
sendKickoff(pi, kickoff);
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=quiz-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quiz-agent.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/quiz-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
export interface ParsedRemoveArgs {
|
|
3
|
+
apply: boolean;
|
|
4
|
+
seed: string;
|
|
5
|
+
sourceLabel: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function parseRemoveArgs(rawArgs: string, cwd: string): ParsedRemoveArgs;
|
|
8
|
+
export interface ComposeRemoveKickoffOpts {
|
|
9
|
+
commandMd: string;
|
|
10
|
+
parsed: ParsedRemoveArgs;
|
|
11
|
+
}
|
|
12
|
+
export declare function composeRemoveKickoff(opts: ComposeRemoveKickoffOpts): string;
|
|
13
|
+
export interface RegisterRemoveCommandOptions {
|
|
14
|
+
forgeRoot: string | null;
|
|
15
|
+
cwd?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function registerRemoveCommand(pi: ExtensionAPI, options: RegisterRemoveCommandOptions): void;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// forge:remove — native kickoff handler (FORGE-S23-T11).
|
|
2
|
+
//
|
|
3
|
+
// Replaces the auto-generated stub previously installed by
|
|
4
|
+
// registerAllForgeCommands (forge-commands.ts). Kickoff Shim archetype
|
|
5
|
+
// (Pack-04 + Pack-06): single LLM handoff in current context, no fork.
|
|
6
|
+
//
|
|
7
|
+
// File is named remove-command.ts (not remove.ts) to avoid naming
|
|
8
|
+
// conflicts with Node.js built-in patterns (consistent with read-command.ts
|
|
9
|
+
// and status-command.ts in this directory).
|
|
10
|
+
//
|
|
11
|
+
// --apply flag bypasses the per-bucket LLM confirmation prompts by including
|
|
12
|
+
// the flag value in the kickoff body so the LLM skips interactive confirmation.
|
|
13
|
+
//
|
|
14
|
+
// Workflow source: <forgeRoot>/commands/remove.md (command file).
|
|
15
|
+
// File-existence check only — command files lack Pack-06 workflow markers.
|
|
16
|
+
//
|
|
17
|
+
// Iron Laws:
|
|
18
|
+
// IL1 — code only under forge-cli/src/extensions/forgecli/.
|
|
19
|
+
// IL4 — no JSON.stringify-into-subagent dispatch.
|
|
20
|
+
// IL6 — no shell-string interpolation; no spawn calls here.
|
|
21
|
+
// IL7 — every failure path emits ctx.ui.notify and returns; no silent
|
|
22
|
+
// continuation.
|
|
23
|
+
import * as fs from "node:fs";
|
|
24
|
+
import * as path from "node:path";
|
|
25
|
+
import { sendKickoff } from "./kickoff.js";
|
|
26
|
+
export function parseRemoveArgs(rawArgs, cwd) {
|
|
27
|
+
const trimmed = (rawArgs ?? "").trim();
|
|
28
|
+
const result = {
|
|
29
|
+
apply: false,
|
|
30
|
+
seed: "",
|
|
31
|
+
sourceLabel: "",
|
|
32
|
+
};
|
|
33
|
+
if (!trimmed) {
|
|
34
|
+
result.sourceLabel = "(no args — interactive removal)";
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
const tokens = trimmed.split(/\s+/);
|
|
38
|
+
const remaining = [];
|
|
39
|
+
for (const tok of tokens) {
|
|
40
|
+
if (tok === "--apply") {
|
|
41
|
+
result.apply = true;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
remaining.push(tok);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const tail = remaining.join(" ").trim();
|
|
48
|
+
if (tail.startsWith("@")) {
|
|
49
|
+
const ref = tail.slice(1).trim();
|
|
50
|
+
const filePath = path.isAbsolute(ref) ? ref : path.resolve(cwd, ref);
|
|
51
|
+
result.seed = fs.readFileSync(filePath, "utf8");
|
|
52
|
+
result.sourceLabel = `(seed from file: ${ref})`;
|
|
53
|
+
}
|
|
54
|
+
else if (tail) {
|
|
55
|
+
result.seed = tail;
|
|
56
|
+
result.sourceLabel = "(seed from inline text)";
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
result.sourceLabel = result.apply ? "(--apply provided)" : "(no args — interactive removal)";
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
export function composeRemoveKickoff(opts) {
|
|
64
|
+
const { commandMd, parsed } = opts;
|
|
65
|
+
const sections = ["# /forge:remove", ""];
|
|
66
|
+
sections.push("## Dispatch", "");
|
|
67
|
+
sections.push("Run the remove command below to remove Forge artifacts from this project.");
|
|
68
|
+
if (parsed.apply) {
|
|
69
|
+
sections.push("", "**`--apply` flag provided.** Proceed with removal of each bucket without asking for per-bucket confirmation. " +
|
|
70
|
+
"Still show a final summary of what will be removed before executing, but do not prompt for each individual bucket.");
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
sections.push("", "Interactive mode: ask for confirmation before removing each bucket (default behavior).");
|
|
74
|
+
}
|
|
75
|
+
sections.push("", "---", "", "## Command", "", commandMd.trim(), "", "---");
|
|
76
|
+
if (parsed.seed) {
|
|
77
|
+
sections.push("", `## Additional Input — ${parsed.sourceLabel}`, "", parsed.seed.trim());
|
|
78
|
+
}
|
|
79
|
+
return sections.join("\n");
|
|
80
|
+
}
|
|
81
|
+
// ── Registration ──────────────────────────────────────────────────────────
|
|
82
|
+
const COMMAND_NAME = "remove";
|
|
83
|
+
export function registerRemoveCommand(pi, options) {
|
|
84
|
+
pi.registerCommand("forge:remove", {
|
|
85
|
+
description: "Remove Forge artifacts from this project — interactive by default. " +
|
|
86
|
+
"Usage: /forge:remove [--apply] [@<file> | <text>]. " +
|
|
87
|
+
"--apply skips per-bucket confirmation prompts.",
|
|
88
|
+
async handler(args, ctx) {
|
|
89
|
+
const { forgeRoot } = options;
|
|
90
|
+
const cwd = options.cwd ?? process.cwd();
|
|
91
|
+
if (!forgeRoot) {
|
|
92
|
+
ctx.ui.notify("× forge:remove — no Forge project at cwd; run /forge:init to bootstrap", "warning");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const commandPath = path.join(forgeRoot, "commands", `${COMMAND_NAME}.md`);
|
|
96
|
+
let commandMd;
|
|
97
|
+
try {
|
|
98
|
+
commandMd = fs.readFileSync(commandPath, "utf8");
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
const e = err;
|
|
102
|
+
if (e.code === "ENOENT") {
|
|
103
|
+
ctx.ui.notify(`× forge:remove — command file not found at commands/${COMMAND_NAME}.md; run /forge:init or /forge:regenerate first.`, "error");
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
ctx.ui.notify(`× forge:remove — failed to read command file: ${e.message ?? "unknown error"}`, "error");
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
let parsed;
|
|
111
|
+
try {
|
|
112
|
+
parsed = parseRemoveArgs(args, cwd);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
const e = err;
|
|
116
|
+
ctx.ui.notify(`× forge:remove — failed to parse args: ${e.message ?? "unknown"}`, "error");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const kickoff = composeRemoveKickoff({ commandMd, parsed });
|
|
120
|
+
sendKickoff(pi, kickoff);
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=remove-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove-command.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/remove-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
export declare function resolveBugRepo(cwd: string): string;
|
|
3
|
+
export interface ParsedReportBugArgs {
|
|
4
|
+
mode: "empty" | "file" | "text";
|
|
5
|
+
symptomText: string;
|
|
6
|
+
sourceLabel: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseReportBugArgs(rawArgs: string, cwd: string): ParsedReportBugArgs;
|
|
9
|
+
export interface GhAuthResult {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
output: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function checkGhAuth(): GhAuthResult;
|
|
14
|
+
export interface ComposeReportBugKickoffOpts {
|
|
15
|
+
commandMd: string;
|
|
16
|
+
parsed: ParsedReportBugArgs;
|
|
17
|
+
bugRepo: string;
|
|
18
|
+
ghAuthOutput: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function composeReportBugKickoff(opts: ComposeReportBugKickoffOpts): string;
|
|
21
|
+
export interface RegisterReportBugOptions {
|
|
22
|
+
forgeRoot: string | null;
|
|
23
|
+
cwd?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function registerReportBug(pi: ExtensionAPI, options: RegisterReportBugOptions): void;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// forge:report-bug — native kickoff handler (FORGE-S23-T11).
|
|
2
|
+
//
|
|
3
|
+
// Replaces the auto-generated stub previously installed by
|
|
4
|
+
// registerAllForgeCommands (forge-commands.ts). Kickoff Shim archetype
|
|
5
|
+
// (Pack-04 + Pack-06): single LLM handoff in current context, no fork.
|
|
6
|
+
//
|
|
7
|
+
// Pre-flights: gh auth status (spawnSync, argv-array, IL6). On failure,
|
|
8
|
+
// notifies and returns — no kickoff sent.
|
|
9
|
+
//
|
|
10
|
+
// Bug repo is configurable (AC#5):
|
|
11
|
+
// 1. FORGE_BUG_REPO env var
|
|
12
|
+
// 2. config.json bugs.repo field (if present)
|
|
13
|
+
// 3. default: "Entelligentsia/forge"
|
|
14
|
+
//
|
|
15
|
+
// Workflow source: <forgeRoot>/commands/report-bug.md (command file).
|
|
16
|
+
// File-existence check only — command files lack Pack-06 workflow markers.
|
|
17
|
+
//
|
|
18
|
+
// Iron Laws:
|
|
19
|
+
// IL1 — code only under forge-cli/src/extensions/forgecli/.
|
|
20
|
+
// IL4 — no JSON.stringify-into-subagent dispatch.
|
|
21
|
+
// IL6 — no shell-string interpolation; spawnSync uses argv arrays.
|
|
22
|
+
// IL7 — every failure path emits ctx.ui.notify and returns; no silent
|
|
23
|
+
// continuation.
|
|
24
|
+
import * as fs from "node:fs";
|
|
25
|
+
import * as path from "node:path";
|
|
26
|
+
import { spawnSync } from "node:child_process";
|
|
27
|
+
import { sendKickoff } from "./kickoff.js";
|
|
28
|
+
// ── Repo resolution ───────────────────────────────────────────────────────
|
|
29
|
+
const DEFAULT_BUG_REPO = "Entelligentsia/forge";
|
|
30
|
+
export function resolveBugRepo(cwd) {
|
|
31
|
+
// 1. FORGE_BUG_REPO env var
|
|
32
|
+
const fromEnv = process.env["FORGE_BUG_REPO"];
|
|
33
|
+
if (fromEnv?.trim())
|
|
34
|
+
return fromEnv.trim();
|
|
35
|
+
// 2. config.json bugs.repo field
|
|
36
|
+
try {
|
|
37
|
+
const configPath = path.join(cwd, ".forge", "config.json");
|
|
38
|
+
const raw = fs.readFileSync(configPath, "utf8");
|
|
39
|
+
const config = JSON.parse(raw);
|
|
40
|
+
const bugs = config["bugs"];
|
|
41
|
+
const repo = bugs?.["repo"];
|
|
42
|
+
if (typeof repo === "string" && repo.trim())
|
|
43
|
+
return repo.trim();
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// config absent or unreadable — fall through to default
|
|
47
|
+
}
|
|
48
|
+
// 3. default
|
|
49
|
+
return DEFAULT_BUG_REPO;
|
|
50
|
+
}
|
|
51
|
+
export function parseReportBugArgs(rawArgs, cwd) {
|
|
52
|
+
const trimmed = (rawArgs ?? "").trim();
|
|
53
|
+
if (!trimmed) {
|
|
54
|
+
return { mode: "empty", symptomText: "", sourceLabel: "(no symptom — LLM will ask)" };
|
|
55
|
+
}
|
|
56
|
+
if (trimmed.startsWith("@")) {
|
|
57
|
+
const ref = trimmed.slice(1).trim();
|
|
58
|
+
const filePath = path.isAbsolute(ref) ? ref : path.resolve(cwd, ref);
|
|
59
|
+
const symptomText = fs.readFileSync(filePath, "utf8");
|
|
60
|
+
return { mode: "file", symptomText, sourceLabel: `(symptom from file: ${ref})` };
|
|
61
|
+
}
|
|
62
|
+
return { mode: "text", symptomText: trimmed, sourceLabel: "(symptom from inline text)" };
|
|
63
|
+
}
|
|
64
|
+
export function checkGhAuth() {
|
|
65
|
+
// IL6: argv-array, no shell interpolation
|
|
66
|
+
const result = spawnSync("gh", ["auth", "status"], {
|
|
67
|
+
encoding: "utf8",
|
|
68
|
+
timeout: 10_000,
|
|
69
|
+
});
|
|
70
|
+
const ok = result.status === 0 && !result.error;
|
|
71
|
+
const output = ((result.stdout ?? "") + (result.stderr ?? "")).trim();
|
|
72
|
+
return { ok, output: output.slice(0, 300) }; // cap for kickoff body
|
|
73
|
+
}
|
|
74
|
+
export function composeReportBugKickoff(opts) {
|
|
75
|
+
const { commandMd, parsed, bugRepo, ghAuthOutput } = opts;
|
|
76
|
+
const sections = ["# /forge:report-bug", ""];
|
|
77
|
+
sections.push("## Dispatch", "");
|
|
78
|
+
sections.push("File a bug report against Forge (not your project). Follow the command steps below. Specifically:");
|
|
79
|
+
sections.push("");
|
|
80
|
+
sections.push(`1. File the issue to: \`${bugRepo}\` (override via \`FORGE_BUG_REPO\` env or \`config.json\` \`bugs.repo\` field).`);
|
|
81
|
+
sections.push("2. \`gh\` is authenticated (pre-flight passed). Use it to file the issue.");
|
|
82
|
+
if (ghAuthOutput) {
|
|
83
|
+
sections.push(`3. Auth context: \`${ghAuthOutput.replace(/\n/g, " ").slice(0, 200)}\``);
|
|
84
|
+
}
|
|
85
|
+
sections.push("4. Gather automatic context (forge version, node version, OS) per Step 2 in the command.");
|
|
86
|
+
sections.push("5. Draft the issue body, show it to the user for review, then file with `gh issue create`.");
|
|
87
|
+
sections.push("", "---", "", "## Command", "", commandMd.trim(), "", "---");
|
|
88
|
+
if (parsed.mode === "empty") {
|
|
89
|
+
sections.push("", "## Input", "", "(no symptom provided — ask the user to describe the bug)");
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
sections.push("", `## Input — ${parsed.sourceLabel}`, "", parsed.symptomText.trim());
|
|
93
|
+
}
|
|
94
|
+
return sections.join("\n");
|
|
95
|
+
}
|
|
96
|
+
// ── Registration ──────────────────────────────────────────────────────────
|
|
97
|
+
const COMMAND_NAME = "report-bug";
|
|
98
|
+
export function registerReportBug(pi, options) {
|
|
99
|
+
pi.registerCommand("forge:report-bug", {
|
|
100
|
+
description: "File a bug against Forge itself as a GitHub issue. " +
|
|
101
|
+
"Usage: /forge:report-bug [@<file> | <symptom description>]. " +
|
|
102
|
+
"Requires `gh` to be installed and authenticated. " +
|
|
103
|
+
"Target repo: FORGE_BUG_REPO env | config.json bugs.repo | Entelligentsia/forge.",
|
|
104
|
+
async handler(args, ctx) {
|
|
105
|
+
const { forgeRoot } = options;
|
|
106
|
+
const cwd = options.cwd ?? process.cwd();
|
|
107
|
+
// gh auth pre-flight (IL6: argv-array)
|
|
108
|
+
const ghAuth = checkGhAuth();
|
|
109
|
+
if (!ghAuth.ok) {
|
|
110
|
+
ctx.ui.notify("× forge:report-bug — gh is not authenticated. Install gh (https://cli.github.com) and run `gh auth login` first.", "error");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!forgeRoot) {
|
|
114
|
+
// report-bug works outside a Forge project (reporting bugs in Forge itself)
|
|
115
|
+
// but we still need the command file from the bundled payload
|
|
116
|
+
}
|
|
117
|
+
// Resolve command file from forgeRoot (bundled payload) or fall back to graceful error
|
|
118
|
+
let commandMd;
|
|
119
|
+
if (forgeRoot) {
|
|
120
|
+
const commandPath = path.join(forgeRoot, "commands", `${COMMAND_NAME}.md`);
|
|
121
|
+
try {
|
|
122
|
+
commandMd = fs.readFileSync(commandPath, "utf8");
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
const e = err;
|
|
126
|
+
if (e.code === "ENOENT") {
|
|
127
|
+
ctx.ui.notify(`× forge:report-bug — command file not found at commands/${COMMAND_NAME}.md; run /forge:init or /forge:regenerate first.`, "error");
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
ctx.ui.notify(`× forge:report-bug — failed to read command file: ${e.message ?? "unknown error"}`, "error");
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
ctx.ui.notify("× forge:report-bug — no Forge project at cwd; run /forge:init to bootstrap before reporting bugs.", "warning");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
let parsed;
|
|
140
|
+
try {
|
|
141
|
+
parsed = parseReportBugArgs(args, cwd);
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
const e = err;
|
|
145
|
+
ctx.ui.notify(`× forge:report-bug — failed to parse args: ${e.message ?? "unknown"}`, "error");
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const bugRepo = resolveBugRepo(cwd);
|
|
149
|
+
const kickoff = composeReportBugKickoff({
|
|
150
|
+
commandMd,
|
|
151
|
+
parsed,
|
|
152
|
+
bugRepo,
|
|
153
|
+
ghAuthOutput: ghAuth.output,
|
|
154
|
+
});
|
|
155
|
+
sendKickoff(pi, kickoff);
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=report-bug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-bug.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/report-bug.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,2DAA2D;AAC3D,uEAAuE;AACvE,uEAAuE;AACvE,EAAE;AACF,wEAAwE;AACxE,0CAA0C;AAC1C,EAAE;AACF,mCAAmC;AACnC,8BAA8B;AAC9B,gDAAgD;AAChD,uCAAuC;AACvC,EAAE;AACF,sEAAsE;AACtE,2EAA2E;AAC3E,EAAE;AACF,aAAa;AACb,8DAA8D;AAC9D,oDAAoD;AACpD,qEAAqE;AACrE,wEAAwE;AACxE,wBAAwB;AAExB,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,6EAA6E;AAE7E,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAEhD,MAAM,UAAU,cAAc,CAAC,GAAW;IACzC,4BAA4B;IAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC9C,IAAI,OAAO,EAAE,IAAI,EAAE;QAAE,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;IAE3C,iCAAiC;IACjC,IAAI,CAAC;QACJ,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAwC,CAAC;QACnE,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACR,wDAAwD;IACzD,CAAC;IAED,aAAa;IACb,OAAO,gBAAgB,CAAC;AACzB,CAAC;AAUD,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,GAAW;IAC9D,MAAM,OAAO,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,EAAE,6BAA6B,EAAE,CAAC;IACvF,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACtD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,uBAAuB,GAAG,GAAG,EAAE,CAAC;IAClF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;AAC1F,CAAC;AASD,MAAM,UAAU,WAAW;IAC1B,0CAA0C;IAC1C,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;QAClD,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,MAAM;KACf,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;IAChD,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,uBAAuB;AACrE,CAAC;AAWD,MAAM,UAAU,uBAAuB,CAAC,IAAiC;IACxE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAE1D,MAAM,QAAQ,GAAa,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACvD,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IACjC,QAAQ,CAAC,IAAI,CACZ,mGAAmG,CACnG,CAAC;IACF,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,IAAI,CAAC,2BAA2B,OAAO,kFAAkF,CAAC,CAAC;IACpI,QAAQ,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;IAC3F,IAAI,YAAY,EAAE,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,sBAAsB,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACzF,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,0FAA0F,CAAC,CAAC;IAC1G,QAAQ,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAC;IAE5G,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IAE5E,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,0DAA0D,CAAC,CAAC;IAC/F,CAAC;SAAM,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,cAAc,MAAM,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,6EAA6E;AAE7E,MAAM,YAAY,GAAG,YAAY,CAAC;AAOlC,MAAM,UAAU,iBAAiB,CAAC,EAAgB,EAAE,OAAiC;IACpF,EAAE,CAAC,eAAe,CAAC,kBAAkB,EAAE;QACtC,WAAW,EACV,qDAAqD;YACrD,8DAA8D;YAC9D,mDAAmD;YACnD,iFAAiF;QAClF,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,GAA4B;YACvD,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;YAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YAEzC,uCAAuC;YACvC,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBAChB,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,kHAAkH,EAClH,OAAO,CACP,CAAC;gBACF,OAAO;YACR,CAAC;YAED,IAAI,CAAC,SAAS,EAAE,CAAC;gBAChB,4EAA4E;gBAC5E,8DAA8D;YAC/D,CAAC;YAED,uFAAuF;YACvF,IAAI,SAAiB,CAAC;YACtB,IAAI,SAAS,EAAE,CAAC;gBACf,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC;gBAC3E,IAAI,CAAC;oBACJ,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;gBAClD,CAAC;gBAAC,OAAO,GAAY,EAAE,CAAC;oBACvB,MAAM,CAAC,GAAG,GAA0C,CAAC;oBACrD,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBACzB,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,2DAA2D,YAAY,kDAAkD,EACzH,OAAO,CACP,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACP,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,qDAAqD,CAAC,CAAC,OAAO,IAAI,eAAe,EAAE,EACnF,OAAO,CACP,CAAC;oBACH,CAAC;oBACD,OAAO;gBACR,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,mGAAmG,EACnG,SAAS,CACT,CAAC;gBACF,OAAO;YACR,CAAC;YAED,IAAI,MAA2B,CAAC;YAChC,IAAI,CAAC;gBACJ,MAAM,GAAG,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACxC,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACvB,MAAM,CAAC,GAAG,GAA2B,CAAC;gBACtC,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,8CAA8C,CAAC,CAAC,OAAO,IAAI,SAAS,EAAE,EACtE,OAAO,CACP,CAAC;gBACF,OAAO;YACR,CAAC;YAED,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,OAAO,GAAG,uBAAuB,CAAC;gBACvC,SAAS;gBACT,MAAM;gBACN,OAAO;gBACP,YAAY,EAAE,MAAM,CAAC,MAAM;aAC3B,CAAC,CAAC;YACH,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC1B,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
export type ArgMode = "empty" | "file" | "text";
|
|
3
|
+
export interface ParsedArgs {
|
|
4
|
+
mode: ArgMode;
|
|
5
|
+
sprintRef: string;
|
|
6
|
+
sourceLabel: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseRetroArgs(rawArgs: string, cwd: string): ParsedArgs;
|
|
9
|
+
export declare function extractPersonaNames(workflowMd: string): string[];
|
|
10
|
+
export interface ComposeKickoffOpts {
|
|
11
|
+
workflowMd: string;
|
|
12
|
+
personaIdentity: string;
|
|
13
|
+
parsed: ParsedArgs;
|
|
14
|
+
}
|
|
15
|
+
export declare function composeKickoff(opts: ComposeKickoffOpts): string;
|
|
16
|
+
export interface RegisterRetrospectiveOptions {
|
|
17
|
+
cwd?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function registerRetrospective(pi: ExtensionAPI, options?: RegisterRetrospectiveOptions): void;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// forge:retrospective — native kickoff handler (FORGE-S23-T06).
|
|
2
|
+
//
|
|
3
|
+
// Replaces the auto-generated stub previously installed by
|
|
4
|
+
// registerAllForgeCommands (forge-commands.ts). Kickoff Shim archetype
|
|
5
|
+
// (Pack-04 + Pack-06): single LLM handoff in current context, no fork.
|
|
6
|
+
//
|
|
7
|
+
// The retrospective workflow (sprint_retrospective.md) is LLM-driven:
|
|
8
|
+
// the handler reads the materialized workflow, composes a kickoff message
|
|
9
|
+
// citing the persona path and workflow path, then dispatches via
|
|
10
|
+
// pi.sendUserMessage with { deliverAs: "steer" }.
|
|
11
|
+
//
|
|
12
|
+
// Iron Laws:
|
|
13
|
+
// IL1 — code only under forge-cli/src/extensions/forgecli/.
|
|
14
|
+
// IL4 — no JSON.stringify-into-subagent dispatch.
|
|
15
|
+
// IL6 — no shell-string interpolation; no spawn calls here.
|
|
16
|
+
// IL7 — every failure path emits ctx.ui.notify and returns; no silent
|
|
17
|
+
// continuation.
|
|
18
|
+
import * as fs from "node:fs";
|
|
19
|
+
import * as path from "node:path";
|
|
20
|
+
import { assertAudience } from "./audience-gate.js";
|
|
21
|
+
import { sendKickoff } from "./kickoff.js";
|
|
22
|
+
import { loadPersona, PersonaSkillLoaderError } from "./loaders/persona-skill-loader.js";
|
|
23
|
+
import { loadWorkflow, WorkflowLoaderError } from "./loaders/workflow-loader.js";
|
|
24
|
+
export function parseRetroArgs(rawArgs, cwd) {
|
|
25
|
+
const trimmed = (rawArgs ?? "").trim();
|
|
26
|
+
if (trimmed === "") {
|
|
27
|
+
return { mode: "empty", sprintRef: "", sourceLabel: "(no sprint specified — will prompt)" };
|
|
28
|
+
}
|
|
29
|
+
if (trimmed.startsWith("@")) {
|
|
30
|
+
const ref = trimmed.slice(1).trim();
|
|
31
|
+
const filePath = path.isAbsolute(ref) ? ref : path.resolve(cwd, ref);
|
|
32
|
+
const seed = fs.readFileSync(filePath, "utf8");
|
|
33
|
+
return { mode: "file", sprintRef: seed, sourceLabel: `(seed from file: ${ref})` };
|
|
34
|
+
}
|
|
35
|
+
return { mode: "text", sprintRef: trimmed, sourceLabel: "(seed from inline text)" };
|
|
36
|
+
}
|
|
37
|
+
// Frontmatter persona extraction (permissive) ------------------------------
|
|
38
|
+
export function extractPersonaNames(workflowMd) {
|
|
39
|
+
const lines = workflowMd.split(/\r?\n/);
|
|
40
|
+
if (lines.length === 0 || lines[0] !== "---")
|
|
41
|
+
return [];
|
|
42
|
+
let inside = false;
|
|
43
|
+
let depsBlock = false;
|
|
44
|
+
for (let i = 0; i < lines.length; i++) {
|
|
45
|
+
const line = lines[i];
|
|
46
|
+
if (i === 0 && line === "---") {
|
|
47
|
+
inside = true;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (!inside)
|
|
51
|
+
break;
|
|
52
|
+
if (line === "---")
|
|
53
|
+
break;
|
|
54
|
+
if (/^deps\s*:\s*$/.test(line)) {
|
|
55
|
+
depsBlock = true;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const m = /^\s*personas\s*:\s*\[([^\]]*)\]\s*$/.exec(line);
|
|
59
|
+
if (m && (depsBlock || /^\s/.test(line))) {
|
|
60
|
+
return m[1]
|
|
61
|
+
.split(",")
|
|
62
|
+
.map((s) => s.trim().replace(/^["']|["']$/g, ""))
|
|
63
|
+
.filter((s) => s.length > 0);
|
|
64
|
+
}
|
|
65
|
+
if (depsBlock && /^[A-Za-z0-9_-]+\s*:/.test(line) && !/^\s/.test(line)) {
|
|
66
|
+
depsBlock = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
export function composeKickoff(opts) {
|
|
72
|
+
const { workflowMd, personaIdentity, parsed } = opts;
|
|
73
|
+
const sections = ["# /forge:retrospective", ""];
|
|
74
|
+
if (personaIdentity.trim().length > 0) {
|
|
75
|
+
sections.push(personaIdentity.trim(), "");
|
|
76
|
+
}
|
|
77
|
+
sections.push("## Dispatch", "", "Run the retrospective workflow below. Specifically:", "", "1. Identify the sprint to retrospect: if a sprint ID was provided (e.g. FORGE-SNN) use it directly; otherwise ask the user which sprint to retrospect before proceeding.", "2. Load the architect persona from `.forge/personas/architect.md` for full identity context.", "3. Follow the workflow at `.forge/workflows/sprint_retrospective.md` verbatim: load all sprint task manifests, event logs, and retrospective notes; compute cost and bottlenecks; write RETROSPECTIVE.md.", "4. Use `forge_store_query` for all store reads — do NOT raw-read `.forge/store/`.", "5. Write retrospective artifacts using the `write` tool.", "6. Honour Pack-06 Read/Write/Ask/Store discipline: in-conversation clarifications use `forge_ask_user`.");
|
|
78
|
+
sections.push("", "---", "", "## Workflow", "", workflowMd.trim(), "", "---");
|
|
79
|
+
if (parsed.mode === "empty") {
|
|
80
|
+
sections.push("", "## Input", "", "(no sprint specified — ask the user which sprint to retrospect before proceeding)");
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
sections.push("", `## Input — ${parsed.sourceLabel}`, "", parsed.sprintRef.trim());
|
|
84
|
+
}
|
|
85
|
+
return sections.join("\n");
|
|
86
|
+
}
|
|
87
|
+
// Registration -------------------------------------------------------------
|
|
88
|
+
const WORKFLOW_REL_PATH = path.join(".forge", "workflows", "sprint_retrospective.md");
|
|
89
|
+
export function registerRetrospective(pi, options = {}) {
|
|
90
|
+
pi.registerCommand("forge:retrospective", {
|
|
91
|
+
description: "Run the retrospective workflow for a Forge sprint. " +
|
|
92
|
+
"Usage: /forge:retrospective [FORGE-SNN | @<file> | <free-form text>]. " +
|
|
93
|
+
"Empty args — the LLM will prompt you for the sprint to retrospect.",
|
|
94
|
+
async handler(args, ctx) {
|
|
95
|
+
const cwd = options.cwd ?? process.cwd();
|
|
96
|
+
const workflowPath = path.join(cwd, WORKFLOW_REL_PATH);
|
|
97
|
+
let workflowMd;
|
|
98
|
+
let workflowAudience;
|
|
99
|
+
try {
|
|
100
|
+
const loaded = loadWorkflow(workflowPath);
|
|
101
|
+
workflowMd = loaded.rawMarkdown;
|
|
102
|
+
workflowAudience = loaded.audience;
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
if (err instanceof WorkflowLoaderError) {
|
|
106
|
+
if (err.code === "missing_file") {
|
|
107
|
+
ctx.ui.notify(`× forge:retrospective — workflow not found at ${WORKFLOW_REL_PATH}; run /forge:init or /forge:regenerate first.`, "error");
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
ctx.ui.notify(`× forge:retrospective — workflow load failed (${err.code}): ${err.message}`, "error");
|
|
111
|
+
}
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const e = err;
|
|
115
|
+
ctx.ui.notify(`× forge:retrospective — failed to read workflow: ${e.message ?? "unknown"}`, "error");
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
let parsed;
|
|
119
|
+
try {
|
|
120
|
+
parsed = parseRetroArgs(args, cwd);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
const e = err;
|
|
124
|
+
ctx.ui.notify(`× forge:retrospective — failed to read seed: ${e.message ?? "unknown"}`, "error");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const personas = extractPersonaNames(workflowMd);
|
|
128
|
+
let personaIdentity = "";
|
|
129
|
+
if (personas.length > 0) {
|
|
130
|
+
try {
|
|
131
|
+
const persona = loadPersona(personas[0], { cwd });
|
|
132
|
+
personaIdentity = persona.identity;
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
if (err instanceof PersonaSkillLoaderError) {
|
|
136
|
+
ctx.ui.notify(`× forge:retrospective — persona '${personas[0]}' load failed (${err.code}): ${err.message}`, "error");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const e = err;
|
|
140
|
+
ctx.ui.notify(`× forge:retrospective — persona load error: ${e.message ?? "unknown"}`, "error");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (!assertAudience({ workflowName: "sprint_retrospective", audience: workflowAudience }, ctx)) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const kickoff = composeKickoff({
|
|
148
|
+
workflowMd,
|
|
149
|
+
personaIdentity,
|
|
150
|
+
parsed,
|
|
151
|
+
});
|
|
152
|
+
sendKickoff(pi, kickoff);
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=retrospective.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retrospective.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/retrospective.ts"],"names":[],"mappings":"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"}
|