scrumrun 1.5.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/CORE.md +224 -311
- package/DECISIONS.md +95 -11
- package/LICENSE +21 -0
- package/MIGRATION-1-to-2.md +109 -0
- package/README.md +137 -78
- package/SPEC.md +248 -257
- package/bin/claude-install.js +18 -132
- package/bin/scrumrun.js +1259 -174
- package/docs/COMMANDS.md +69 -0
- package/docs/ENTITY-MODEL.md +38 -0
- package/docs/RELEASE.md +44 -0
- package/docs/SCHEMA.md +80 -0
- package/docs/SEMANTIC-MEMORY.md +68 -0
- package/docs/TROUBLESHOOTING.md +66 -0
- package/lib/code-intel/adapter.js +20 -0
- package/lib/code-intel/javascript.js +199 -0
- package/lib/code-intel/learning.js +66 -0
- package/lib/code-intel/scanner.js +126 -0
- package/lib/commands/manifest.js +109 -0
- package/lib/commands/render.js +75 -0
- package/lib/memory/index.js +600 -0
- package/lib/memory/markdown.js +51 -0
- package/lib/memory/service.js +300 -0
- package/lib/runtime/budgets.js +19 -0
- package/lib/runtime/context.js +141 -0
- package/lib/runtime/orchestrator.js +270 -0
- package/lib/runtime/request-engine.js +128 -0
- package/lib/security/secrets.js +23 -0
- package/lib/v2/artifacts.js +343 -0
- package/lib/v2/conformance.js +167 -0
- package/lib/v2/migration.js +1161 -0
- package/lib/v2/project-store.js +44 -0
- package/lib/v2/schema.js +128 -0
- package/package.json +16 -6
- package/scripts/generate-contract-docs.js +113 -0
- package/templates/project/.scrumrun/config.md +4 -7
- package/templates/project/.scrumrun/guardrails.md +23 -0
- package/templates/project/.scrumrun/map.md +4 -16
- package/templates/project/.scrumrun/memory/decisions/.gitkeep +1 -0
- package/templates/project/.scrumrun/memory/dossiers/.gitkeep +1 -0
- package/templates/project/.scrumrun/memory/insights/.gitkeep +1 -0
- package/templates/project/.scrumrun/memory/knowledge/.gitkeep +1 -0
- package/templates/project/.scrumrun/method.json +4 -0
- package/templates/project/.scrumrun/project.md +6 -12
- package/templates/project/.scrumrun/runs/.gitkeep +1 -0
- package/templates/project/.scrumrun/sprints/.gitkeep +1 -0
- package/templates/project/.scrumrun/state.md +21 -0
- package/templates/project/.scrumrun/tasks/.gitkeep +1 -0
- package/templates/project/AGENTS.md +16 -49
- package/templates/project-lean/AGENTS.md +18 -0
- package/templates/shared/skills/scrumrun/SKILL.md +201 -0
- package/templates/codex/prompts/sc-agent.md +0 -14
- package/templates/codex/prompts/sc-backlog.md +0 -13
- package/templates/codex/prompts/sc-challenge.md +0 -57
- package/templates/codex/prompts/sc-config.md +0 -18
- package/templates/codex/prompts/sc-context.md +0 -24
- package/templates/codex/prompts/sc-decisions.md +0 -8
- package/templates/codex/prompts/sc-feature.md +0 -16
- package/templates/codex/prompts/sc-fix.md +0 -21
- package/templates/codex/prompts/sc-goal.md +0 -14
- package/templates/codex/prompts/sc-golden.md +0 -14
- package/templates/codex/prompts/sc-help.md +0 -12
- package/templates/codex/prompts/sc-init.md +0 -14
- package/templates/codex/prompts/sc-intake.md +0 -22
- package/templates/codex/prompts/sc-know.md +0 -75
- package/templates/codex/prompts/sc-map.md +0 -13
- package/templates/codex/prompts/sc-review.md +0 -13
- package/templates/codex/prompts/sc-sprint.md +0 -28
- package/templates/codex/prompts/sc-study.md +0 -23
- package/templates/codex/prompts/sc-uninstall.md +0 -14
- package/templates/codex/prompts/sc-update.md +0 -8
- package/templates/codex/prompts/sc-vault.md +0 -27
- package/templates/codex/skills/scrumrun/SKILL.md +0 -412
- package/templates/opencode/commands/sc-agent.md +0 -14
- package/templates/opencode/commands/sc-backlog.md +0 -13
- package/templates/opencode/commands/sc-challenge.md +0 -57
- package/templates/opencode/commands/sc-config.md +0 -18
- package/templates/opencode/commands/sc-context.md +0 -24
- package/templates/opencode/commands/sc-decisions.md +0 -8
- package/templates/opencode/commands/sc-feature.md +0 -16
- package/templates/opencode/commands/sc-fix.md +0 -21
- package/templates/opencode/commands/sc-goal.md +0 -14
- package/templates/opencode/commands/sc-golden.md +0 -14
- package/templates/opencode/commands/sc-help.md +0 -12
- package/templates/opencode/commands/sc-init.md +0 -14
- package/templates/opencode/commands/sc-intake.md +0 -22
- package/templates/opencode/commands/sc-know.md +0 -75
- package/templates/opencode/commands/sc-map.md +0 -13
- package/templates/opencode/commands/sc-review.md +0 -13
- package/templates/opencode/commands/sc-sprint.md +0 -28
- package/templates/opencode/commands/sc-study.md +0 -23
- package/templates/opencode/commands/sc-uninstall.md +0 -14
- package/templates/opencode/commands/sc-update.md +0 -8
- package/templates/opencode/commands/sc-vault.md +0 -27
- package/templates/opencode/skills/scrumrun/SKILL.md +0 -412
- package/templates/project/.scrumrun/agents.md +0 -36
- package/templates/project/.scrumrun/backlog.md +0 -7
- package/templates/project/.scrumrun/context.md +0 -61
- package/templates/project/.scrumrun/goals/main/decisions.md +0 -9
- package/templates/project/.scrumrun/goals/main/history.md +0 -51
- package/templates/project/.scrumrun/goals/main/sprint.md +0 -54
- package/templates/project/.scrumrun/golden-rules.md +0 -9
- package/templates/project/.scrumrun/knowledge.md +0 -15
- package/templates/project/.scrumrun/runbook.md +0 -101
- package/templates/project/.scrumrun/token-policy.md +0 -43
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const path = require("node:path");
|
|
5
|
+
const { JavaScriptAdapter } = require("./javascript");
|
|
6
|
+
|
|
7
|
+
const EXCLUDED = new Set([".git", ".scrumrun", "node_modules", "vendor", "dist", "build", "coverage", ".next", ".nuxt"]);
|
|
8
|
+
const TEST_FILE = /(?:^|\/)(?:__tests__\/.*|[^/]*(?:\.test|\.spec)\.[^/]+)$/i;
|
|
9
|
+
|
|
10
|
+
function posix(value) {
|
|
11
|
+
return value.split(path.sep).join("/");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function currentCommit(projectRoot) {
|
|
15
|
+
const gitDir = path.join(projectRoot, ".git");
|
|
16
|
+
const headFile = path.join(gitDir, "HEAD");
|
|
17
|
+
if (!fs.existsSync(headFile)) return null;
|
|
18
|
+
const head = fs.readFileSync(headFile, "utf8").trim();
|
|
19
|
+
if (/^[a-f0-9]{40,64}$/i.test(head)) return head;
|
|
20
|
+
const ref = (head.match(/^ref:\s+(.+)$/) || [])[1];
|
|
21
|
+
if (!ref || ref.includes("..")) return null;
|
|
22
|
+
const loose = path.join(gitDir, ref);
|
|
23
|
+
if (fs.existsSync(loose)) return fs.readFileSync(loose, "utf8").trim() || null;
|
|
24
|
+
const packed = path.join(gitDir, "packed-refs");
|
|
25
|
+
if (!fs.existsSync(packed)) return null;
|
|
26
|
+
const match = fs.readFileSync(packed, "utf8").match(new RegExp(`^([a-f0-9]{40,64})\\s+${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m"));
|
|
27
|
+
return match ? match[1] : null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function sourceFiles(projectRoot, adapters, { maxFiles = 2000, maxFileBytes = 1024 * 1024 } = {}) {
|
|
31
|
+
const files = [];
|
|
32
|
+
const warnings = [];
|
|
33
|
+
function walk(directory) {
|
|
34
|
+
if (files.length >= maxFiles) return;
|
|
35
|
+
for (const entry of fs.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
36
|
+
if (files.length >= maxFiles) break;
|
|
37
|
+
if (entry.isSymbolicLink()) {
|
|
38
|
+
warnings.push(`Skipped symbolic link: ${posix(path.relative(projectRoot, path.join(directory, entry.name)))}`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (entry.isDirectory()) {
|
|
42
|
+
if (!EXCLUDED.has(entry.name)) walk(path.join(directory, entry.name));
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (!entry.isFile()) continue;
|
|
46
|
+
const file = path.join(directory, entry.name);
|
|
47
|
+
const adapter = adapters.find((candidate) => candidate.supports(file));
|
|
48
|
+
if (!adapter) continue;
|
|
49
|
+
const size = fs.statSync(file).size;
|
|
50
|
+
if (size > maxFileBytes) {
|
|
51
|
+
warnings.push(`Skipped oversized source: ${posix(path.relative(projectRoot, file))}`);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
files.push({ file, relative: path.relative(projectRoot, file), adapter });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
walk(projectRoot);
|
|
58
|
+
if (files.length >= maxFiles) warnings.push(`Source scan reached the ${maxFiles}-file limit.`);
|
|
59
|
+
return { files, warnings };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function scanProject(projectRoot, options = {}) {
|
|
63
|
+
const root = path.resolve(projectRoot);
|
|
64
|
+
const adapters = options.adapters || [new JavaScriptAdapter()];
|
|
65
|
+
const commit = currentCommit(root);
|
|
66
|
+
const discovered = sourceFiles(root, adapters, options);
|
|
67
|
+
const scans = [];
|
|
68
|
+
const warnings = [...discovered.warnings];
|
|
69
|
+
for (const source of discovered.files) {
|
|
70
|
+
try {
|
|
71
|
+
scans.push(source.adapter.scan({ projectRoot: root, file: source.file, relative: source.relative, commit }));
|
|
72
|
+
} catch (error) {
|
|
73
|
+
warnings.push(`Failed to scan ${posix(source.relative)}: ${error.message}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const nodes = scans.flatMap((scan) => [scan.module, ...scan.symbols]);
|
|
78
|
+
const edges = [];
|
|
79
|
+
for (const scan of scans) {
|
|
80
|
+
for (const symbol of scan.symbols) {
|
|
81
|
+
edges.push({ from: symbol.id, relation: "defined_in", to: scan.module.id, evidence: `${symbol.path}:${symbol.line}`, confidence: "structural" });
|
|
82
|
+
for (const dependency of scan.dependencies) {
|
|
83
|
+
edges.push({ from: symbol.id, relation: "depends_on", to: dependency.target, evidence: `${symbol.path}:import:${dependency.specifier}`, confidence: "module" });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for (const dependency of scan.dependencies) {
|
|
87
|
+
edges.push({ from: scan.module.id, relation: "depends_on", to: dependency.target, evidence: `${scan.module.path}:import:${dependency.specifier}`, confidence: "module" });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const references = new Map();
|
|
92
|
+
for (const scan of scans) {
|
|
93
|
+
const identifiers = new Set(scan.masked.match(/[A-Za-z_$][\w$]*/g) || []);
|
|
94
|
+
for (const identifier of identifiers) {
|
|
95
|
+
if (!references.has(identifier)) references.set(identifier, []);
|
|
96
|
+
references.get(identifier).push(scan);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const symbols = nodes.filter((node) => node.kind !== "module");
|
|
100
|
+
for (const symbol of symbols) {
|
|
101
|
+
for (const scan of references.get(symbol.name) || []) {
|
|
102
|
+
if (scan.module.path === symbol.path) continue;
|
|
103
|
+
const test = TEST_FILE.test(scan.module.path);
|
|
104
|
+
edges.push({
|
|
105
|
+
from: symbol.id,
|
|
106
|
+
relation: test ? "protected_by" : "used_by",
|
|
107
|
+
to: test ? `test:${scan.module.path}` : scan.module.id,
|
|
108
|
+
evidence: `${scan.module.path}:lexical-reference:${symbol.name}`,
|
|
109
|
+
confidence: "lexical"
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const uniqueEdges = new Map();
|
|
115
|
+
for (const edge of edges) uniqueEdges.set(`${edge.from}\0${edge.relation}\0${edge.to}\0${edge.evidence}`, edge);
|
|
116
|
+
return {
|
|
117
|
+
adapterIds: adapters.map((adapter) => adapter.id),
|
|
118
|
+
commit,
|
|
119
|
+
nodes: nodes.map(({ start, end, ...node }) => node),
|
|
120
|
+
edges: [...uniqueEdges.values()].sort((a, b) => `${a.from}\0${a.relation}\0${a.to}`.localeCompare(`${b.from}\0${b.relation}\0${b.to}`)),
|
|
121
|
+
files: scans.length,
|
|
122
|
+
warnings
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = { EXCLUDED, TEST_FILE, currentCommit, scanProject, sourceFiles };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { METHOD_VERSION } = require("../v2/schema");
|
|
4
|
+
|
|
5
|
+
const nouns = Object.freeze({
|
|
6
|
+
plan: {
|
|
7
|
+
description: "turn intent into Features, Tasks, Sprints, and Runs",
|
|
8
|
+
subjects: {
|
|
9
|
+
task: ["--add [--type fix] [--status backlog]", "--list", "--show", "--run", "--audit", "--cancel", "--retry"],
|
|
10
|
+
sprint: ["--add", "--list", "--show", "--start", "--complete", "--block"],
|
|
11
|
+
feature: ["--add", "--list", "--show", "--activate", "--complete"],
|
|
12
|
+
run: ["--list", "--show", "--validate", "--learn", "--complete", "--resume", "--fail", "--block"],
|
|
13
|
+
intake: ["<request>", "--request", "--approve"],
|
|
14
|
+
challenge: ["<question>"]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
knowledge: {
|
|
18
|
+
description: "manage evidence-backed project memory and bounded context",
|
|
19
|
+
subjects: {
|
|
20
|
+
fact: ["--add [--title] [--content] [--evidence] [--relation] [--subject] [--source] [--source-id] [--valid-from] [--valid-until] [--review-trigger]", "--list [--include-inactive]", "--show", "--approve [--evidence] [--note]", "--reject [--note]", "--deprecate [--note]", "--invalidate [--note]"],
|
|
21
|
+
decision: ["--add [--title] [--content] [--evidence] [--relation] [--subject] [--source] [--source-id] [--valid-from] [--valid-until] [--review-trigger]", "--list [--include-inactive]", "--show", "--resolve [--evidence] [--note]", "--deprecate [--note]", "--invalidate [--note]"],
|
|
22
|
+
insight: ["--propose [--title] [--content] [--evidence] [--relation] [--subject] [--source] [--source-id] [--confidence] [--valid-from] [--valid-until] [--review-trigger]", "--list [--include-inactive]", "--show", "--confirm [--evidence] [--note]", "--stale [--note]", "--reject [--note]", "--deprecate [--note]", "--invalidate [--note]"],
|
|
23
|
+
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]"],
|
|
24
|
+
context: ["--build", "--update", "--show", "--clear"],
|
|
25
|
+
map: ["--build", "--show"],
|
|
26
|
+
study: ["<focus>"],
|
|
27
|
+
vault: ["--add", "--list", "--show", "--remove", "--path"]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
rules: {
|
|
31
|
+
description: "manage mandatory project guardrails and reviewers",
|
|
32
|
+
subjects: {
|
|
33
|
+
guardrail: ["--add", "--list", "--show", "--retire"],
|
|
34
|
+
reviewer: ["--add", "--list", "--show", "--run"]
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
review: {
|
|
38
|
+
description: "run scoped evidence-based quality gates",
|
|
39
|
+
subjects: {
|
|
40
|
+
code: ["--run"],
|
|
41
|
+
artifact: ["--run"],
|
|
42
|
+
migration: ["--run"],
|
|
43
|
+
release: ["--run"]
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
config: {
|
|
47
|
+
description: "manage project preferences, lifecycle, migration, and help",
|
|
48
|
+
subjects: {
|
|
49
|
+
project: ["--show", "--language", "--interaction", "--approval", "--quick-tasks"],
|
|
50
|
+
init: ["--local", "--shared", "--lean", "--no-agent-hint", "--force"],
|
|
51
|
+
update: ["all [--migrate]", "codex [--migrate]", "opencode [--migrate]", "claude [--migrate]"],
|
|
52
|
+
migrate: ["--to 2 --dry-run", "--to 2 --apply", "--to 2 --rollback"],
|
|
53
|
+
doctor: ["all [--strict]", "codex [--strict]", "opencode [--strict]", "claude [--strict]"],
|
|
54
|
+
uninstall: ["--force"],
|
|
55
|
+
help: ["<topic>"]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const aliases = Object.freeze({
|
|
61
|
+
"sc-sprint": { target: ["plan", "sprint"] },
|
|
62
|
+
"sc-fix": { target: ["plan", "task"], note: "Treat the Task as type fix." },
|
|
63
|
+
"sc-feature": { target: ["plan", "feature"] },
|
|
64
|
+
"sc-backlog": { target: ["plan", "task"], note: "Treat the Task status as backlog." },
|
|
65
|
+
"sc-goal": { target: ["plan", "feature"], note: "Treat this as the main project initiative." },
|
|
66
|
+
"sc-decisions": { target: ["knowledge", "decision"] },
|
|
67
|
+
"sc-intake": { target: ["plan", "intake"] },
|
|
68
|
+
"sc-challenge": { target: ["plan", "challenge"] },
|
|
69
|
+
"sc-know": { target: ["knowledge", "fact"] },
|
|
70
|
+
"sc-vault": { target: ["knowledge", "vault"] },
|
|
71
|
+
"sc-context": { target: ["knowledge", "context"] },
|
|
72
|
+
"sc-map": { target: ["knowledge", "map"] },
|
|
73
|
+
"sc-study": { target: ["knowledge", "study"] },
|
|
74
|
+
"sc-golden": { target: ["rules", "guardrail"] },
|
|
75
|
+
"sc-agent": { target: ["rules", "reviewer"] },
|
|
76
|
+
"sc-review": { target: ["review", "code"] },
|
|
77
|
+
"sc-config": { target: ["config", "project"] },
|
|
78
|
+
"sc-help": { target: ["config", "help"] },
|
|
79
|
+
"sc-init": { target: ["config", "init"] },
|
|
80
|
+
"sc-uninstall": { target: ["config", "uninstall"] },
|
|
81
|
+
"sc-update": { target: ["config", "update"] }
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
function resolveRoute(parts) {
|
|
85
|
+
const [noun, subject, ...args] = parts;
|
|
86
|
+
if (!noun) return { type: "help", level: "root" };
|
|
87
|
+
const nounSpec = nouns[noun];
|
|
88
|
+
if (!nounSpec) return { type: "error", message: `Unknown ScrumRun noun: ${noun}` };
|
|
89
|
+
if (!subject) return { type: "help", level: "noun", noun, spec: nounSpec };
|
|
90
|
+
if (!nounSpec.subjects[subject]) return { type: "error", message: `Unknown ${noun} subject: ${subject}` };
|
|
91
|
+
const actions = nounSpec.subjects[subject];
|
|
92
|
+
if (!args.length) return { type: "help", level: "subject", noun, subject, actions };
|
|
93
|
+
const acceptsNaturalLanguage = actions.some((action) => action.startsWith("<"));
|
|
94
|
+
if (acceptsNaturalLanguage && !args[0].startsWith("-")) return { type: "route", noun, subject, args, actions };
|
|
95
|
+
const declaredFlags = [...new Set(actions.flatMap((action) => action.match(/--[a-z0-9-]+/g) || []))];
|
|
96
|
+
const unknownFlag = args.find((arg) => arg.startsWith("-") && declaredFlags.length && !declaredFlags.includes(arg));
|
|
97
|
+
if (unknownFlag) {
|
|
98
|
+
return { type: "error", message: `Unknown ${noun} ${subject} action: ${unknownFlag}` };
|
|
99
|
+
}
|
|
100
|
+
return { type: "route", noun, subject, args, actions };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function resolveAlias(alias, args = []) {
|
|
104
|
+
const spec = aliases[alias];
|
|
105
|
+
if (!spec) return null;
|
|
106
|
+
return { alias, noun: spec.target[0], subject: spec.target[1], args, note: spec.note || null };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = { METHOD_VERSION, aliases, nouns, resolveAlias, resolveRoute };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { METHOD_VERSION, aliases, nouns } = require("./manifest");
|
|
4
|
+
|
|
5
|
+
function grammarLines() {
|
|
6
|
+
return Object.entries(nouns).flatMap(([noun, spec]) => [
|
|
7
|
+
`- **${noun}** — ${spec.description}`,
|
|
8
|
+
...Object.entries(spec.subjects).map(([subject, actions]) => ` - \`${subject}\`: ${actions.join(", ")}`)
|
|
9
|
+
]);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function renderRootPrompt() {
|
|
13
|
+
return `---
|
|
14
|
+
description: ScrumRun ${METHOD_VERSION} — one root command for planning, execution, memory, rules, reviews, and configuration
|
|
15
|
+
argument-hint: <noun> <subject> <action> [args]
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
Execute ScrumRun with this request: $ARGUMENTS
|
|
19
|
+
|
|
20
|
+
Use the installed \`scrumrun\` skill as the authoritative workflow. This prompt is the only canonical slash-command entry point.
|
|
21
|
+
|
|
22
|
+
If \`$ARGUMENTS\` is empty, show the five nouns below and the current project status; do not guess an action. Otherwise parse exactly \`/sc <noun> <subject> <action> [args]\`.
|
|
23
|
+
|
|
24
|
+
## Grammar
|
|
25
|
+
|
|
26
|
+
${grammarLines().join("\n")}
|
|
27
|
+
|
|
28
|
+
## Execution contract
|
|
29
|
+
|
|
30
|
+
- Natural-language product work enters through \`plan intake\` automatically.
|
|
31
|
+
- Intake, contextualization, policy, risk, classification, and planning are read-only until explicit approval.
|
|
32
|
+
- Approved work creates/updates a Task and creates a Run; a Sprint only groups Tasks when a real timebox/batch exists.
|
|
33
|
+
- Run execution follows \`executing → validating → learning → completed|failed|blocked\`.
|
|
34
|
+
- \`guardrails.md\` is canonical project policy; \`golden-rules.md\` is v1 compatibility only.
|
|
35
|
+
- Knowledge/Decision/Insight records require evidence; AI-proposed Insights remain \`candidate\` until confirmed.
|
|
36
|
+
- Never print vault values or write before approval.
|
|
37
|
+
- Unknown nouns, subjects, actions, ids, or ambiguous approval must produce a deterministic explanation, never a guessed mutation.
|
|
38
|
+
|
|
39
|
+
Method: ${METHOD_VERSION}. Command grammar source: \`lib/commands/manifest.js\`.
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function renderCompatibilityPrompt(alias) {
|
|
44
|
+
const spec = aliases[alias];
|
|
45
|
+
if (!spec) throw new Error(`Unknown compatibility alias: ${alias}`);
|
|
46
|
+
const target = `/sc ${spec.target.join(" ")}`;
|
|
47
|
+
return `---
|
|
48
|
+
description: Deprecated ScrumRun v1 adapter — executes ${target}
|
|
49
|
+
argument-hint: [action] [args]
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
Compatibility adapter for \`/${alias}\`.
|
|
53
|
+
|
|
54
|
+
Execute this request now as \`${target} $ARGUMENTS\` using the installed \`scrumrun\` skill. Do not ask the user to re-enter the command and do not merely print a redirect.
|
|
55
|
+
|
|
56
|
+
Emit one concise deprecation note: \`/${alias}\` becomes \`${target}\` in ScrumRun 2.0. ${spec.note || ""}
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function renderCommandHelp() {
|
|
61
|
+
const nounLines = Object.entries(nouns).map(([noun, spec]) => ` /sc ${noun.padEnd(10)} ${spec.description}`);
|
|
62
|
+
const aliasLines = Object.entries(aliases).map(([alias, spec]) => ` /${alias.padEnd(14)} -> /sc ${spec.target.join(" ")}`);
|
|
63
|
+
return `ScrumRun ${METHOD_VERSION} command grammar:
|
|
64
|
+
|
|
65
|
+
Canonical root:
|
|
66
|
+
/sc <noun> <subject> <action> [args]
|
|
67
|
+
|
|
68
|
+
Nouns:
|
|
69
|
+
${nounLines.join("\n")}
|
|
70
|
+
|
|
71
|
+
Compatibility adapters (upgrade only; not installed for fresh v2 users):
|
|
72
|
+
${aliasLines.join("\n")}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { grammarLines, renderCommandHelp, renderCompatibilityPrompt, renderRootPrompt };
|