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 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.6` · **Method target:** `2.0.0` · **Runtime:** Node.js `>=22.13.0` · **License:** MIT
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 artifacts = repository.list(subject).map((artifact) => {
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);
@@ -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
  }
@@ -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
- module.exports = { TERMINAL, generateBriefing };
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scrumrun",
3
- "version": "2.7.6",
3
+ "version": "2.7.7",
4
4
  "description": "Evidence-driven Agile runtime and semantic project memory for AI coding agents.",
5
5
  "bin": {
6
6
  "scrumrun": "bin/scrumrun.js",
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;