runward 0.13.0 → 0.13.1

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.
@@ -3,7 +3,8 @@ import { join, resolve } from "node:path";
3
3
  import { analyze, findMissionRoot } from "../lib/mission.js";
4
4
  import { c, createHeader, section } from "../lib/styles.js";
5
5
  import { VERSION, WORKFLOWS } from "../lib/paths.js";
6
- /** Mission snapshot: phase, ADR journal, framing summary, workflow presence. */
6
+ /** Mission snapshot: phase progress, decision journal, activity, workflows
7
+ * a transmission-ready "where the mission stands", read-only from the mission files. */
7
8
  export async function statusCommand(opts) {
8
9
  const root = findMissionRoot(resolve(process.cwd(), opts.path ?? "."));
9
10
  if (!root) {
@@ -13,7 +14,7 @@ export async function statusCommand(opts) {
13
14
  const mission = join(root, "runward");
14
15
  const report = analyze(mission);
15
16
  console.log(createHeader(`Runward v${VERSION} — mission status`, root));
16
- // Framing summary: first line of Problem + success criterion heading state
17
+ // Mission title + current gate
17
18
  console.log(section("Mission"));
18
19
  const framingPath = join(mission, "framing.md");
19
20
  if (existsSync(framingPath)) {
@@ -21,6 +22,25 @@ export async function statusCommand(opts) {
21
22
  console.log(` ${c.white(title)}`);
22
23
  }
23
24
  console.log(` ${c.primaryBold("Current gate")} ${c.white(report.currentPhase)}`);
25
+ // Phase progress across the gated arc — where the mission stands, gate by gate
26
+ console.log(section("Phase progress"));
27
+ const currentIndex = report.phases.findIndex((p) => !p.complete);
28
+ report.phases.forEach((p, i) => {
29
+ const filled = p.artifacts.filter((a) => a.state === "filled").length;
30
+ const total = p.artifacts.length;
31
+ const isCurrent = i === currentIndex;
32
+ const mark = p.complete ? c.success("✓") : isCurrent ? c.primary("▸") : c.darkGray("○");
33
+ const label = p.complete ? c.white(p.spec.label) : isCurrent ? c.primaryBold(p.spec.label) : c.gray(p.spec.label);
34
+ const count = p.complete ? c.darkGray(`${filled}/${total}`) : c.white(`${filled}/${total}`);
35
+ console.log(` ${mark} ${label} ${count}${isCurrent ? c.primary(" ← you are here") : ""}`);
36
+ // Under the current phase, name exactly what is still open.
37
+ if (isCurrent) {
38
+ for (const a of p.artifacts.filter((a) => a.state !== "filled")) {
39
+ console.log(` ${c.darkGray("○")} ${c.gray(a.artifact.label)} ${c.darkGray(`(${a.state})`)}`);
40
+ }
41
+ }
42
+ });
43
+ // Decision journal — the ADRs, dated
24
44
  console.log(section("Decision journal"));
25
45
  const adrDir = join(mission, "adr");
26
46
  const adrs = existsSync(adrDir)
@@ -38,12 +58,44 @@ export async function statusCommand(opts) {
38
58
  }
39
59
  if (adrs.length > 5)
40
60
  console.log(c.darkGray(` … and ${adrs.length - 5} more`));
61
+ console.log(c.darkGray(` ${adrs.length} decision(s) traced`));
62
+ }
63
+ // Activity — the most recently touched deliverable, so a receiving team sees the last movement
64
+ console.log(section("Activity"));
65
+ let latest = null;
66
+ for (const p of report.phases) {
67
+ for (const a of p.artifacts) {
68
+ const abs = join(mission, a.artifact.relPath);
69
+ if (!existsSync(abs))
70
+ continue;
71
+ const st = statSync(abs);
72
+ if (!st.isFile())
73
+ continue;
74
+ const date = st.mtime.toISOString().slice(0, 10);
75
+ if (!latest || date > latest.date)
76
+ latest = { date, label: a.artifact.label };
77
+ }
41
78
  }
79
+ if (latest)
80
+ console.log(` ${c.primaryBold("Last touched")} ${c.white(latest.date)} ${c.darkGray(latest.label)}`);
81
+ else
82
+ console.log(c.darkGray(" no deliverable written yet"));
83
+ // Workflows
42
84
  console.log(section("Workflows"));
43
85
  const missing = WORKFLOWS.filter((wf) => !existsSync(join(mission, "workflows", `${wf}.md`)));
44
86
  if (missing.length === 0)
45
87
  console.log(c.success(" ✓ ") + c.white(`all ${WORKFLOWS.length} workflows present`));
46
88
  else
47
89
  console.log(c.warning(" ! ") + c.white(`missing: ${missing.join(", ")} — run \`runward update\``));
90
+ // Next — the transmission surface: name the next gesture, never leave the reader guessing
91
+ console.log(section("Next"));
92
+ if (currentIndex === -1) {
93
+ console.log(` All gated deliverables are filled. Run ${c.primary("runward check --strict")} to confirm on evidence, then ${c.primary("runward compliance <regime>")} for the evidence pack.`);
94
+ }
95
+ else {
96
+ const cur = report.phases[currentIndex];
97
+ const open = cur.artifacts.filter((a) => a.state !== "filled").length;
98
+ console.log(` Fill the ${open} open deliverable(s) in ${c.white(cur.spec.label)}, then run ${c.primary("runward check")} to cross the gate on evidence.`);
99
+ }
48
100
  console.log();
49
101
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runward",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "After the spec: ship and run. A delivery framework for agentic systems — floor first, evolution on evidence, governance from day zero, handover with proof.",
5
5
  "keywords": [
6
6
  "agentic",
@@ -17,6 +17,7 @@ This project is delivered with the Runward method: floor first, evolution on evi
17
17
  - Before any structural decision, run `runward/workflows/decision-loop.md`: verify in the real code, check the sourced state of the art, challenge the source, take a durable position, lock it in an ADR — only then edit.
18
18
  - One ADR per structural decision, in `runward/adr/`, with a dated re-evaluation trigger. Use the template `runward/adr/ADR-0000-template.md`.
19
19
  - Current phase and gates: see `runward/framing.md` (Definition of Ready) and each workflow's Definition of Done. Do not skip a gate on assertion; pass it on evidence.
20
+ - Offer to wire the gate at your harness's lifecycle seam — git `pre-commit`, a CI required check, or a turn-end hook — from the inert samples in `runward/adapters/` (its README has the exact command). Propose it to the operator and act only on their explicit approval; never wire it silently. runward installs nothing itself (ADR-0012): you are the operator's hands, and the operator owns the gate.
20
21
  - Show before you build: for any deliverable meant for humans, produce a reviewable preview first.
21
22
  - Never mark a phase done if its Definition of Done is not demonstrably met.
22
23