scrumrun 2.7.6 → 2.7.7
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 +6 -0
- package/README.md +1 -1
- package/bin/scrumrun.js +10 -3
- package/lib/commands/manifest.js +1 -0
- package/lib/runtime/briefing.js +37 -1
- package/lib/runtime/orchestrator.js +9 -2
- package/package.json +1 -1
- package/types/index.d.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes follow Semantic Versioning.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 2.7.7 - 2026-08-24
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Error index.** `sc knowledge errors --show` renders `.scrumrun/errors.md` — a derived index grouping `type: fix` Tasks into Open and Resolved (with branch), so reported bugs have a dedicated project log. `sc plan task --list --type <type>` now filters Tasks by type (e.g. `--type fix`).
|
|
12
|
+
|
|
7
13
|
## 2.7.6 - 2026-08-24
|
|
8
14
|
|
|
9
15
|
### Added
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
ScrumRun gives an agent a small command surface and a precise project memory: what should be done, how each attempt happened, which decisions constrain the code, and why the architecture exists in its current form.
|
|
6
6
|
|
|
7
|
-
**Package:** `2.7.
|
|
7
|
+
**Package:** `2.7.7` · **Method target:** `2.0.0` · **Runtime:** Node.js `>=22.13.0` · **License:** MIT
|
|
8
8
|
|
|
9
9
|
**New here?** Read the [Quickstart](docs/QUICKSTART.md) — first Run in under 10 minutes, no `SPEC.md` reading required. Full docs map in [`docs/INDEX.md`](docs/INDEX.md).
|
|
10
10
|
|
package/bin/scrumrun.js
CHANGED
|
@@ -31,7 +31,7 @@ const { ARTIFACT_TYPES, ArtifactRepository } = require(path.join(root, "lib", "v
|
|
|
31
31
|
const { aliases: COMMAND_ALIASES, resolveAlias, resolveRoute } = require(path.join(root, "lib", "commands", "manifest"));
|
|
32
32
|
const { renderCommandHelp, renderCompatibilityPrompt, renderRootPrompt } = require(path.join(root, "lib", "commands", "render"));
|
|
33
33
|
const { planRequest } = require(path.join(root, "lib", "runtime", "request-engine"));
|
|
34
|
-
const { addPlanArtifact, approveRequest, nextBacklogTask, refreshState, retryTask, startBacklogTask, transitionRun } = require(path.join(root, "lib", "runtime", "orchestrator"));
|
|
34
|
+
const { addPlanArtifact, approveRequest, nextBacklogTask, refreshErrors, refreshState, retryTask, startBacklogTask, transitionRun } = require(path.join(root, "lib", "runtime", "orchestrator"));
|
|
35
35
|
const { authorizeMutation, recordMutation, satisfyGuardrail } = require(path.join(root, "lib", "runtime", "mutation-gateway"));
|
|
36
36
|
const { recordArtifactReview } = require(path.join(root, "lib", "runtime", "review-service"));
|
|
37
37
|
const { createMemory, listMemory, showMemory, transitionMemory } = require(path.join(root, "lib", "memory", "service"));
|
|
@@ -1378,6 +1378,11 @@ function runSemanticContext(subject, args) {
|
|
|
1378
1378
|
console.log(JSON.stringify(result, null, 2));
|
|
1379
1379
|
return;
|
|
1380
1380
|
}
|
|
1381
|
+
if (subject === "errors") {
|
|
1382
|
+
const report = refreshErrors(path.join(process.cwd(), ".scrumrun"));
|
|
1383
|
+
console.log(report.content);
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1381
1386
|
if (subject === "map") {
|
|
1382
1387
|
if (action === "--build") {
|
|
1383
1388
|
const built = rebuildIndex(process.cwd());
|
|
@@ -1537,7 +1542,9 @@ function executeRootRoute(route) {
|
|
|
1537
1542
|
if (noun === "plan" && ["task", "run", "feature", "sprint"].includes(subject) && ["--list", "--show"].includes(routeArgs[0])) {
|
|
1538
1543
|
const repository = new ArtifactRepository(projectFile());
|
|
1539
1544
|
if (routeArgs[0] === "--list") {
|
|
1540
|
-
const
|
|
1545
|
+
const typeFilter = optionValue(routeArgs, "--type");
|
|
1546
|
+
const listed = repository.list(subject).filter((artifact) => !typeFilter || artifact.record.type === typeFilter);
|
|
1547
|
+
const artifacts = listed.map((artifact) => {
|
|
1541
1548
|
const title = ((artifact.body || "").match(/^# ([^\r\n]+)/m) || [])[1] || artifact.record.id;
|
|
1542
1549
|
const branch = artifact.record.branch ? ` [${artifact.record.branch}]` : "";
|
|
1543
1550
|
return `${artifact.record.id} | ${artifact.record.status} | ${title}${branch}`;
|
|
@@ -1601,7 +1608,7 @@ function executeRootRoute(route) {
|
|
|
1601
1608
|
}
|
|
1602
1609
|
}
|
|
1603
1610
|
if (noun === "knowledge" && ["fact", "decision", "insight", "dossier"].includes(subject) && v2Project()) return runV2Memory(subject, routeArgs);
|
|
1604
|
-
if (noun === "knowledge" && ["context", "map", "study"].includes(subject) && v2Project()) return runSemanticContext(subject, routeArgs);
|
|
1611
|
+
if (noun === "knowledge" && ["context", "map", "study", "errors"].includes(subject) && v2Project()) return runSemanticContext(subject, routeArgs);
|
|
1605
1612
|
if (noun === "knowledge" && subject === "decision") return runDecisions(routeArgs);
|
|
1606
1613
|
if (noun === "knowledge" && subject === "fact") return runKnow(routeArgs);
|
|
1607
1614
|
if (noun === "knowledge" && subject === "vault") return runVault(routeArgs);
|
package/lib/commands/manifest.js
CHANGED
|
@@ -38,6 +38,7 @@ const nouns = Object.freeze({
|
|
|
38
38
|
dossier: ["--add [--title] [--content] [--evidence] [--relation] [--subject] [--source] [--source-id] [--valid-from] [--valid-until] [--review-trigger]", "--list [--include-inactive]", "--show", "--refresh [--evidence] [--note]", "--stale [--note]", "--deprecate [--note]", "--archive [--note]"],
|
|
39
39
|
context: ["--build", "--update", "--show", "--clear"],
|
|
40
40
|
map: ["--build", "--show"],
|
|
41
|
+
errors: ["--show"],
|
|
41
42
|
study: ["<focus>"],
|
|
42
43
|
vault: ["--add", "--list", "--show", "--remove", "--path"]
|
|
43
44
|
}
|
package/lib/runtime/briefing.js
CHANGED
|
@@ -101,4 +101,40 @@ ${backlogTasks.length ? backlogTasks.join("\n") : "- No backlog Tasks."}
|
|
|
101
101
|
return { content, sourceFingerprint, watchFingerprint: watch.fingerprint, sourceFiles: watch.files };
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
function generateErrorsReport(scrumDir, repository) {
|
|
105
|
+
const repo = repository || new ArtifactRepository(scrumDir);
|
|
106
|
+
const snapshot = artifactSnapshot(scrumDir);
|
|
107
|
+
const sourceFingerprint = canonicalFingerprint(scrumDir, snapshot.hashes);
|
|
108
|
+
const fixes = repo.list("task")
|
|
109
|
+
.filter((artifact) => artifact.record && !artifact.errors.length && artifact.record.type === "fix")
|
|
110
|
+
.sort((left, right) => left.record.id.localeCompare(right.record.id));
|
|
111
|
+
const open = fixes.filter((artifact) => artifact.record.status !== "completed");
|
|
112
|
+
const resolved = fixes.filter((artifact) => artifact.record.status === "completed");
|
|
113
|
+
const line = (artifact) => {
|
|
114
|
+
const record = artifact.record;
|
|
115
|
+
const title = ((artifact.body || "").match(/^# ([^\r\n]+)/m) || [])[1] || record.id;
|
|
116
|
+
return `- ${record.id} | ${record.status} | ${title}${record.branch ? ` [${record.branch}]` : ""}`;
|
|
117
|
+
};
|
|
118
|
+
const content = `# ScrumRun Error Index
|
|
119
|
+
|
|
120
|
+
Projection schema: 1
|
|
121
|
+
Generated: ${new Date().toISOString()}
|
|
122
|
+
Source fingerprint: ${sourceFingerprint}
|
|
123
|
+
Authority: none; rebuild from canonical artifacts.
|
|
124
|
+
|
|
125
|
+
## Open
|
|
126
|
+
|
|
127
|
+
${open.length ? open.map(line).join("\n") : "- None."}
|
|
128
|
+
|
|
129
|
+
## Resolved
|
|
130
|
+
|
|
131
|
+
${resolved.length ? resolved.map(line).join("\n") : "- None."}
|
|
132
|
+
|
|
133
|
+
## Summary
|
|
134
|
+
|
|
135
|
+
- Fix Tasks: ${fixes.length} (${open.length} open, ${resolved.length} resolved)
|
|
136
|
+
`;
|
|
137
|
+
return { content, sourceFingerprint };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = { TERMINAL, generateBriefing, generateErrorsReport };
|
|
@@ -22,7 +22,7 @@ const { containsSecret } = require("../security/secrets");
|
|
|
22
22
|
const { currentBranch } = require("./workspace-state");
|
|
23
23
|
const { extractLearningCandidates } = require("../code-intel/learning");
|
|
24
24
|
const { appendRunEvent, appendTechnicalSummary, createRunBody, instant } = require("./run-ledger");
|
|
25
|
-
const { generateBriefing } = require("./briefing");
|
|
25
|
+
const { generateBriefing, generateErrorsReport } = require("./briefing");
|
|
26
26
|
const { assertCanonicalWrite, policyState, prepareCompletion, publicWorkspace, verifyWorkspaceIntegrity, workspaceState } = require("./mutation-gateway");
|
|
27
27
|
const { recoverPendingTransactions, runKernelTransaction } = require("../v2/transaction");
|
|
28
28
|
|
|
@@ -65,6 +65,13 @@ function refreshState(scrumDir) {
|
|
|
65
65
|
return projection;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
function refreshErrors(scrumDir) {
|
|
69
|
+
const repository = new ArtifactRepository(scrumDir);
|
|
70
|
+
const report = generateErrorsReport(scrumDir, repository);
|
|
71
|
+
atomicWrite(path.join(scrumDir, "errors.md"), report.content);
|
|
72
|
+
return report;
|
|
73
|
+
}
|
|
74
|
+
|
|
68
75
|
function stateIsStale(scrumDir) {
|
|
69
76
|
const content = fs.existsSync(path.join(scrumDir, "state.md")) ? fs.readFileSync(path.join(scrumDir, "state.md"), "utf8") : "";
|
|
70
77
|
const stored = (content.match(/^Source fingerprint:\s*([a-f0-9]{64})$/m) || [])[1];
|
|
@@ -535,4 +542,4 @@ function addPlanArtifact(projectRoot, kind, label, options = {}) {
|
|
|
535
542
|
return withArtifactLock(scrumDir, "create", () => addPlanArtifactUnlocked(projectRoot, kind, label, options));
|
|
536
543
|
}
|
|
537
544
|
|
|
538
|
-
module.exports = { addPlanArtifact, approveRequest, nextBacklogTask, nextId, refreshState, renderState, retryTask, startBacklogTask, stateFingerprint, stateIsStale, transitionRun };
|
|
545
|
+
module.exports = { addPlanArtifact, approveRequest, nextBacklogTask, nextId, refreshErrors, refreshState, renderState, retryTask, startBacklogTask, stateFingerprint, stateIsStale, transitionRun };
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -392,6 +392,7 @@ export function retryTask(projectRoot: string, taskId: string, options?: { note?
|
|
|
392
392
|
export function startBacklogTask(projectRoot: string, taskId: string, options?: { note?: string; failurePoint?: string | null; interruptPoint?: string | null }): { run: ArtifactRecord; task: ArtifactRecord; content: string; recovered?: unknown[] };
|
|
393
393
|
export function nextBacklogTask(repository: ArtifactRepository): ArtifactRecord | null;
|
|
394
394
|
export function refreshState(scrumDir: string): StateProjection;
|
|
395
|
+
export function refreshErrors(scrumDir: string): { content: string; sourceFingerprint: string };
|
|
395
396
|
export function renderState(repository: ArtifactRepository): string;
|
|
396
397
|
export function stateFingerprint(repository: ArtifactRepository): string;
|
|
397
398
|
export function stateIsStale(scrumDir: string): boolean;
|