scrumrun 3.1.2 → 4.1.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 +29 -0
- package/CORE.md +13 -5
- package/README.md +73 -16
- package/SPEC.md +38 -3
- package/bin/scrumrun.js +102 -13
- package/docs/COMMANDS.md +17 -7
- package/docs/ENTITY-MODEL.md +17 -14
- package/docs/ERROR-CODES.md +4 -0
- package/docs/QUICKSTART.md +21 -19
- package/docs/SCHEMA.md +14 -10
- package/docs/SEMANTIC-MEMORY.md +28 -0
- package/lib/actions/index.js +81 -0
- package/lib/commands/manifest.js +4 -3
- package/lib/commands/render.js +3 -2
- package/lib/errors.js +4 -0
- package/lib/git/context.js +30 -0
- package/lib/guardrails/changeset.js +45 -0
- package/lib/guardrails/evaluate.js +175 -0
- package/lib/memory/compaction.js +289 -0
- package/lib/memory/index.js +62 -2
- package/lib/migrate/ops.js +92 -0
- package/lib/migrate/run.js +108 -0
- package/lib/runtime/briefing.js +29 -0
- package/lib/runtime/context.js +3 -1
- package/lib/runtime/orchestrator.js +4 -4
- package/lib/runtime/policy-engine.js +11 -0
- package/lib/runtime/policy-integrity.js +83 -0
- package/lib/runtime/watcher.js +185 -0
- package/lib/v2/artifacts.js +9 -0
- package/lib/v2/conformance.js +45 -18
- package/lib/v2/paths.js +2 -1
- package/lib/v2/runs-jsonl.js +134 -0
- package/lib/v2/schema.js +7 -7
- package/lib/v2/task-schema.js +133 -0
- package/package.json +2 -2
- package/scripts/generate-contract-docs.js +6 -2
- package/templates/project/.scrumrun/config.md +9 -0
- package/templates/project/.scrumrun/method.json +3 -0
- package/templates/project/AGENTS.md +10 -4
- package/templates/project-lean/AGENTS.md +6 -2
- package/templates/shared/hooks/pre-commit +16 -0
- package/templates/shared/skills/scrumrun/SKILL.md +11 -7
- package/templates/shared/view.html +281 -0
- package/types/index.d.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,35 @@ All notable changes follow Semantic Versioning.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 4.1.0 - 2026-09-22
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Declarative migration runner (`lib/migrate/run.js`).** Migrations become plain Markdown files under `migrations/*.md` with fenced ````yaml steps`, ````yaml verify`, and optional ````yaml rollback` blocks. Whitelisted ops: `create_backup`, `rename_path`, `bump_schema`, `move_frontmatter_field`, `assert_hash`. Runner supports `{ dryRun: true }` (no writes) and returns `{ status, journal }` so rollback can operate on exactly what was applied. Path safety enforced: absolute paths and paths escaping the project root are rejected. See `migrations/README.md` for the format contract. Rewrite of the existing v1→v2 imperative migration into this format is delegated to the release cycle (large diff, coordinated release).
|
|
12
|
+
- **Declarative actions API (`lib/actions/`).** New `executeAction(name, projectRoot, payload)` entry point exposes 7 pure functions (`plan.task.add`, `plan.feature.add`, `plan.sprint.add`, `plan.task.amend`, `knowledge.fact.add`, `knowledge.decision.add`, `knowledge.insight.propose`) that delegate to the existing orchestrator/memory services, sharing validation and atomicity. New CLI command `scrumrun action <name> [--payload <json>|--file <path>|--stdin]` and `scrumrun action --list`. Enables hooks, the static view (TASK-026), and future clients to share one write layer without shelling into subcommands. Existing `plan/knowledge/rules/review/config` subcommands are unchanged; rip-out is a release-cycle task.
|
|
13
|
+
- **Append-only per-Task Run ledger (`runs/TASK-NNN.jsonl`).** New `lib/v2/runs-jsonl.js` records each execution event on one line with SHA-256 chain (`prev`/`hash`) for tamper detection. Supersedes the one-file-per-attempt Markdown layout for new work; historic `RUN-NNN.md` files remain readable. Cross-process append safety via `TASK-NNN.jsonl.lock` (exclusive `open wx` + jittered backoff). Design captured in `DEC-010`. Reader/writer wiring for `scrumrun plan run *` and migration of legacy Markdown Runs will land alongside the declarative migration runner (see task TASK-030).
|
|
14
|
+
- **Static HTML view at `.scrumrun/view.html`.** Zero-dependency single-file dashboard (vanilla JS, inline CSS, self-contained) that reads canonical Markdown via relative `fetch()` and renders a status kanban (Tasks), a recent-Runs list, active Guardrails, and Decisions. `scrumrun init` copies it into every project; `scrumrun update --project` refreshes it. Open with `open .scrumrun/view.html` on macOS, `xdg-open .scrumrun/view.html` on Linux, or `start .scrumrun\view.html` on Windows. If your browser blocks `file://` fetches, serve locally: `cd .scrumrun && python3 -m http.server 8080`.
|
|
15
|
+
- **Task Markdown schema validator (opt-in).** New pure library `lib/v2/task-schema.js` validates that a Task carries the sections and evidence its lifecycle requires: `## Request` + `## Done when` for opt-in Tasks, `## Completion` on `status: completed` (or a linked Run whose body contains `## Technical Summary`), and — inside a git repo — a `branch` field in the frontmatter when the Task is `running`/`in_progress`/`validating`/`learning`. Errors: `SR-E-452` (missing section), `SR-E-453` (completed without summary), `SR-E-454` (running without branch, warning-only). Legacy Tasks without `task_schema: 1` in frontmatter are silently skipped for full backward compatibility. Wired into `scrumrun review artifact --run` and `scrumrun doctor --strict`; both accept `--strict` to promote schema warnings to blocking errors.
|
|
16
|
+
- **`lib/git/context.js`.** Pure shell-out helper that returns `{ isRepo, branch, headSha }` for any project directory. Never throws — returns a non-repo shape when git is missing or the cwd is outside a working tree. Cross-platform: resolves `git` from `PATH` (Git for Windows, macOS, Linux). Consumed by the task-schema validator and available to any future feature (e.g. review/verify diff scoping).
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **Legacy `sc-*` skill directories are removed on install/update.** Older versions of ScrumRun published one skill per compatibility alias (`sc-sprint`, `sc-decisions`, `sc-vault`, …). Every listed skill costs context in every client conversation, so install/update now sweeps those directories from the target skills folder alongside the pre-existing `ai-scrum` cleanup, while leaving unrelated user skills untouched. The canonical skill remains `scrumrun`; the `scrumrun sc-*` command aliases are unchanged.
|
|
21
|
+
|
|
22
|
+
## 4.0.0 - 2026-08-31
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- **Simple Markdown model.** Core, Guardrails, Knowledge, Feature, Sprint, Task, Run, and Backlog are one local Markdown graph connected by stable IDs and relative links. Derived cache/index data is optional and never required for normal work.
|
|
27
|
+
- **Execution-first.** An approved Task continues through discover → implement → verify → fix → verify. Intermediate inventories, progress reports, and discovered in-scope gaps are internal work, never a valid stopping point or Follow-up.
|
|
28
|
+
- **Flexible Task bodies.** Tasks preserve arbitrary owner frontmatter and sections. `## Done when` and `## Completion` are the packaged minimal convention; project Guardrails may require extra sections only for affected Tasks.
|
|
29
|
+
- **Human status vocabulary.** `in_progress` is accepted as a Task status. A Markdown-first Task neither needs a Run nor must agree with historical Run state.
|
|
30
|
+
- **Runs are optional.** A Run may record a Task or a Sprint execution, but no Run, ledger, permit, or CLI state transition can block daily delivery.
|
|
31
|
+
|
|
32
|
+
### Safety
|
|
33
|
+
|
|
34
|
+
- **Sealed Markdown policy.** Fresh and refreshed projects pin Core and Guardrail fingerprints. Agents do not edit policy during product work; owner-reviewed policy changes use `scrumrun update --project --seal-policy`. Strict doctor/release audits detect policy drift at the edge, not during every edit.
|
|
35
|
+
|
|
7
36
|
## 3.1.2 - 2026-08-31
|
|
8
37
|
|
|
9
38
|
### Fixed
|
package/CORE.md
CHANGED
|
@@ -84,13 +84,21 @@ AGENTS.md
|
|
|
84
84
|
|
|
85
85
|
**Before querying project state, read `.scrumrun/method.json`.** Its `paths` block is the authoritative index of every canonical location in this project. Navigate by that index; if a path is not declared there, it is not canonical truth. Directory listing and grep are fallbacks — never the first step. A ScrumRun-aware agent must never search for `goals/`, `backlog.md`, `sprint.md`, or any legacy layout: those are absent by design once migration completes and are surfaced only through `.scrumrun/.migration-backup/`.
|
|
86
86
|
|
|
87
|
-
**Markdown is the normal runtime.** After explicit approval, work directly in source files and relevant `.scrumrun/` Markdown. A Task is free to be created, refined, started, completed, and handed off in Markdown; a Run is optional audit context, never a state machine that can prevent daily work. Update the Task's scope,
|
|
87
|
+
**Markdown is the normal runtime.** After explicit approval, work directly in source files and relevant `.scrumrun/` Markdown. A Task is free to be created, refined, started, completed, and handed off in Markdown; a Run is optional audit context, never a state machine that can prevent daily work. Update the Task's scope, Done when, Completion, and Follow-ups directly. Do not use `npx scrumrun@latest` or normal `scrumrun plan/run` commands during execution.
|
|
88
|
+
|
|
89
|
+
**Execution is continuous.** Once the owner approves a Task, implement it through its delivery contract before replying. Keep using tools and editing files through the full loop: discover → implement → verify → fix → verify. A progress report is allowed only when the owner asks for status, and it must be followed immediately by more execution in the same workflow; it is never an endpoint. Do not stop to give an inventory, a progress report, a decomposition, or a remaining-work list: those are internal steps, not a deliverable. A discovery of missing code, literals, tests, migrations, or configuration inside the approved contract is required work to implement now — it cannot become a report, a partial checker, a “next step”, or a Follow-up. Stop only for an owner decision, external access, an explicit Guardrail, a secret/security risk, destructive work without approval, or an unmet required delivery criterion. A Task's `## Done when` is short and observable; `## Follow-ups` contains only work outside that contract. Never move unfinished contract work to Follow-ups without explicit owner approval.
|
|
90
|
+
|
|
91
|
+
**Verification must cover the claim.** Never claim that a Task condition is verified merely because a narrower check passes. If the request is “no visible hardcoded literals”, a locale-key parity checker alone is insufficient: scan the relevant views for literals, replace every result in scope, then re-run both the scan and the build. The same rule applies to every delivery claim.
|
|
88
92
|
|
|
89
93
|
**The CLI is maintenance, not a work gate.** Use it for `init`, `update --project`, `migrate`, `repair`, `doctor`, reports, and release checks. Strict per-edit permits and ledger finalization remain available only when the owner asks for that audit level. Missing/invalid Runs, old status vocabulary, stale projections, and optional tests are warnings to reconcile in Markdown — never an automatic blocker.
|
|
90
94
|
|
|
91
|
-
**Block only on real constraints.** An agent must stop for an explicit active Guardrail, secret/security risk, destructive action without approval, or an unmet required
|
|
95
|
+
**Block only on real constraints.** An agent must stop for an explicit active Guardrail, secret/security risk, destructive action without approval, or an unmet required Done when item. It must not manufacture a failed/blocked Run because optional E2E coverage, an optional reviewer, or a non-required environment is unavailable; record meaningful gaps in `## Follow-ups` or a risk note.
|
|
96
|
+
|
|
97
|
+
**Normal operation never mutates Run state through the CLI.** Do not call `plan run --fail|--block|--retry|--finalize|--complete|--validate` or `plan task --start` in daily work. Those are owner-requested strict audit tools only. When a legacy Run already has the wrong administrative outcome, preserve it as history and correct the delivery record directly in the Task's Completion and Follow-ups.
|
|
98
|
+
|
|
99
|
+
**Policy is sealed at the edge.** `core.md` is the universal execution contract and `guardrails.md` is project policy. Never edit either while delivering product work. A policy change requires an explicit owner request; after review, `scrumrun update --project --seal-policy` records fresh fingerprints. Daily work stays Markdown-only; `doctor --strict` and release audit policy fingerprints, canonical guardrails, and code checks at the boundary.
|
|
92
100
|
|
|
93
|
-
**
|
|
101
|
+
**Markdown relations are the graph.** Every artifact has a stable ID. Use small frontmatter links such as `sprint: SPRINT-012`, `feature: FEAT-003`, and `depends_on: [TASK-151, DEC-008]`, plus a human-readable `## Related` section with relative links. Preserve all unknown frontmatter and all owner-defined sections. A Guardrail may require a Task section such as `## Migration Plan`, `## Rollback`, or `## Guardrail Evidence`; add it only to the affected Task and keep it until the rule is satisfied.
|
|
94
102
|
|
|
95
103
|
Canonical truth is Markdown. SQLite/cache data stores only rebuildable indexes, symbol projections, relations, and bounded context packages. Deleting `.cache/` must never delete authored truth.
|
|
96
104
|
|
|
@@ -176,7 +184,7 @@ understand → approve → work → validate required criteria → hand off
|
|
|
176
184
|
|
|
177
185
|
Rules:
|
|
178
186
|
|
|
179
|
-
- a Task carries
|
|
187
|
+
- a Task carries intended scope, a short `## Done when` contract, `## Completion`, and relevant `## Follow-ups`;
|
|
180
188
|
- validation matches risk and acceptance criteria; tests, reviews, and environments are gates only when explicitly required by the owner, the Task, or an active Guardrail;
|
|
181
189
|
- direct Markdown workflow never blocks on Run linkage, status syntax, stale generated views, or missing optional coverage. If an optional check matters, record it as a follow-up/risk instead of fabricating failure;
|
|
182
190
|
- configured reviews run only when a Guardrail requires one;
|
|
@@ -184,7 +192,7 @@ Rules:
|
|
|
184
192
|
- strict permits, workspace-drift checks, and append-only Guardrail obligations apply only to that optional strict audit path;
|
|
185
193
|
- learning proposes memory candidates when work reveals reusable context and never auto-confirms AI inference;
|
|
186
194
|
- complete a Sprint only when its included Tasks meet its real exit gate;
|
|
187
|
-
- do not mark work complete merely because time or token budget ended.
|
|
195
|
+
- do not mark work complete merely because time or token budget ended, and do not stop an approved Task merely to report intermediate progress.
|
|
188
196
|
|
|
189
197
|
Canonical mutations are schema-validated, lossless, and atomic. Preserve unknown fields, prose, and unrelated owner edits. A failed mutation must leave canonical state unchanged or recoverable.
|
|
190
198
|
|
package/README.md
CHANGED
|
@@ -4,30 +4,33 @@
|
|
|
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:** `
|
|
7
|
+
**Package:** `4.1.0` · **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
|
|
|
11
11
|
## The model
|
|
12
12
|
|
|
13
13
|
```text
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
Core = how the agent works
|
|
15
|
+
Guardrails = rules that cannot be broken
|
|
16
|
+
Knowledge = what the project knows and why
|
|
17
|
+
Backlog = provisioned Tasks not yet started
|
|
18
|
+
Feature = why a larger initiative exists
|
|
19
|
+
Sprint = a feature, fix, or maintenance delivery grouping Tasks
|
|
20
|
+
Task = concrete work, independent or in a Sprint
|
|
21
|
+
Run = optional record of what happened while executing a Task/Sprint
|
|
19
22
|
```
|
|
20
23
|
|
|
21
24
|
```text
|
|
22
|
-
|
|
25
|
+
SPRINT-012 (type: fix)
|
|
23
26
|
└── TASK-018
|
|
24
|
-
├──
|
|
25
|
-
├──
|
|
26
|
-
├──
|
|
27
|
-
└──
|
|
27
|
+
├── feature → FEAT-003
|
|
28
|
+
├── depends_on → TASK-014, DEC-018
|
|
29
|
+
├── guardrails → GR-004
|
|
30
|
+
└── run → RUN-044 (optional)
|
|
28
31
|
```
|
|
29
32
|
|
|
30
|
-
A Task does not need a Sprint. A
|
|
33
|
+
A Task does not need a Sprint. A Sprint may be `feature`, `fix`, or `maintenance`. A Run is optional and may document a Task or Sprint. Backlog is simply Tasks with `status: backlog`.
|
|
31
34
|
|
|
32
35
|
See [`docs/SCHEMA.md`](docs/SCHEMA.md) for the generated executable contract and [`docs/ENTITY-MODEL.md`](docs/ENTITY-MODEL.md) for the conceptual guide.
|
|
33
36
|
|
|
@@ -60,6 +63,32 @@ scrumrun <noun> <subject> <action> [args]
|
|
|
60
63
|
|
|
61
64
|
The five nouns are `plan`, `knowledge`, `rules`, `review`, and `config`. `/sc` is an optional AI-client shortcut; `scrumrun sc ...` remains a compatibility alias for existing integrations.
|
|
62
65
|
|
|
66
|
+
## Compatibility
|
|
67
|
+
|
|
68
|
+
ScrumRun is designed to be **portable across AI clients and operating systems**. The runtime is plain Markdown + a small Node.js CLI; nothing is tied to a specific vendor.
|
|
69
|
+
|
|
70
|
+
### Operating systems
|
|
71
|
+
|
|
72
|
+
| OS | Status | Notes |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| macOS 12+ | Supported | Primary development platform. |
|
|
75
|
+
| Linux (glibc-based distros) | Supported | Tested on Ubuntu/Debian/Fedora; `fs.watch` uses inotify. |
|
|
76
|
+
| Windows 10/11 | Supported | Requires Git for Windows for the optional pre-commit hook; `.scrumrun/` paths are POSIX-normalized internally. |
|
|
77
|
+
| WSL2 | Supported | Behaves as Linux. |
|
|
78
|
+
|
|
79
|
+
Requirement everywhere: **Node.js ≥ 22.13.0** and (optionally) `git` on `PATH`.
|
|
80
|
+
|
|
81
|
+
### AI clients
|
|
82
|
+
|
|
83
|
+
| Client | Integration | Notes |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| Claude Code | `scrumrun install claude` | Installs the `scrumrun` skill under `~/.claude/skills/`. |
|
|
86
|
+
| OpenCode | `scrumrun install opencode` | Installs skill under `~/.config/opencode/skills/`. |
|
|
87
|
+
| Codex | `scrumrun install codex` | Installs skill under `~/.codex/skills/`. |
|
|
88
|
+
| Cursor / Windsurf / Zed / any Markdown-capable agent | Manual | Point the agent at `.scrumrun/` and `CORE.md`; no CLI adapter required. |
|
|
89
|
+
|
|
90
|
+
The method itself (Markdown tree + guardrails + task/run model) is client-agnostic: any agent that can read files can operate a ScrumRun project.
|
|
91
|
+
|
|
63
92
|
## Daily flow
|
|
64
93
|
|
|
65
94
|
Natural language is the normal entry point:
|
|
@@ -79,15 +108,17 @@ RECEIVED → CONTEXTUALIZING → POLICY → RISK → CLASSIFICATION
|
|
|
79
108
|
|
|
80
109
|
The agent may assert the classification (`--type fix|task|feature|docs|discovery`) and attach a short technical preview (`--preview "…"`), rendered with color in the terminal before any Task exists. Nothing canonical is persisted before approval.
|
|
81
110
|
|
|
82
|
-
Explicit approval authorizes work. In
|
|
111
|
+
Explicit approval authorizes work. In 4.0, the daily runtime is the `.scrumrun/` folder: the agent creates or refines the relevant Task Markdown, works in code, and leaves a short handoff. Feature, Sprint, and Run are optional context, not prerequisites. A structured CLI audit path remains available only at maintenance/release edges.
|
|
83
112
|
|
|
84
113
|
```text
|
|
85
114
|
EXECUTING → VALIDATING → LEARNING → COMPLETED | FAILED | BLOCKED
|
|
86
115
|
```
|
|
87
116
|
|
|
88
|
-
Every Task carries `##
|
|
117
|
+
Every Task carries a short `## Done when` delivery contract. After approval, the agent works directly in code and Task Markdown until that contract is delivered: it keeps the full discover → implement → verify → fix → verify loop running. A report is allowed only when you ask for it and never ends execution. The normal close is a concise `## Completion`; `## Follow-ups` may only contain work outside the agreed contract. No CLI transition is required.
|
|
89
118
|
|
|
90
|
-
|
|
119
|
+
**Opt-in Task-schema validator.** Adding `task_schema: 1` to a Task's frontmatter turns on the structural checks in `lib/v2/task-schema.js`: `## Request` + `## Done when` are required, `## Completion` (or an associated Run's `## Technical Summary`) is required once the Task is `completed`, and inside a git repo the Task must record its `branch` while executing. `scrumrun doctor --strict` and `scrumrun review artifact --run --strict` promote these to blocking errors; without `--strict` they are warnings. Legacy Tasks without `task_schema` are unaffected.
|
|
120
|
+
|
|
121
|
+
Guardrails still apply. An agent stops only for an explicit active Guardrail, a secret/security risk, destructive work without approval, or an unmet required delivery criterion. Tests, reviews, and environments are gates only when the owner, `Done when`, or a Guardrail explicitly requires them. Optional missing E2E coverage is a follow-up/risk, not a failed Task.
|
|
91
122
|
|
|
92
123
|
Use the CLI at the edges, where its safety is valuable:
|
|
93
124
|
|
|
@@ -99,6 +130,10 @@ scrumrun repair --recover-orphan-tasks --apply
|
|
|
99
130
|
scrumrun review release --run
|
|
100
131
|
```
|
|
101
132
|
|
|
133
|
+
`core.md` and `guardrails.md` are sealed Markdown policy. Agents never edit them during normal product work. An owner-requested policy change is reviewed and then sealed explicitly with `scrumrun update --project --seal-policy`; `doctor --strict` and release checks detect later policy drift.
|
|
134
|
+
|
|
135
|
+
Relations are plain, offline Markdown: stable IDs in frontmatter (`sprint: SPRINT-012`, `depends_on: [TASK-014, DEC-018]`) and relative links in `## Related`. Task Markdown is intentionally extensible: a Guardrail can require `## Migration Plan`, `## Rollback`, or `## Guardrail Evidence` only where relevant, and ScrumRun preserves every unknown section.
|
|
136
|
+
|
|
102
137
|
`update --project` refreshes packaged `core.md` and recognized generated `AGENTS.md` with a local byte-exact backup before replacing them. The CLI can still generate/validate Task, Feature, Sprint, and Run records when desired, but it must never become a routine blocker.
|
|
103
138
|
|
|
104
139
|
For extra protection, CLI Task start/retry and every Run state transition require `--strict`. This prevents accidental administrative failures in the normal Markdown-first workflow.
|
|
@@ -144,6 +179,22 @@ The fast graph/search layer is `.scrumrun/.cache/semantic-index.sqlite`. It is i
|
|
|
144
179
|
|
|
145
180
|
`map.md` is shown only when its source fingerprint matches the current semantic index. A fresh placeholder or stale map is rejected with an explicit rebuild instruction instead of being presented as project truth.
|
|
146
181
|
|
|
182
|
+
For local projects that benefit from always-fresh projections, opt into the lightweight watcher in `.scrumrun/config.md` and start it once:
|
|
183
|
+
|
|
184
|
+
```yaml
|
|
185
|
+
watcher.enabled: true
|
|
186
|
+
watcher.debounce_ms: 250
|
|
187
|
+
watcher.poll_interval_ms: 1500
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
scrumrun config watch --start
|
|
192
|
+
scrumrun config watch --status
|
|
193
|
+
scrumrun config watch --stop
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The watcher uses native `fs.watch` where recursive watching is available and polling otherwise. It is never authority or a work gate: a later on-demand rebuild always remains correct if it stops. The daemon records its PID in `.scrumrun/.cache/watcher.pid`, ignores the vault, `.cache/contexts/`, and its own generated outputs, coalesces rapid writes, and writes only `state.md`, `map.md`, and `.cache/`.
|
|
197
|
+
|
|
147
198
|
## Project briefing
|
|
148
199
|
|
|
149
200
|
`state.md` is the **briefing**: a bounded summary an agent reads first, before touching anything else.
|
|
@@ -161,12 +212,18 @@ It is progressive disclosure: the briefing is enough for most work; the agent fo
|
|
|
161
212
|
|
|
162
213
|
## Migrating an ongoing v1 project
|
|
163
214
|
|
|
164
|
-
Update the client integrations. For an existing project, refresh the
|
|
215
|
+
Update the client integrations. For an existing project, refresh the execution-first guidance explicitly:
|
|
165
216
|
|
|
166
217
|
```bash
|
|
167
218
|
scrumrun update --project
|
|
168
219
|
```
|
|
169
220
|
|
|
221
|
+
If you intentionally changed project Guardrails after owner review, seal the reviewed Markdown policy once:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
scrumrun update --project --seal-policy
|
|
225
|
+
```
|
|
226
|
+
|
|
170
227
|
This shows the source inventory, proposed mappings, and blockers without changing project data. Apply only the verified plan with:
|
|
171
228
|
|
|
172
229
|
```bash
|
package/SPEC.md
CHANGED
|
@@ -83,6 +83,8 @@ method: 2.0.0
|
|
|
83
83
|
|
|
84
84
|
IDs, filenames, kind, status, real ISO dates, and method version must agree. Unknown fields and authored prose are preserved. Duplicate fields, malformed frontmatter, unsafe paths, and symlinked canonical paths are invalid.
|
|
85
85
|
|
|
86
|
+
Relationship lists are valid local frontmatter, for example `depends_on: [TASK-014, DEC-018]` and `guardrails: [GR-004]`. Human-readable `## Related` links use relative Markdown paths. These local IDs and links are the canonical graph; generated indexes only accelerate retrieval.
|
|
87
|
+
|
|
86
88
|
A Task may carry an optional `assignee` scalar recording the agent identity (`SCRUMRUN_AGENT` or `config.md` `Agent Identity`) that owns the work. It is descriptive metadata, never a competing authority: it does not change status transitions or block conformance.
|
|
87
89
|
|
|
88
90
|
### 3.2 Stable identifiers
|
|
@@ -200,13 +202,15 @@ RECEIVED
|
|
|
200
202
|
|
|
201
203
|
Everything through `AWAITING_APPROVAL` is read-only. It may exist in process memory or ignored cache only. A valid approval token binds the normalized request, policy result, classification, risk, issuance time, canonical context fingerprint, and complete workspace fingerprint. Canonical or source drift after planning invalidates approval.
|
|
202
204
|
|
|
203
|
-
Approval authorizes work after the read-only planning pass. In Markdown-first mode, a Task and optional Run may be created or updated directly; their absence or imperfect administrative metadata never prevents approved work. The CLI's atomic Task/Run creation remains an optional strict/audit path. Tests, reviews, and environments are completion gates only when explicitly required by the owner, the Task's
|
|
205
|
+
Approval authorizes work after the read-only planning pass. In Markdown-first mode, a Task and optional Run may be created or updated directly; their absence or imperfect administrative metadata never prevents approved work. The CLI's atomic Task/Run creation remains an optional strict/audit path. Tests, reviews, and environments are completion gates only when explicitly required by the owner, the Task's `## Done when` contract, or an active Guardrail; missing optional coverage is a documented follow-up/risk, not a failure by itself.
|
|
206
|
+
|
|
207
|
+
An approved Task executes continuously to its delivery contract. An agent must not end a work turn merely to provide inventory, decomposition, progress, or a list of remaining implementation work. Those are internal execution steps. It may stop only for an owner decision, external access, an active Guardrail, secret/security risk, destructive work without approval, or an unmet required contract item. `## Follow-ups` may contain only work outside `## Done when`; moving required work there requires explicit owner approval.
|
|
204
208
|
|
|
205
209
|
When a structured Run is explicitly chosen, it binds the exact Guardrail-policy fingerprint and workspace baseline. Strict audit then verifies the complete delta: policy freshness, read-only boundaries, symlink safety, scannability, newly introduced secret-like content, and evidence for every Guardrail. Strict teams may opt into short-lived, path-scoped permits and per-edit recording. This audit path is never a prerequisite for ordinary Markdown-first execution.
|
|
206
210
|
|
|
207
|
-
The agent may assert the classification explicitly (`--type fix|task|feature|docs|discovery`), overriding keyword inference with validation and a stable reason. It may attach a short technical preview (`--preview`), rendered in the terminal, bound into the approval token, and stored as `## Preview` on the approved Task. A Task declares
|
|
211
|
+
The agent may assert the classification explicitly (`--type fix|task|feature|docs|discovery`), overriding keyword inference with validation and a stable reason. It may attach a short technical preview (`--preview`), rendered in the terminal, bound into the approval token, and stored as `## Preview` on the approved Task. A Task normally declares a concise `## Done when` contract before execution, but owner-defined Markdown sections remain valid; completion is measured against the agreed delivery contract, never against elapsed time or token budget.
|
|
208
212
|
|
|
209
|
-
When a structured Run is used, CLI transitions synchronously update the linked Task and append one event to its ledger. This is an optional audit path, not daily operational authority. Markdown-first completion records the
|
|
213
|
+
When a structured Run is used, CLI transitions synchronously update the linked Task and append one event to its ledger. This is an optional audit path, not daily operational authority. Markdown-first completion records the Done when contract, Completion, validation evidence, and Follow-ups directly on the Task. Multi-file CLI mutations use a durable local transaction journal; `doctor --recover` and `repair` remain explicit maintenance operations. Entering learning may extract candidates, but no administrative artifact failure blocks approved work.
|
|
210
214
|
|
|
211
215
|
Backlog is a queue view of intentionally parked Tasks, ordered oldest-first by id. CLI `--next`/`--start` helpers may create a structured Run when wanted, but an explicit owner approval is the only daily-work start gate.
|
|
212
216
|
|
|
@@ -230,6 +234,37 @@ Secret-like content detection is canonical-policy-level and applies to every art
|
|
|
230
234
|
|
|
231
235
|
The executable Policy Engine may infer enforcement for migrated prose, but fresh v2 policy declares it explicitly. Unknown enforcement, duplicate ids, inactive-only policy, configuration that disables approval, and unsafe read-only paths fail conformance. Configuration can tune presentation and workflow preferences; it cannot retire, bypass, or weaken active Guardrails.
|
|
232
236
|
|
|
237
|
+
### 6.1 Declarative Guardrail enforcement
|
|
238
|
+
|
|
239
|
+
A Guardrail may add one optional fenced `yaml enforcement` block. It is parsed without an LLM and evaluated as a pure function over a ChangeSet (`paths`, `diff`, and optional `symbols`); ordinary prose-only Guardrails remain valid. The supported YAML subset is intentionally limited to mappings and string lists so every installed client evaluates the same rule without a network dependency.
|
|
240
|
+
|
|
241
|
+
````markdown
|
|
242
|
+
## GR-010 - No debug logs in production code
|
|
243
|
+
|
|
244
|
+
Status: active
|
|
245
|
+
Enforcement: manual
|
|
246
|
+
Scope: validation, commit
|
|
247
|
+
Rule: Production changes must not add debug logging.
|
|
248
|
+
|
|
249
|
+
```yaml enforcement
|
|
250
|
+
match:
|
|
251
|
+
paths:
|
|
252
|
+
- "src/**/*.js"
|
|
253
|
+
diff:
|
|
254
|
+
- "/\\bconsole\\.log\\s*\\(/"
|
|
255
|
+
symbols:
|
|
256
|
+
- "debug*"
|
|
257
|
+
on_violation: block
|
|
258
|
+
severity: high
|
|
259
|
+
evidence:
|
|
260
|
+
- "Remove debug output or justify it in the reviewed policy."
|
|
261
|
+
```
|
|
262
|
+
````
|
|
263
|
+
|
|
264
|
+
`match.paths` accepts globs (`src/**`), extensions (`.ts` or `ext:.ts`), and regexes (`regex:^src/` or `/^src\\//`). `match.diff` accepts regexes (recommended) or literal fragments; `match.symbols` uses the same glob/regex form. At least one matcher is required. `on_violation` is `block` or `warn`; `severity` is `low`, `medium`, `high`, or `critical`; `evidence` is an optional scalar or string list surfaced with a match. Invalid blocks are a conformance error with `SR-E-153`.
|
|
265
|
+
|
|
266
|
+
The declared action is authoritative. `config.md` may promote a warning to a block through `Guardrail On Violation: block`; it may never downgrade an explicit block. `scrumrun review artifact --run` evaluates the worktree, `--staged` evaluates the index, and `doctor --strict` consumes the same evaluator. The optional offline pre-commit template is `templates/shared/hooks/pre-commit`.
|
|
267
|
+
|
|
233
268
|
## 7. Semantic memory and code intelligence
|
|
234
269
|
|
|
235
270
|
Memory records include subject, source, evidence, validity window, confidence where useful, review trigger, and last-verified commit. Insight types may include placement rationale, design constraint, known trade-off, failure history, usage warning, compatibility reason, business rule, performance reason, security reason, and testing note.
|
package/bin/scrumrun.js
CHANGED
|
@@ -35,10 +35,13 @@ const { addPlanArtifact, amendPlanArtifact, approveRequest, finalizeRun, nextBac
|
|
|
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"));
|
|
38
|
+
const { applyCompaction, proposedClusters, rollbackCompaction } = require(path.join(root, "lib", "memory", "compaction"));
|
|
38
39
|
const { indexPath, indexStatus, mapStatus, queryIndex, rebuildIndex, writeMap } = require(path.join(root, "lib", "memory", "index"));
|
|
39
40
|
const { auditProject } = require(path.join(root, "lib", "v2", "conformance"));
|
|
40
41
|
const { recoverPendingTransactions, previewPendingRecovery } = require(path.join(root, "lib", "v2", "transaction"));
|
|
41
42
|
const { containsSecret } = require(path.join(root, "lib", "security", "secrets"));
|
|
43
|
+
const { sealPolicyIntegrity } = require(path.join(root, "lib", "runtime", "policy-integrity"));
|
|
44
|
+
const { readStatus: watcherStatus, startWatcher, stopWatcher } = require(path.join(root, "lib", "runtime", "watcher"));
|
|
42
45
|
|
|
43
46
|
const COMMANDS = ["sc"];
|
|
44
47
|
const COMPATIBILITY_COMMANDS = Object.keys(COMMAND_ALIASES);
|
|
@@ -58,7 +61,7 @@ Usage:
|
|
|
58
61
|
scrumrun <noun> <subject> <action> [args]
|
|
59
62
|
scrumrun sc <noun> <subject> <action> [args] # compatibility alias
|
|
60
63
|
scrumrun install [all|codex|opencode|claude] [--force]
|
|
61
|
-
scrumrun update [all|codex|opencode|claude] [--project] [--migrate] [--verbose]
|
|
64
|
+
scrumrun update [all|codex|opencode|claude] [--project] [--seal-policy] [--migrate] [--verbose]
|
|
62
65
|
scrumrun init [--local|--shared] [--lean] [--no-agent-hint] [--force]
|
|
63
66
|
scrumrun status
|
|
64
67
|
scrumrun core [--path|--prompt]
|
|
@@ -67,6 +70,7 @@ Usage:
|
|
|
67
70
|
scrumrun migrate --to 2 --apply
|
|
68
71
|
scrumrun migrate --to 2 --rollback
|
|
69
72
|
scrumrun doctor [all|codex|opencode|claude] [--strict] [--recover]
|
|
73
|
+
scrumrun config watch --start|--stop|--status # optional generated-projection daemon; never a gate
|
|
70
74
|
scrumrun repair [--recover-orphan-tasks] [--apply]
|
|
71
75
|
scrumrun uninstall [--force]
|
|
72
76
|
|
|
@@ -218,11 +222,16 @@ function cleanupLegacy(commandsDir, skillsDir) {
|
|
|
218
222
|
}
|
|
219
223
|
}
|
|
220
224
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
fs.
|
|
224
|
-
|
|
225
|
-
|
|
225
|
+
if (fs.existsSync(skillsDir)) {
|
|
226
|
+
const legacySkillNames = new Set(["ai-scrum", ...COMPATIBILITY_COMMANDS]);
|
|
227
|
+
for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
|
|
228
|
+
if (!entry.isDirectory()) continue;
|
|
229
|
+
if (!legacySkillNames.has(entry.name)) continue;
|
|
230
|
+
const target = path.join(skillsDir, entry.name);
|
|
231
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
232
|
+
installSummary.cleaned += 1;
|
|
233
|
+
installLog(` rm legacy ${target}`);
|
|
234
|
+
}
|
|
226
235
|
}
|
|
227
236
|
}
|
|
228
237
|
|
|
@@ -380,10 +389,16 @@ function refreshProjectGuidance(cwd = process.cwd()) {
|
|
|
380
389
|
} else {
|
|
381
390
|
results.push({ status: "skipped", dest: `${agentsFile} (not recognized as ScrumRun-generated)` });
|
|
382
391
|
}
|
|
392
|
+
const marker = path.join(cwd, ".scrumrun", "method.json");
|
|
393
|
+
const sealed = writeFile(marker, sealPolicyIntegrity(path.join(cwd, ".scrumrun")), { backup: true });
|
|
394
|
+
results.push({ status: sealed.changed ? "updated" : "skipped", dest: marker, backup: sealed.backup });
|
|
395
|
+
const viewFile = path.join(cwd, ".scrumrun", "view.html");
|
|
396
|
+
const viewResult = writeFile(viewFile, fs.readFileSync(path.join(templates, "shared", "view.html"), "utf8"), { backup: true });
|
|
397
|
+
results.push({ status: viewResult.changed ? "updated" : "skipped", dest: viewFile, backup: viewResult.backup });
|
|
383
398
|
return results;
|
|
384
399
|
}
|
|
385
400
|
|
|
386
|
-
function updateInstallation(target, { migrate = false, project = false, verbose = false } = {}) {
|
|
401
|
+
function updateInstallation(target, { migrate = false, project = false, sealPolicy = false, verbose = false } = {}) {
|
|
387
402
|
installVerbose = verbose;
|
|
388
403
|
installSummary.cleaned = 0;
|
|
389
404
|
installSummary.written = 0;
|
|
@@ -391,7 +406,14 @@ function updateInstallation(target, { migrate = false, project = false, verbose
|
|
|
391
406
|
installSummary.targets.length = 0;
|
|
392
407
|
const migration = migrate ? migrationPreflightOnUpdate({ apply: true }) : { status: "skipped" };
|
|
393
408
|
install(target, true, { compatibility: true });
|
|
409
|
+
if (sealPolicy && !project) throw new Error("`--seal-policy` requires `--project` so the owner-reviewed project policy is explicit.");
|
|
394
410
|
const projectResults = project ? refreshProjectGuidance() : [];
|
|
411
|
+
if (sealPolicy && project) {
|
|
412
|
+
const scrumDir = path.join(process.cwd(), ".scrumrun");
|
|
413
|
+
const marker = path.join(scrumDir, "method.json");
|
|
414
|
+
const sealed = writeFile(marker, sealPolicyIntegrity(scrumDir, { includeGuardrails: true }), { backup: true });
|
|
415
|
+
projectResults.push({ status: sealed.changed ? "updated" : "skipped", dest: marker, backup: sealed.backup });
|
|
416
|
+
}
|
|
395
417
|
if (migrate && v2Project()) {
|
|
396
418
|
try {
|
|
397
419
|
refreshState(path.join(process.cwd(), ".scrumrun"));
|
|
@@ -1361,6 +1383,25 @@ function printMemoryArtifact(artifact) {
|
|
|
1361
1383
|
function runV2Memory(subject, args) {
|
|
1362
1384
|
const kind = subject === "fact" ? "knowledge" : subject;
|
|
1363
1385
|
const action = args[0];
|
|
1386
|
+
if (kind === "dossier" && action === "--compact") {
|
|
1387
|
+
if (args.includes("--dry-run")) {
|
|
1388
|
+
const preview = proposedClusters(process.cwd());
|
|
1389
|
+
console.log(JSON.stringify({ mode: "dry-run", ...preview }, null, 2));
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
if (args.includes("--apply")) {
|
|
1393
|
+
const result = applyCompaction(process.cwd(), { approved: args.includes("--approve") });
|
|
1394
|
+
console.log(JSON.stringify({ mode: "apply", ...result }, null, 2));
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
if (args.includes("--rollback")) {
|
|
1398
|
+
const dossier = args[args.indexOf("--rollback") + 1];
|
|
1399
|
+
if (!dossier || dossier.startsWith("--")) throw new Error("--rollback requires a DOS-NNN id.");
|
|
1400
|
+
console.log(JSON.stringify(rollbackCompaction(process.cwd(), dossier), null, 2));
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
throw new Error("Usage: scrumrun knowledge dossier --compact --dry-run|--apply --approve|--rollback DOS-NNN");
|
|
1404
|
+
}
|
|
1364
1405
|
const createAction = kind === "insight" ? "--propose" : "--add";
|
|
1365
1406
|
if (action === createAction) {
|
|
1366
1407
|
const artifact = createMemory(process.cwd(), kind, memoryOptions(args));
|
|
@@ -1680,7 +1721,7 @@ function executeRootRoute(route) {
|
|
|
1680
1721
|
if (noun === "knowledge" && subject === "vault") return runVault(routeArgs);
|
|
1681
1722
|
if (noun === "knowledge" && subject === "context") return runContext(routeArgs);
|
|
1682
1723
|
if (noun === "review" && subject === "artifact" && routeArgs[0] === "--run") {
|
|
1683
|
-
const audit = auditProject(process.cwd());
|
|
1724
|
+
const audit = auditProject(process.cwd(), { staged: routeArgs.includes("--staged"), strict: routeArgs.includes("--strict") });
|
|
1684
1725
|
console.log(JSON.stringify(audit, null, 2));
|
|
1685
1726
|
if (!audit.passed) process.exitCode = 1;
|
|
1686
1727
|
return;
|
|
@@ -1704,9 +1745,23 @@ function executeRootRoute(route) {
|
|
|
1704
1745
|
const target = ["all", "codex", "opencode", "claude"].includes(routeArgs[0]) ? routeArgs[0] : "all";
|
|
1705
1746
|
return doctor(target, { strict: routeArgs.includes("--strict"), recover: routeArgs.includes("--recover"), dryRun: routeArgs.includes("--dry-run") });
|
|
1706
1747
|
}
|
|
1748
|
+
if (noun === "config" && subject === "watch") {
|
|
1749
|
+
let result;
|
|
1750
|
+
if (routeArgs[0] === "--start") result = startWatcher(process.cwd());
|
|
1751
|
+
else if (routeArgs[0] === "--stop") result = stopWatcher(process.cwd());
|
|
1752
|
+
else if (routeArgs[0] === "--status") result = watcherStatus(process.cwd());
|
|
1753
|
+
else throw new Error("Usage: scrumrun config watch --start|--stop|--status");
|
|
1754
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1707
1757
|
if (noun === "config" && subject === "update") {
|
|
1708
1758
|
const target = ["all", "codex", "opencode", "claude"].includes(routeArgs[0]) ? routeArgs[0] : "all";
|
|
1709
|
-
return updateInstallation(target, {
|
|
1759
|
+
return updateInstallation(target, {
|
|
1760
|
+
migrate: routeArgs.includes("--migrate"),
|
|
1761
|
+
project: routeArgs.includes("--project"),
|
|
1762
|
+
sealPolicy: routeArgs.includes("--seal-policy"),
|
|
1763
|
+
verbose: routeArgs.includes("--verbose")
|
|
1764
|
+
});
|
|
1710
1765
|
}
|
|
1711
1766
|
if (noun === "config" && subject === "init") {
|
|
1712
1767
|
const localMode = routeArgs.includes("--local");
|
|
@@ -2322,6 +2377,8 @@ function promptCommand(parts) {
|
|
|
2322
2377
|
|
|
2323
2378
|
function initProject({ force, mode, agentHint, lean }) {
|
|
2324
2379
|
const cwd = process.cwd();
|
|
2380
|
+
const marker = path.join(cwd, ".scrumrun", "method.json");
|
|
2381
|
+
const markerExisted = fs.existsSync(marker);
|
|
2325
2382
|
const vars = {
|
|
2326
2383
|
PROJECT_NAME: path.basename(cwd),
|
|
2327
2384
|
DATE: new Date().toISOString().slice(0, 10)
|
|
@@ -2332,6 +2389,11 @@ function initProject({ force, mode, agentHint, lean }) {
|
|
|
2332
2389
|
|
|
2333
2390
|
results.push(...copyDir(path.join(projectTemplate, ".scrumrun"), path.join(cwd, ".scrumrun"), { force, vars }));
|
|
2334
2391
|
results.push(copyFile(path.join(root, "CORE.md"), path.join(cwd, ".scrumrun", "core.md"), { force, vars }));
|
|
2392
|
+
results.push(copyFile(path.join(templates, "shared", "view.html"), path.join(cwd, ".scrumrun", "view.html"), { force }));
|
|
2393
|
+
if (force || !markerExisted) {
|
|
2394
|
+
const sealed = writeFile(marker, sealPolicyIntegrity(path.join(cwd, ".scrumrun"), { includeGuardrails: true }), { backup: false });
|
|
2395
|
+
results.push({ status: sealed.changed ? "written" : "skipped", dest: marker, backup: sealed.backup });
|
|
2396
|
+
}
|
|
2335
2397
|
results.push(ensureProjectIgnore(cwd));
|
|
2336
2398
|
|
|
2337
2399
|
if (mode === "shared" || agentHint) {
|
|
@@ -2610,9 +2672,10 @@ function doctor(target = "all", { compatibility = false, strict = false, recover
|
|
|
2610
2672
|
ok = false;
|
|
2611
2673
|
console.log(`miss ScrumRun project audit: ${scrumDir}`);
|
|
2612
2674
|
} else {
|
|
2613
|
-
const audit = auditProject(process.cwd());
|
|
2614
|
-
|
|
2615
|
-
|
|
2675
|
+
const audit = auditProject(process.cwd(), { strict: true });
|
|
2676
|
+
const blocking = audit.findings.filter((item) => ["critical", "high"].includes(item.severity));
|
|
2677
|
+
ok = ok && audit.passed && blocking.length === 0;
|
|
2678
|
+
console.log(`${audit.passed && blocking.length === 0 ? "ok " : "fail"} ScrumRun project audit: ${audit.findings.length} finding(s)`);
|
|
2616
2679
|
for (const item of audit.findings) console.log(` ${item.severity} ${item.code}: ${item.message}`);
|
|
2617
2680
|
}
|
|
2618
2681
|
}
|
|
@@ -2633,12 +2696,38 @@ if (!command || command === "--help" || command === "-h") {
|
|
|
2633
2696
|
console.log(`ScrumRun ${version}`);
|
|
2634
2697
|
} else if (command === "install" || command === "update") {
|
|
2635
2698
|
const target = ["all", "codex", "opencode", "claude"].includes(args[1]) ? args[1] : "all";
|
|
2636
|
-
if (command === "update") updateInstallation(target, { migrate: args.includes("--migrate"), project: args.includes("--project"), verbose: args.includes("--verbose") });
|
|
2699
|
+
if (command === "update") updateInstallation(target, { migrate: args.includes("--migrate"), project: args.includes("--project"), sealPolicy: args.includes("--seal-policy"), verbose: args.includes("--verbose") });
|
|
2637
2700
|
else install(target, true, { compatibility: false });
|
|
2638
2701
|
} else if (command === "sc") {
|
|
2639
2702
|
runRoot(args.slice(1));
|
|
2640
2703
|
} else if (["plan", "knowledge", "rules", "review", "config"].includes(command)) {
|
|
2641
2704
|
runRoot(args);
|
|
2705
|
+
} else if (command === "action") {
|
|
2706
|
+
const { executeAction, listActions } = require(path.join(root, "lib", "actions"));
|
|
2707
|
+
try {
|
|
2708
|
+
const name = args[1];
|
|
2709
|
+
if (!name || name === "--list") {
|
|
2710
|
+
console.log("Available actions:");
|
|
2711
|
+
for (const item of listActions()) console.log(` ${item.name.padEnd(30)} ${item.describe}`);
|
|
2712
|
+
process.exit(0);
|
|
2713
|
+
}
|
|
2714
|
+
const rest = args.slice(2);
|
|
2715
|
+
let payload = {};
|
|
2716
|
+
const payloadFlag = rest.indexOf("--payload");
|
|
2717
|
+
const fileFlag = rest.indexOf("--file");
|
|
2718
|
+
if (payloadFlag !== -1) {
|
|
2719
|
+
payload = JSON.parse(rest[payloadFlag + 1] || "{}");
|
|
2720
|
+
} else if (fileFlag !== -1) {
|
|
2721
|
+
payload = JSON.parse(fs.readFileSync(rest[fileFlag + 1], "utf8"));
|
|
2722
|
+
} else if (rest.includes("--stdin")) {
|
|
2723
|
+
payload = JSON.parse(fs.readFileSync(0, "utf8"));
|
|
2724
|
+
}
|
|
2725
|
+
const result = executeAction(name, process.cwd(), payload);
|
|
2726
|
+
console.log(JSON.stringify(result, null, 2));
|
|
2727
|
+
} catch (error) {
|
|
2728
|
+
console.error(`action failed: ${error.message}`);
|
|
2729
|
+
process.exitCode = 1;
|
|
2730
|
+
}
|
|
2642
2731
|
} else if (COMMAND_ALIASES[command]) {
|
|
2643
2732
|
runCompatibilityAlias(command, args.slice(1));
|
|
2644
2733
|
} else if (command === "init") {
|
package/docs/COMMANDS.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ScrumRun
|
|
1
|
+
# ScrumRun 4.0 Command Reference
|
|
2
2
|
|
|
3
3
|
The canonical grammar is:
|
|
4
4
|
|
|
@@ -27,13 +27,13 @@ scrumrun plan run --satisfy-guardrail RUN-NNN --guardrail GR-NNN [typed evidence
|
|
|
27
27
|
scrumrun plan challenge <question>
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
Normal execution is Markdown-first: after approval, work in code and the relevant Task Markdown, then record
|
|
30
|
+
Normal execution is Markdown-first: after approval, work in code and the relevant Task Markdown through discover → implement → verify → fix → verify, then record `## Completion` and any genuinely out-of-scope Follow-ups directly. A Run/`--finalize` checkpoint is optional strict audit, never a prerequisite. Mutation permits are available only for explicitly requested strict mode.
|
|
31
31
|
|
|
32
32
|
The CLI refuses Task start/retry and all Run state changes unless `--strict` is present. This prevents an agent from accidentally manufacturing a failed/blocked retry during normal work; `--strict` is for an owner-requested audit only.
|
|
33
33
|
|
|
34
34
|
`--amend` is an optional structured helper. The Markdown-first workflow may adjust Task/Feature/Sprint content directly, preserving a useful handoff. Use the CLI when atomic relation synchronization or machine audit is valuable; do not let status vocabulary or missing relations stop approved work.
|
|
35
35
|
|
|
36
|
-
Every new Task starts with
|
|
36
|
+
Every new Task starts with `## Done when` and `## Validation Scope`: only checks explicitly required by the owner, Done when contract, or an active Guardrail block completion. A discovered in-scope gap remains work to implement, not a status report or Follow-up. Missing optional E2E, integration, or review coverage belongs in a follow-up/risk note; it must not be used to mark the Run failed.
|
|
37
37
|
|
|
38
38
|
## What can be changed
|
|
39
39
|
|
|
@@ -69,28 +69,38 @@ Creation options include `--title`, `--content`, repeated `--evidence`, repeated
|
|
|
69
69
|
scrumrun rules guardrail --add|--list|--show|--retire
|
|
70
70
|
scrumrun rules reviewer --add|--list|--show|--run
|
|
71
71
|
scrumrun review code --run
|
|
72
|
-
scrumrun review artifact --run
|
|
72
|
+
scrumrun review artifact --run [--staged]
|
|
73
73
|
scrumrun review artifact --record --task TASK-NNN [--run RUN-NNN] [--title "..."] [--evidence "..."]
|
|
74
74
|
scrumrun review migration --run
|
|
75
75
|
scrumrun review release --run
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
`review artifact --run` is read-only and returns a machine-readable
|
|
78
|
+
`review artifact --run` is read-only and returns a machine-readable project audit, including declarative Guardrail matches against the current Git worktree. `--staged` evaluates the Git index, for the optional pre-commit hook. `--record` reruns that audit and persists its exact pass/fail result as a canonical `REV-NNN`; supplied evidence is additive and cannot turn a failed audit into a pass. Other review routes require repository reasoning and remain read-only unless fixes receive separate approval.
|
|
79
|
+
|
|
80
|
+
To install the optional offline hook locally:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
cp node_modules/scrumrun/templates/shared/hooks/pre-commit .git/hooks/pre-commit
|
|
84
|
+
chmod +x .git/hooks/pre-commit
|
|
85
|
+
```
|
|
79
86
|
|
|
80
87
|
## Config and lifecycle
|
|
81
88
|
|
|
82
89
|
```text
|
|
83
90
|
scrumrun config project --show|--language|--interaction|--approval|--quick-tasks
|
|
84
91
|
scrumrun config init --local|--shared|--lean|--no-agent-hint|--force
|
|
85
|
-
scrumrun config update [all|codex|opencode|claude] [--project] [--migrate]
|
|
92
|
+
scrumrun config update [all|codex|opencode|claude] [--project] [--seal-policy] [--migrate]
|
|
86
93
|
scrumrun config migrate --to 2 --dry-run|--apply|--rollback
|
|
87
94
|
scrumrun config doctor [all|codex|opencode|claude] [--strict] [--recover]
|
|
95
|
+
scrumrun config watch --start|--stop|--status
|
|
88
96
|
scrumrun config uninstall --force
|
|
89
97
|
scrumrun config help <topic>
|
|
90
98
|
```
|
|
91
99
|
|
|
92
|
-
Top-level CLI aliases (`init`, `update`, `migrate`, `doctor`, `uninstall`, `status`) remain available for shell automation. `update --project` refreshes the packaged
|
|
100
|
+
Top-level CLI aliases (`init`, `update`, `migrate`, `doctor`, `uninstall`, `status`) remain available for shell automation. `update --project` refreshes the packaged execution-first Core and recognized generated agent instructions with local backup. `update --project --seal-policy` is the owner-reviewed maintenance action that pins fresh Core/Guardrail fingerprints. Ordinary update does not inspect migrations, while `--migrate` explicitly does so and applies the verified plan.
|
|
93
101
|
|
|
94
102
|
Run transitions accept typed evidence through `--command`, `--test`, `--file`, `--review`, `--decision`, `--insight`, `--risk`, or generic `--evidence kind:value`. `doctor --recover` is an explicit write that resolves only safe pending kernel transactions; doctor without it remains read-only.
|
|
95
103
|
|
|
96
104
|
Run `scrumrun commands` for grammar rendered directly from the current manifest.
|
|
105
|
+
|
|
106
|
+
`watch` is an optional convenience, never a gate or authority. Set `watcher.enabled: true` in `.scrumrun/config.md`, then use `--start`. It records its liveness PID at `.scrumrun/.cache/watcher.pid`; `--stop` shuts that daemon down. Native recursive `fs.watch` is used where supported; otherwise the daemon falls back to portable polling. It ignores `vault.local.md`, `.cache/contexts/`, its own generated outputs, and writes only generated `state.md`, `map.md`, and `.cache/semantic-index.sqlite`.
|