sdd-forge 0.1.0-alpha.549 → 0.1.0-alpha.622
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/README.md +1 -1
- package/package.json +1 -1
- package/src/AGENTS.md +1 -1
- package/src/docs/commands/agents.js +2 -2
- package/src/docs/commands/enrich.js +1 -1
- package/src/docs/commands/forge.js +5 -19
- package/src/docs/commands/readme.js +2 -2
- package/src/docs/commands/text.js +1 -2
- package/src/docs/commands/translate.js +2 -3
- package/src/flow/commands/merge.js +23 -22
- package/src/flow/commands/report.js +11 -11
- package/src/flow/commands/review.js +368 -50
- package/src/flow/lib/base-command.js +40 -0
- package/src/flow/lib/get-check.js +84 -0
- package/src/flow/{get/context.js → lib/get-context.js} +64 -151
- package/src/flow/lib/get-guardrail.js +61 -0
- package/src/flow/lib/get-issue.js +42 -0
- package/src/flow/{get/prompt.js → lib/get-prompt.js} +40 -39
- package/src/flow/lib/get-qa-count.js +16 -0
- package/src/flow/lib/get-resolve-context.js +99 -0
- package/src/flow/lib/get-status.js +38 -0
- package/src/flow/lib/phases.js +15 -0
- package/src/flow/lib/run-finalize.js +337 -0
- package/src/flow/lib/run-gate.js +463 -0
- package/src/flow/lib/run-impl-confirm.js +97 -0
- package/src/flow/lib/run-lint.js +61 -0
- package/src/flow/lib/run-prepare-spec.js +324 -0
- package/src/flow/lib/run-report.js +56 -0
- package/src/flow/lib/run-resume.js +103 -0
- package/src/flow/lib/run-retro.js +232 -0
- package/src/flow/lib/run-review.js +196 -0
- package/src/flow/lib/run-sync.js +85 -0
- package/src/flow/lib/set-auto.js +28 -0
- package/src/flow/lib/set-issue-log.js +73 -0
- package/src/flow/lib/set-issue.js +29 -0
- package/src/flow/lib/set-metric.js +42 -0
- package/src/flow/lib/set-note.js +24 -0
- package/src/flow/lib/set-req.js +30 -0
- package/src/flow/lib/set-request.js +24 -0
- package/src/flow/lib/set-step.js +25 -0
- package/src/flow/lib/set-summary.js +35 -0
- package/src/flow/lib/set-test-summary.js +39 -0
- package/src/flow/registry.js +298 -40
- package/src/flow.js +92 -22
- package/src/lib/agent.js +8 -4
- package/src/lib/cli.js +9 -15
- package/src/lib/flow-state.js +97 -61
- package/src/lib/git-helpers.js +70 -0
- package/src/lib/lint.js +2 -2
- package/src/lib/process.js +76 -21
- package/src/presets/api/templates/en/guardrail.json +25 -0
- package/src/presets/api/templates/ja/guardrail.json +25 -0
- package/src/presets/architecture/templates/en/guardrail.json +15 -0
- package/src/presets/architecture/templates/ja/guardrail.json +15 -0
- package/src/presets/base/templates/en/guardrail.json +64 -1
- package/src/presets/base/templates/ja/guardrail.json +64 -1
- package/src/presets/cakephp2/data/models.js +101 -103
- package/src/presets/ci/preset.json +1 -9
- package/src/presets/ci/templates/en/ci_cd.md +12 -6
- package/src/presets/ci/templates/en/guardrail.json +25 -0
- package/src/presets/ci/templates/ja/ci_cd.md +12 -6
- package/src/presets/ci/templates/ja/guardrail.json +25 -0
- package/src/presets/cli/templates/en/guardrail.json +0 -11
- package/src/presets/cli/templates/ja/guardrail.json +0 -11
- package/src/presets/coding-rule/preset.json +5 -0
- package/src/presets/coding-rule/templates/en/guardrail.json +51 -0
- package/src/presets/coding-rule/templates/ja/guardrail.json +51 -0
- package/src/presets/database/templates/en/guardrail.json +58 -0
- package/src/presets/database/templates/ja/guardrail.json +58 -0
- package/src/presets/document/preset.json +5 -0
- package/src/presets/document/templates/en/guardrail.json +24 -0
- package/src/presets/document/templates/ja/guardrail.json +24 -0
- package/src/presets/edge/templates/en/guardrail.json +35 -0
- package/src/presets/edge/templates/ja/guardrail.json +35 -0
- package/src/presets/{ci → github-actions}/data/pipelines.js +1 -1
- package/src/presets/github-actions/preset.json +11 -0
- package/src/presets/github-actions/templates/en/ci_cd.md +16 -0
- package/src/presets/github-actions/templates/en/guardrail.json +34 -0
- package/src/presets/github-actions/templates/ja/ci_cd.md +16 -0
- package/src/presets/github-actions/templates/ja/guardrail.json +34 -0
- package/src/presets/graphql/templates/en/guardrail.json +36 -0
- package/src/presets/graphql/templates/ja/guardrail.json +36 -0
- package/src/presets/greenfield/preset.json +5 -0
- package/src/presets/greenfield/templates/en/guardrail.json +65 -0
- package/src/presets/greenfield/templates/ja/guardrail.json +65 -0
- package/src/presets/infrastructure/preset.json +5 -0
- package/src/presets/infrastructure/templates/en/guardrail.json +15 -0
- package/src/presets/infrastructure/templates/ja/guardrail.json +15 -0
- package/src/presets/js-webapp/templates/en/guardrail.json +14 -0
- package/src/presets/js-webapp/templates/ja/guardrail.json +14 -0
- package/src/presets/laravel/data/controllers.js +71 -88
- package/src/presets/laravel/data/models.js +148 -172
- package/src/presets/library/templates/en/guardrail.json +10 -0
- package/src/presets/library/templates/ja/guardrail.json +10 -0
- package/src/presets/maintenance/preset.json +5 -0
- package/src/presets/maintenance/templates/en/guardrail.json +45 -0
- package/src/presets/maintenance/templates/ja/guardrail.json +45 -0
- package/src/presets/monorepo/templates/en/guardrail.json +26 -0
- package/src/presets/monorepo/templates/ja/guardrail.json +26 -0
- package/src/presets/nextjs/templates/en/guardrail.json +36 -0
- package/src/presets/nextjs/templates/ja/guardrail.json +36 -0
- package/src/presets/oss-contribute/preset.json +5 -0
- package/src/presets/oss-contribute/templates/en/guardrail.json +35 -0
- package/src/presets/oss-contribute/templates/ja/guardrail.json +35 -0
- package/src/presets/rest/templates/en/guardrail.json +15 -0
- package/src/presets/rest/templates/ja/guardrail.json +15 -0
- package/src/presets/storage/templates/en/guardrail.json +26 -0
- package/src/presets/storage/templates/ja/guardrail.json +26 -0
- package/src/presets/symfony/NOTICE +51 -0
- package/src/presets/symfony/data/controllers.js +77 -103
- package/src/presets/symfony/data/entities.js +111 -107
- package/src/presets/symfony/templates/en/guardrail.json +279 -18
- package/src/presets/symfony/templates/ja/guardrail.json +276 -15
- package/src/presets/ui-ux/preset.json +5 -0
- package/src/presets/web-design/preset.json +1 -1
- package/src/presets/webapp/templates/en/guardrail.json +46 -14
- package/src/presets/webapp/templates/ja/guardrail.json +46 -14
- package/src/presets/workers/templates/en/guardrail.json +15 -0
- package/src/presets/workers/templates/ja/guardrail.json +15 -0
- package/src/templates/partials/{redo-recording.md → issue-log-recording.md} +5 -5
- package/src/templates/skills/sdd-forge.flow-finalize/SKILL.md +4 -3
- package/src/templates/skills/sdd-forge.flow-impl/SKILL.md +26 -7
- package/src/templates/skills/sdd-forge.flow-plan/SKILL.md +64 -20
- package/src/flow/get/check.js +0 -97
- package/src/flow/get/guardrail.js +0 -76
- package/src/flow/get/issue.js +0 -38
- package/src/flow/get/qa-count.js +0 -21
- package/src/flow/get/resolve-context.js +0 -133
- package/src/flow/get/status.js +0 -42
- package/src/flow/run/finalize.js +0 -292
- package/src/flow/run/gate.js +0 -252
- package/src/flow/run/impl-confirm.js +0 -121
- package/src/flow/run/lint.js +0 -79
- package/src/flow/run/prepare-spec.js +0 -339
- package/src/flow/run/report.js +0 -91
- package/src/flow/run/retro.js +0 -269
- package/src/flow/run/review.js +0 -130
- package/src/flow/run/sync.js +0 -114
- package/src/flow/set/auto.js +0 -29
- package/src/flow/set/issue.js +0 -33
- package/src/flow/set/metric.js +0 -48
- package/src/flow/set/note.js +0 -27
- package/src/flow/set/redo.js +0 -113
- package/src/flow/set/req.js +0 -34
- package/src/flow/set/request.js +0 -27
- package/src/flow/set/step.js +0 -28
- package/src/flow/set/summary.js +0 -40
- package/src/flow/set/test-summary.js +0 -57
- package/src/lib/git-state.js +0 -52
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# <!-- {{data("cli.project.name")}} -->sdd-forge<!-- {{/data}} -->
|
|
2
2
|
|
|
3
3
|
<!-- {{data("cli.docs.langSwitcher", {labels: "absolute"})}} -->
|
|
4
|
-
|
|
4
|
+
[日本語](https://github.com/SpreadWorks/sdd-forge/blob/main/docs/ja/README.md) | **English**
|
|
5
5
|
<!-- {{/data}} -->
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/sdd-forge)
|
package/package.json
CHANGED
package/src/AGENTS.md
CHANGED
|
@@ -27,7 +27,7 @@ src/
|
|
|
27
27
|
│ ├── presets.js プリセット自動探索・親チェーン解決
|
|
28
28
|
│ ├── flow-state.js SDD フロー状態永続化
|
|
29
29
|
│ ├── flow-envelope.js flow get/set/run の JSON envelope
|
|
30
|
-
│ ├── git-
|
|
30
|
+
│ ├── git-helpers.js git/gh 状態取得ヘルパー
|
|
31
31
|
│ ├── include.js include ディレクティブ展開
|
|
32
32
|
│ ├── i18n.js 3層 i18n(ドメイン名前空間付き)
|
|
33
33
|
│ └── types.js 型エイリアス解決・バリデーション
|
|
@@ -12,7 +12,7 @@ import path from "path";
|
|
|
12
12
|
import { runIfDirect } from "../../lib/entrypoint.js";
|
|
13
13
|
import { parseArgs } from "../../lib/cli.js";
|
|
14
14
|
import { sddOutputDir } from "../../lib/config.js";
|
|
15
|
-
import { callAgent, loadAgentConfig
|
|
15
|
+
import { callAgent, loadAgentConfig } from "../../lib/agent.js";
|
|
16
16
|
import { translate } from "../../lib/i18n.js";
|
|
17
17
|
import { createResolver } from "../lib/resolver-factory.js";
|
|
18
18
|
import { createLogger } from "../../lib/progress.js";
|
|
@@ -201,7 +201,7 @@ async function main(ctx) {
|
|
|
201
201
|
const prompt = buildRefinePrompt(projectContent, combinedDocs, config, srcRoot, sddContent);
|
|
202
202
|
|
|
203
203
|
try {
|
|
204
|
-
const result = callAgent(agent, prompt,
|
|
204
|
+
const result = callAgent(agent, prompt, agent.timeoutMs, undefined, { systemPrompt });
|
|
205
205
|
|
|
206
206
|
let refined = result.trim();
|
|
207
207
|
|
|
@@ -441,7 +441,7 @@ async function main(ctx) {
|
|
|
441
441
|
const batches = splitIntoBatches(pending, maxTokens);
|
|
442
442
|
const concurrency = resolveConcurrency(config);
|
|
443
443
|
|
|
444
|
-
const timeoutMs =
|
|
444
|
+
const timeoutMs = agent.timeoutMs || DEFAULT_AGENT_TIMEOUT_MS;
|
|
445
445
|
let totalEnriched = 0;
|
|
446
446
|
|
|
447
447
|
logger.log(`${batches.length} batches (token limit: ${maxTokens}, concurrency: ${concurrency})`);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import fs from "fs";
|
|
15
15
|
import path from "path";
|
|
16
|
-
import {
|
|
16
|
+
import { runCmdAsync } from "../../lib/process.js";
|
|
17
17
|
import { runIfDirect } from "../../lib/entrypoint.js";
|
|
18
18
|
import { populateFromAnalysis } from "./data.js";
|
|
19
19
|
import { textFillFromAnalysis } from "./text.js";
|
|
@@ -119,28 +119,14 @@ function printHelp() {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
|
-
*
|
|
122
|
+
* コマンド文字列をコマンドと引数に分割して実行する。
|
|
123
123
|
* bash に依存しない。
|
|
124
124
|
*/
|
|
125
125
|
function runCommand(cmdString, cwd) {
|
|
126
126
|
const parts = cmdString.match(/"[^"]*"|'[^']*'|\S+/g) || [];
|
|
127
127
|
const command = parts[0];
|
|
128
128
|
const args = parts.slice(1).map((s) => s.replace(/^["']|["']$/g, ""));
|
|
129
|
-
return
|
|
130
|
-
execFile(
|
|
131
|
-
command,
|
|
132
|
-
args,
|
|
133
|
-
{ cwd, maxBuffer: 20 * 1024 * 1024 },
|
|
134
|
-
(err, stdout, stderr) => {
|
|
135
|
-
resolve({
|
|
136
|
-
ok: !err,
|
|
137
|
-
code: err?.code ?? 0,
|
|
138
|
-
stdout: String(stdout || ""),
|
|
139
|
-
stderr: String(stderr || ""),
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
);
|
|
143
|
-
});
|
|
129
|
+
return runCmdAsync(command, args, { cwd });
|
|
144
130
|
}
|
|
145
131
|
|
|
146
132
|
/**
|
|
@@ -220,7 +206,7 @@ async function main() {
|
|
|
220
206
|
const t = translate();
|
|
221
207
|
const agent = resolveAgent(config, "docs.forge");
|
|
222
208
|
const mode = cli.mode || DEFAULT_MODE;
|
|
223
|
-
const timeoutMs =
|
|
209
|
+
const timeoutMs = agent?.timeoutMs;
|
|
224
210
|
|
|
225
211
|
if (mode === "agent" && !agent) {
|
|
226
212
|
throw new Error(
|
|
@@ -397,7 +383,7 @@ async function main() {
|
|
|
397
383
|
// docs/ を直接編集するため generate ステップは不要
|
|
398
384
|
|
|
399
385
|
const review = await runCommand(cli.reviewCmd, root);
|
|
400
|
-
console.log(`[forge] review: ${review.ok ? "ok" : "failed"} (code=${review.
|
|
386
|
+
console.log(`[forge] review: ${review.ok ? "ok" : "failed"} (code=${review.status})`);
|
|
401
387
|
if (review.ok) {
|
|
402
388
|
console.log("[forge] review passed.");
|
|
403
389
|
const readme = await runCommand(`node "${path.join(PKG_DIR, "docs", "commands", "readme.js")}"`, root);
|
|
@@ -21,7 +21,7 @@ import { resolveCommandContext, loadFullAnalysis } from "../lib/command-context.
|
|
|
21
21
|
import { processTemplate } from "./text.js";
|
|
22
22
|
import { buildTextSystemPrompt } from "../lib/text-prompts.js";
|
|
23
23
|
import { loadConfig, resolveConcurrency } from "../../lib/config.js";
|
|
24
|
-
import { loadAgentConfig, ensureAgentWorkDir
|
|
24
|
+
import { loadAgentConfig, ensureAgentWorkDir } from "../../lib/agent.js";
|
|
25
25
|
|
|
26
26
|
const logger = createLogger("readme");
|
|
27
27
|
|
|
@@ -148,7 +148,7 @@ async function main(ctx) {
|
|
|
148
148
|
const analysis = loadFullAnalysis(root) || {};
|
|
149
149
|
const documentStyle = cfg.docs?.style;
|
|
150
150
|
const systemPrompt = buildTextSystemPrompt(documentStyle, lang);
|
|
151
|
-
const timeoutMs =
|
|
151
|
+
const timeoutMs = agent.timeoutMs;
|
|
152
152
|
|
|
153
153
|
const result = await processTemplate(
|
|
154
154
|
resolved, analysis, "README.md", agent, timeoutMs,
|
|
@@ -687,11 +687,10 @@ async function main(ctx) {
|
|
|
687
687
|
logger.verbose(`--id=${ctx.id}: per-directive mode forced.`);
|
|
688
688
|
}
|
|
689
689
|
|
|
690
|
-
const configTimeout = cfg.agent?.timeout ? Number(cfg.agent.timeout) * 1000 : undefined;
|
|
691
690
|
const retryCount = Number(cfg?.agent?.retryCount) || 0;
|
|
692
691
|
const processFn = ctx.perDirective ? processTemplate : processTemplateFileBatch;
|
|
693
692
|
if (!ctx.perDirective) {
|
|
694
|
-
if (!ctx.timeout) ctx.timeout =
|
|
693
|
+
if (!ctx.timeout) ctx.timeout = agent.timeoutMs || DEFAULT_TIMEOUT_MS;
|
|
695
694
|
logger.verbose(`Mode: batch (file-level, ${targetFiles.length} file(s), concurrency=${concurrency}, timeout=${ctx.timeout}ms). Use --per-directive for single-call mode.`);
|
|
696
695
|
}
|
|
697
696
|
|
|
@@ -15,13 +15,12 @@ import { runIfDirect } from "../../lib/entrypoint.js";
|
|
|
15
15
|
import { parseArgs } from "../../lib/cli.js";
|
|
16
16
|
import { resolveOutputConfig } from "../../lib/types.js";
|
|
17
17
|
import { resolveConcurrency } from "../../lib/config.js";
|
|
18
|
-
import { callAgentAsync
|
|
18
|
+
import { callAgentAsync } from "../../lib/agent.js";
|
|
19
19
|
import { createLogger } from "../../lib/progress.js";
|
|
20
20
|
import { resolveCommandContext, getChapterFiles, stripResponsePreamble } from "../lib/command-context.js";
|
|
21
21
|
import { mapWithConcurrency } from "../lib/concurrency.js";
|
|
22
22
|
|
|
23
23
|
const logger = createLogger("translate");
|
|
24
|
-
const DEFAULT_TIMEOUT_MS = DEFAULT_AGENT_TIMEOUT_MS;
|
|
25
24
|
|
|
26
25
|
/**
|
|
27
26
|
* Translate a Markdown document from one language to another via AI agent.
|
|
@@ -72,7 +71,7 @@ async function translateDocument(content, fromLang, toLang, agent, root, documen
|
|
|
72
71
|
|
|
73
72
|
const prompt = content;
|
|
74
73
|
|
|
75
|
-
const result = await callAgentAsync(agent, prompt,
|
|
74
|
+
const result = await callAgentAsync(agent, prompt, agent.timeoutMs, root, {
|
|
76
75
|
systemPrompt,
|
|
77
76
|
});
|
|
78
77
|
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* Called by finalize.js with ctx containing root, flowState, worktreePath, mainRepoPath, mergeStrategy.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { execFileSync } from "child_process";
|
|
9
8
|
import { readFileSync } from "fs";
|
|
9
|
+
import { runCmd } from "../../lib/process.js";
|
|
10
10
|
import path from "path";
|
|
11
11
|
import { loadConfig } from "../../lib/config.js";
|
|
12
|
+
import { isGhAvailable } from "../../lib/git-helpers.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Resolve push remote from config.
|
|
@@ -19,19 +20,6 @@ function resolveRemote(cfg) {
|
|
|
19
20
|
return cfg?.flow?.push?.remote || "origin";
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
/**
|
|
23
|
-
* Check if gh command is available.
|
|
24
|
-
* @returns {boolean}
|
|
25
|
-
*/
|
|
26
|
-
function isGhAvailable() {
|
|
27
|
-
try {
|
|
28
|
-
execFileSync("gh", ["--version"], { stdio: "ignore" });
|
|
29
|
-
return true;
|
|
30
|
-
} catch (_) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
23
|
/**
|
|
36
24
|
* Extract a markdown section body by heading name.
|
|
37
25
|
* @param {string} content - full markdown text
|
|
@@ -177,14 +165,16 @@ function main(ctx) {
|
|
|
177
165
|
const title = buildPrTitle(spec, fallbackTitle);
|
|
178
166
|
const body = buildPrBody(state, spec);
|
|
179
167
|
|
|
180
|
-
|
|
181
|
-
|
|
168
|
+
const pushRes = runCmd("git", ["push", "-u", remote, featureBranch]);
|
|
169
|
+
if (!pushRes.ok) throw new Error(pushRes.stderr || "git push failed");
|
|
170
|
+
const prRes = runCmd("gh", [
|
|
182
171
|
"pr", "create",
|
|
183
172
|
"--base", baseBranch,
|
|
184
173
|
"--head", featureBranch,
|
|
185
174
|
"--title", title,
|
|
186
175
|
...(body ? ["--body", body] : []),
|
|
187
|
-
]
|
|
176
|
+
]);
|
|
177
|
+
if (!prRes.ok) throw new Error(prRes.stderr || "gh pr create failed");
|
|
188
178
|
return { strategy: "pr" };
|
|
189
179
|
}
|
|
190
180
|
|
|
@@ -192,16 +182,27 @@ function main(ctx) {
|
|
|
192
182
|
const specTitle = state.spec?.replace(/^specs\/\d+-/, "").replace(/\/spec\.md$/, "") || featureBranch;
|
|
193
183
|
const commitMsg = state.issue ? `${specTitle}\n\nfixes #${state.issue}` : specTitle;
|
|
194
184
|
|
|
185
|
+
function runSquashMerge(gitPrefix, hint) {
|
|
186
|
+
const mergeArgs = [...gitPrefix, "merge", "--squash", featureBranch];
|
|
187
|
+
const resetArgs = [...gitPrefix, "reset", "--merge"];
|
|
188
|
+
const mergeRes = runCmd("git", mergeArgs);
|
|
189
|
+
if (!mergeRes.ok) {
|
|
190
|
+
runCmd("git", resetArgs);
|
|
191
|
+
throw new Error(`Merge conflict detected. ${hint}`);
|
|
192
|
+
}
|
|
193
|
+
const commitRes = runCmd("git", [...gitPrefix, "commit", "-m", commitMsg]);
|
|
194
|
+
if (!commitRes.ok) throw new Error(commitRes.stderr || "commit after squash merge failed");
|
|
195
|
+
}
|
|
196
|
+
|
|
195
197
|
if (worktree && mainRepoPath) {
|
|
196
|
-
|
|
197
|
-
execFileSync("git", ["-C", mainRepoPath, "commit", "-m", commitMsg], { stdio: "inherit" });
|
|
198
|
+
runSquashMerge(["-C", mainRepoPath], `Run 'git rebase ${baseBranch}' in the worktree and retry finalize.`);
|
|
198
199
|
return { strategy: "squash" };
|
|
199
200
|
}
|
|
200
201
|
|
|
201
202
|
// Branch mode
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
const checkoutRes = runCmd("git", ["checkout", baseBranch]);
|
|
204
|
+
if (!checkoutRes.ok) throw new Error(checkoutRes.stderr || "git checkout failed");
|
|
205
|
+
runSquashMerge([], `Run 'git rebase ${baseBranch}' and retry finalize.`);
|
|
205
206
|
return { strategy: "squash" };
|
|
206
207
|
}
|
|
207
208
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import fs from "fs";
|
|
9
9
|
import path from "path";
|
|
10
|
-
import {
|
|
10
|
+
import { loadIssueLog } from "../lib/set-issue-log.js";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Aggregate metrics across all phases.
|
|
@@ -15,7 +15,7 @@ import { loadRedoLog } from "../set/redo.js";
|
|
|
15
15
|
* @returns {{ docsRead: number, srcRead: number, question: number, redo: number }}
|
|
16
16
|
*/
|
|
17
17
|
function aggregateMetrics(metrics) {
|
|
18
|
-
const totals = { docsRead: 0, srcRead: 0, question: 0,
|
|
18
|
+
const totals = { docsRead: 0, srcRead: 0, question: 0, issueLog: 0 };
|
|
19
19
|
if (!metrics) return totals;
|
|
20
20
|
for (const phase of Object.values(metrics)) {
|
|
21
21
|
if (!phase || typeof phase !== "object") continue;
|
|
@@ -31,13 +31,13 @@ function aggregateMetrics(metrics) {
|
|
|
31
31
|
* @param {Object} input
|
|
32
32
|
* @param {Object} input.state - flow.json state
|
|
33
33
|
* @param {Object} input.results - finalize step results
|
|
34
|
-
* @param {Object} input.
|
|
34
|
+
* @param {Object} input.issueLog - issue-log data { entries: [] }
|
|
35
35
|
* @param {string} input.implDiffStat - git diff --stat output for implementation
|
|
36
36
|
* @param {string[]} input.commitMessages - commit messages from feature branch
|
|
37
37
|
* @returns {{ data: Object, text: string }}
|
|
38
38
|
*/
|
|
39
39
|
export function generateReport(input) {
|
|
40
|
-
const { state, results,
|
|
40
|
+
const { state, results, issueLog, implDiffStat, commitMessages } = input;
|
|
41
41
|
|
|
42
42
|
// Implementation
|
|
43
43
|
const implementation = {
|
|
@@ -52,8 +52,8 @@ export function generateReport(input) {
|
|
|
52
52
|
: null;
|
|
53
53
|
|
|
54
54
|
// Redolog
|
|
55
|
-
const entries =
|
|
56
|
-
const
|
|
55
|
+
const entries = issueLog?.entries || [];
|
|
56
|
+
const issueLogData = {
|
|
57
57
|
count: entries.length,
|
|
58
58
|
entries: entries.map(e => ({
|
|
59
59
|
step: e.step,
|
|
@@ -96,7 +96,7 @@ export function generateReport(input) {
|
|
|
96
96
|
tests = { unit, integration, acceptance, total: unit + integration + acceptance };
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
const data = { implementation, retro,
|
|
99
|
+
const data = { implementation, retro, issueLog: issueLogData, metrics, tests, sync };
|
|
100
100
|
const text = formatText(data);
|
|
101
101
|
|
|
102
102
|
return { data, text };
|
|
@@ -150,7 +150,7 @@ function formatText(data) {
|
|
|
150
150
|
lines.push(" Metrics");
|
|
151
151
|
lines.push(` ${thin}`);
|
|
152
152
|
const m = data.metrics;
|
|
153
|
-
lines.push(` docs ${m.docsRead} src ${m.srcRead} Q&A ${m.question}
|
|
153
|
+
lines.push(` docs ${m.docsRead} src ${m.srcRead} Q&A ${m.question} issues ${m.issueLog}`);
|
|
154
154
|
|
|
155
155
|
// Tests
|
|
156
156
|
if (data.tests) {
|
|
@@ -162,11 +162,11 @@ function formatText(data) {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
// Redo (only if entries exist)
|
|
165
|
-
if (data.
|
|
165
|
+
if (data.issueLog.count > 0) {
|
|
166
166
|
lines.push("");
|
|
167
|
-
lines.push(`
|
|
167
|
+
lines.push(` Issue Log (${data.issueLog.count})`);
|
|
168
168
|
lines.push(` ${thin}`);
|
|
169
|
-
for (const e of data.
|
|
169
|
+
for (const e of data.issueLog.entries) {
|
|
170
170
|
lines.push(` [${e.step}] ${e.reason}${e.resolution ? ` -> ${e.resolution}` : ""}`);
|
|
171
171
|
}
|
|
172
172
|
}
|