runward 0.6.0 → 0.7.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.
Files changed (30) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +1 -0
  3. package/dist/commands/check.js +38 -2
  4. package/dist/lib/conformance.js +88 -0
  5. package/package.json +1 -1
  6. package/templates/mission/architecture.md +8 -0
  7. package/templates/mission/floor.md +8 -0
  8. package/templates/mission/threat-model.md +8 -0
  9. package/templates/rules/async-job-guardrails.md +1 -0
  10. package/templates/rules/config-secrets-boundary.md +1 -0
  11. package/templates/rules/contracts-governance.md +1 -0
  12. package/templates/rules/eval-loop.md +1 -0
  13. package/templates/rules/frontier-deterministic-boundary.md +1 -0
  14. package/templates/rules/hexa-adapter-pattern.md +1 -0
  15. package/templates/rules/hexa-architecture.md +1 -0
  16. package/templates/rules/hexa-move-deterministic-out.md +1 -0
  17. package/templates/rules/hexa-typescript-native.md +1 -0
  18. package/templates/rules/process-adr-and-journal.md +1 -0
  19. package/templates/rules/provider-llm-auto-detection.md +1 -0
  20. package/templates/rules/provider-no-crash-missing-env.md +1 -0
  21. package/templates/rules/resilience-fail-open.md +1 -0
  22. package/templates/rules/resilience-multi-provider-fallback.md +1 -0
  23. package/templates/rules/resilience-retry-backoff.md +1 -0
  24. package/templates/rules/security-prompt-injection.md +1 -0
  25. package/templates/rules/state-event-sourcing.md +1 -0
  26. package/templates/rules/tools-scope-atomicity.md +1 -0
  27. package/templates/targets/AGENTS.md +1 -1
  28. package/templates/workflows/architect.md +3 -0
  29. package/templates/workflows/floor.md +3 -0
  30. package/templates/workflows/govern.md +3 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Runward
2
2
 
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-0a0a0a?style=for-the-badge)](LICENSE) [![Doctrine: CC BY-ND 4.0](https://img.shields.io/badge/Doctrine-CC%20BY--ND%204.0-C9A45C?style=for-the-badge)](https://github.com/stranxik/designing-and-running-agentic-systems) [![Support via Ko-fi](https://img.shields.io/badge/%E2%98%95%20Support%20via%20Ko--fi-orange?style=for-the-badge)](https://ko-fi.com/stranxik)
3
+ [![npm](https://img.shields.io/npm/v/runward?style=for-the-badge&color=0a0a0a&label=npm)](https://www.npmjs.com/package/runward) [![License: MIT](https://img.shields.io/badge/License-MIT-0a0a0a?style=for-the-badge)](LICENSE) [![Doctrine: CC BY-ND 4.0](https://img.shields.io/badge/Doctrine-CC%20BY--ND%204.0-C9A45C?style=for-the-badge)](https://github.com/stranxik/designing-and-running-agentic-systems) [![Support via Ko-fi](https://img.shields.io/badge/%E2%98%95%20Support%20via%20Ko--fi-orange?style=for-the-badge)](https://ko-fi.com/stranxik)
4
4
 
5
5
  **From business need to a system that holds in production.**
6
6
 
package/dist/cli.js CHANGED
@@ -57,6 +57,7 @@ program
57
57
  .command("check")
58
58
  .description("can I cross the gate — gate audit, exit 1 on gaps (CI-friendly)")
59
59
  .option("-p, --path <path>", "project directory")
60
+ .option("--strict", "also verify the floor rule-conformance manifest (deterministic)")
60
61
  .action(checkCommand);
61
62
  program
62
63
  .command("status")
@@ -1,10 +1,15 @@
1
1
  import { join } from "node:path";
2
2
  import { analyze, findMissionRoot } from "../lib/mission.js";
3
+ import { conformance } from "../lib/conformance.js";
3
4
  import { c, createHeader, section, status } from "../lib/styles.js";
4
5
  import { VERSION } from "../lib/paths.js";
5
6
  /**
6
7
  * Gate audit — the gap analysis: which deliverable, expected at which
7
8
  * phase, is present, started, or still a raw template.
9
+ * With --strict, also verifies the floor rule-conformance manifest (see
10
+ * docs/adr/ADR-0001): every CRITICAL/HIGH rule mapped to the floor phase must be
11
+ * accounted for. It checks the presence of a traced decision, never the quality
12
+ * of the implementation — that stays the operator's judgment at the gate.
8
13
  * Exit codes: 0 = current gate clean, 1 = gaps, 2 = no mission found.
9
14
  */
10
15
  export async function checkCommand(opts) {
@@ -37,14 +42,45 @@ export async function checkCommand(opts) {
37
42
  gaps++;
38
43
  }
39
44
  }
45
+ let strictGaps = 0;
46
+ if (opts.strict) {
47
+ const CONFORMANCE = [
48
+ { phase: "architect", deliverable: "architecture.md", label: "Architect" },
49
+ { phase: "floor", deliverable: "floor.md", label: "Floor" },
50
+ { phase: "govern", deliverable: "governance/threat-model.md", label: "Govern" },
51
+ ];
52
+ console.log(section("Rule conformance (--strict)"));
53
+ let checked = 0;
54
+ for (const { phase, deliverable, label } of CONFORMANCE) {
55
+ const { expected, violations } = conformance(mission, phase, deliverable);
56
+ if (expected.length === 0)
57
+ continue;
58
+ checked++;
59
+ if (violations.length === 0) {
60
+ console.log(` ${status.success(`${label}: ${expected.length} rule(s) accounted for`)}`);
61
+ }
62
+ else {
63
+ for (const v of violations)
64
+ console.log(` ${c.error("✗")} ${c.darkGray(label + " · ")}${c.white(v.rule)}${c.darkGray(" — " + v.problem)}`);
65
+ strictGaps += violations.length;
66
+ }
67
+ }
68
+ if (checked === 0)
69
+ console.log(" " + c.darkGray("no CRITICAL/HIGH rules mapped to a build phase"));
70
+ }
40
71
  console.log(section("Summary"));
41
72
  console.log(` ${c.primaryBold("Current gate")} ${c.white(report.currentPhase)}`);
42
73
  console.log(` ${c.primaryBold("ADRs")} ${c.white(String(report.adrCount))}${report.adrCount === 0 ? c.warning(" — no structural decision locked yet") : ""}`);
43
- if (gaps === 0) {
74
+ if (gaps === 0 && strictGaps === 0) {
44
75
  console.log("\n" + status.success("All expected deliverables are filled. Cross gates on evidence, not on paperwork."));
45
76
  }
46
77
  else {
47
- console.log("\n" + status.warning(`${gaps} deliverable(s) not filled. The gate rule: no phase closes without its artifact.`));
78
+ const parts = [];
79
+ if (gaps)
80
+ parts.push(`${gaps} deliverable(s) not filled`);
81
+ if (strictGaps)
82
+ parts.push(`${strictGaps} floor rule-conformance gap(s)`);
83
+ console.log("\n" + status.warning(`${parts.join(" · ")}. No phase closes without its artifact — and, under --strict, without its CRITICAL/HIGH rules accounted for.`));
48
84
  process.exitCode = 1;
49
85
  }
50
86
  }
@@ -0,0 +1,88 @@
1
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { TEMPLATES } from "./paths.js";
4
+ const FRONTMATTER = /^---\n([\s\S]*?)\n---/;
5
+ const VALID_STATUS = new Set(["applied", "deviated", "n/a"]);
6
+ function parseRuleMeta(content) {
7
+ const fm = content.match(FRONTMATTER)?.[1] ?? "";
8
+ const impact = (fm.match(/^impact:\s*(.+)$/m)?.[1] ?? "").trim();
9
+ const phasesRaw = fm.match(/^phases:\s*\[(.*)\]/m)?.[1] ?? "";
10
+ const phases = phasesRaw.split(",").map((s) => s.trim()).filter(Boolean);
11
+ return { impact, phases };
12
+ }
13
+ /** CRITICAL/HIGH rules mapped to a phase — the set that must be accounted for.
14
+ * The mapping is a property of the rule definitions: read the mission's own
15
+ * `runward/rules/` when present, else fall back to the package rules (the
16
+ * authoritative source — covers missions predating rules-in-mission). */
17
+ export function expectedRules(missionDir, phaseId) {
18
+ const missionRules = join(missionDir, "rules");
19
+ const dir = existsSync(missionRules) ? missionRules : join(TEMPLATES, "rules");
20
+ if (!existsSync(dir))
21
+ return [];
22
+ return readdirSync(dir)
23
+ .filter((f) => f.endsWith(".md"))
24
+ .filter((f) => {
25
+ const { impact, phases } = parseRuleMeta(readFileSync(join(dir, f), "utf8"));
26
+ return (impact === "CRITICAL" || impact === "HIGH") && phases.includes(phaseId);
27
+ })
28
+ .map((f) => f.replace(/\.md$/, ""))
29
+ .sort();
30
+ }
31
+ /** Parse the "## Rule conformance" markdown table from a deliverable. */
32
+ export function parseManifest(content) {
33
+ const lines = content.split("\n");
34
+ const start = lines.findIndex((l) => /^##\s+Rule conformance/i.test(l));
35
+ if (start === -1)
36
+ return [];
37
+ const rows = [];
38
+ for (let i = start + 1; i < lines.length; i++) {
39
+ const line = lines[i];
40
+ if (/^##\s/.test(line))
41
+ break; // next section
42
+ if (!line.trim().startsWith("|"))
43
+ continue;
44
+ const cols = line.split("|").slice(1, -1).map((c) => c.replace(/`/g, "").trim());
45
+ if (cols.length < 3)
46
+ continue;
47
+ const [rule, status, evidence] = cols;
48
+ if (/^rule$/i.test(rule) || /^:?-+:?$/.test(rule))
49
+ continue; // header / separator
50
+ rows.push({ rule, status: status.toLowerCase(), evidence });
51
+ }
52
+ return rows;
53
+ }
54
+ function adrExists(missionDir, evidence) {
55
+ const id = evidence.match(/ADR-\d+/i)?.[0].toUpperCase();
56
+ if (!id)
57
+ return false;
58
+ const dir = join(missionDir, "adr");
59
+ return existsSync(dir) && readdirSync(dir).some((f) => f.toUpperCase().startsWith(id));
60
+ }
61
+ /** Verify a build phase's conformance manifest against its expected rule set. */
62
+ export function conformance(missionDir, phaseId, deliverable) {
63
+ const expected = expectedRules(missionDir, phaseId);
64
+ const violations = [];
65
+ const path = join(missionDir, deliverable);
66
+ if (!existsSync(path)) {
67
+ return { expected, violations: expected.map((rule) => ({ rule, problem: `${deliverable} missing` })) };
68
+ }
69
+ const byRule = new Map(parseManifest(readFileSync(path, "utf8")).map((r) => [r.rule, r]));
70
+ for (const rule of expected) {
71
+ const row = byRule.get(rule);
72
+ if (!row) {
73
+ violations.push({ rule, problem: "not accounted for in the Rule conformance manifest" });
74
+ continue;
75
+ }
76
+ if (!VALID_STATUS.has(row.status)) {
77
+ violations.push({ rule, problem: `invalid status "${row.status}" (use applied | deviated | n/a)` });
78
+ continue;
79
+ }
80
+ if (row.status === "applied" && !row.evidence)
81
+ violations.push({ rule, problem: "applied without an evidence pointer" });
82
+ if (row.status === "deviated" && !adrExists(missionDir, row.evidence))
83
+ violations.push({ rule, problem: "deviated but no matching ADR in runward/adr/" });
84
+ if (row.status === "n/a" && !row.evidence)
85
+ violations.push({ rule, problem: "n/a without a reason" });
86
+ }
87
+ return { expected, violations };
88
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runward",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
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": ["agentic", "ai-agents", "spec-driven", "delivery", "governance", "llm", "architecture"],
6
6
  "author": "Thibault Souris",
@@ -37,6 +37,14 @@
37
37
  | Tool registry + middleware chain | [single transversal surface, thin channel] | [—] |
38
38
  | One core language, thin model SDK | [no heavy chain framework] | [mature library or proven performance need → sidecar] |
39
39
 
40
+ ## Rule conformance
41
+
42
+ > Account for every CRITICAL/HIGH craft rule mapped to the architect phase (`runward/rules/`, frontmatter `phases: [architect]`). `applied` needs a pointer; `deviated` needs an ADR; `n/a` needs a reason. `runward check --strict` verifies this table is complete — it checks a traced decision, not the quality of your architecture.
43
+
44
+ | Rule | Status | Evidence |
45
+ |---|---|---|
46
+ | [rule-slug] | applied \| deviated \| n/a | [pointer, ADR-id, or reason] |
47
+
40
48
  ## 5. What stays open
41
49
 
42
50
  [Explicitly undecided: language(s), framework, model provider, hosting. Each is an adapter decision, taken later behind the contracts above, justified by a local technical reason.]
@@ -17,6 +17,14 @@
17
17
  | Deterministic guardrails | [shipped] | [classification, validation, mutation access control] |
18
18
  | Baseline observability + cost ceiling | [shipped] | [request ID propagated; per-run ceiling: [value]] |
19
19
 
20
+ ## Rule conformance
21
+
22
+ > Account for every CRITICAL/HIGH craft rule mapped to the floor phase (`runward/rules/`, frontmatter `phases: [floor]`). Status: `applied` needs an evidence pointer (a `file:line` or a test); `deviated` needs an ADR reference; `n/a` needs a one-line reason. `runward check --strict` verifies this table is complete and well-formed — it does not judge your implementation; you do, at the gate.
23
+
24
+ | Rule | Status | Evidence |
25
+ |---|---|---|
26
+ | [rule-slug] | applied \| deviated \| n/a | [file:line, a test, ADR-id, or a reason] |
27
+
20
28
  ## 2. Proof against the success criterion
21
29
 
22
30
  [The measurement, on real traffic or a representative sample — never on cases picked to impress.]
@@ -48,6 +48,14 @@
48
48
 
49
49
  **Reminder**: the approval summary is itself an attack surface. It must be deterministic and faithful to the real arguments, or an injected action slips through in the batch. Group low-urgency requests into a prioritized queue with summaries, so approvers are not trained to rubber-stamp.
50
50
 
51
+ ## Rule conformance
52
+
53
+ > Account for every CRITICAL/HIGH craft rule mapped to the govern phase (`runward/rules/`, frontmatter `phases: [govern]`). `applied` needs a pointer; `deviated` needs an ADR; `n/a` needs a reason. `runward check --strict` verifies this table is complete — it checks a traced decision, not the quality of your governance.
54
+
55
+ | Rule | Status | Evidence |
56
+ |---|---|---|
57
+ | [rule-slug] | applied \| deviated \| n/a | [pointer, ADR-id, or reason] |
58
+
51
59
  ## References
52
60
 
53
61
  - [Related hardening ADR, observability schema, evaluation rubric.]
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Background Job Guardrails (Retry, Idempotency, Bounded Concurrency, Job Observability)
3
3
  impact: HIGH
4
+ phases: [govern]
4
5
  impactDescription: The four non-negotiables of any background job — bounded retry per step, idempotency under concurrency, capped and partitioned concurrency, and queue lag plus failure rate as first-class metrics
5
6
  tags: [async, jobs, idempotency, concurrency, retry, observability]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Secrets at the Network Boundary, Never in the Model
3
3
  impact: CRITICAL
4
+ phases: [floor, govern]
4
5
  impactDescription: Makes secret disclosure structurally impossible by keeping the real key out of the model and the domain
5
6
  tags: [security, secrets, configuration, boundary]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Contract Governance (Versioned, Additive, Expand-then-Contract)
3
3
  impact: CRITICAL
4
+ phases: [architect]
4
5
  impactDescription: Lets the system evolve without breaking consumers, by governing the contract at the boundary rather than the implementation behind it
5
6
  tags: [architecture, contracts, ports, versioning, compatibility]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Evaluation Loop (Test + Evaluate, Hold-out, Anchored Judge)
3
3
  impact: CRITICAL
4
+ phases: [govern]
4
5
  impactDescription: Gives a non-deterministic system a trustworthy way to detect behavioural regressions without letting it optimise its own grader
5
6
  tags: [evaluation, testing, llm, quality, governance]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Deterministic Boundary of the Model
3
3
  impact: CRITICAL
4
+ phases: [floor]
4
5
  impactDescription: Keeps every fact, figure and decision that can be checked out of the model, so the system is verifiable and cannot hallucinate load-bearing values
5
6
  tags: [architecture, llm, frontier, grounding, safety, determinism]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: New Feature = New Adapter
3
3
  impact: HIGH
4
+ phases: [architect, floor]
4
5
  impactDescription: Keeps core business logic clean and external integrations isolated
5
6
  tags: [architecture, hexagonal, adapters, integration]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Hexagonal Architecture Structure
3
3
  impact: HIGH
4
+ phases: [architect, floor]
4
5
  impactDescription: Enables testability, maintainability, and clean dependency management
5
6
  tags: [architecture, hexagonal, structure, testing]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Move the Deterministic out of the Model
3
3
  impact: CRITICAL
4
+ phases: [floor]
4
5
  impactDescription: Reduces LLM costs and latency by moving deterministic logic out of LLM calls
5
6
  tags: [architecture, llm, cost-optimization, performance]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: A Thin Model Abstraction You Own (Not a Heavy Chain Framework)
3
3
  impact: HIGH
4
+ phases: [architect]
4
5
  impactDescription: Reduces token overhead, improves debuggability, removes volatile dependencies by keeping a light abstraction you control instead of a heavy framework
5
6
  tags: [architecture, typescript, llm, frameworks]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: ADR Discipline and Working Journal
3
3
  impact: HIGH
4
+ phases: [architect]
4
5
  impactDescription: Makes structural decisions traceable and reversible-by-record, so the system can be picked up by anyone without re-litigating settled choices
5
6
  tags: [process, adr, journal, traceability, governance]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Model Provider as an Adapter (Detected, Never Hardcoded)
3
3
  impact: CRITICAL
4
+ phases: [floor]
4
5
  impactDescription: Keeps the model behind a port so the provider can change by configuration without touching the core
5
6
  tags: [provider, llm, embeddings, ports, configuration, portability]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Graceful Degradation of Optional Services
3
3
  impact: HIGH
4
+ phases: [floor]
4
5
  impactDescription: Lets the app start and run wherever it is deployed, enabling features by available config rather than crashing on a missing variable
5
6
  tags: [provider, configuration, resilience, deployment]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Fail-Open for the Non-Critical, Fail-Closed for the Sensitive
3
3
  impact: CRITICAL
4
+ phases: [govern]
4
5
  impactDescription: Degrades gracefully where safe and denies safely where it matters, instead of applying one failure policy everywhere
5
6
  tags: [resilience, error-handling, availability, safety]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Multi-Provider Fallback
3
3
  impact: HIGH
4
+ phases: [govern]
4
5
  impactDescription: Ensures LLM availability by falling back to alternative providers
5
6
  tags: [resilience, llm, providers, availability]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: LLM Retry with Exponential Backoff
3
3
  impact: HIGH
4
+ phases: [govern]
4
5
  impactDescription: Handles transient LLM failures gracefully without overwhelming the API
5
6
  tags: [resilience, llm, retry, error-handling]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Untrusted Input, Prompt Injection and the Lethal Trifecta
3
3
  impact: CRITICAL
4
+ phases: [floor, govern]
4
5
  impactDescription: Treats prompt injection as a first-rank, structural threat constrained by architecture rather than detected by heuristics
5
6
  tags: [security, llm, injection, trifecta, untrusted-input]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: State as an Immutable Journal (Event Sourcing, Replay, Provenance)
3
3
  impact: HIGH
4
+ phases: [floor]
4
5
  impactDescription: Makes the agent a stateless reducer over an external, replayable journal, so truth, audit and recovery are structural rather than bolted on
5
6
  tags: [state, event-sourcing, replay, provenance, memory]
6
7
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Tool Scope and Atomicity
3
3
  impact: HIGH
4
+ phases: [floor]
4
5
  impactDescription: Reduces token usage and improves LLM tool selection accuracy
5
6
  tags: [tools, llm, architecture, cost-optimization]
6
7
  ---
@@ -12,7 +12,7 @@ This project is delivered with the Runward method: floor first, evolution on evi
12
12
 
13
13
  ## How to work
14
14
 
15
- - Apply the craft rules in `runward/rules/` while building: they cover memory scoring, tiered retrieval, event sourcing, request-id propagation, resilience, cost routing, secrets and prompt-injection defenses. When a rule and a habit conflict, the rule wins; deviating from a rule requires an ADR.
15
+ - Apply the craft rules in `runward/rules/` while building and confront them at the point of action, not from memory. Each rule declares where it applies (`phases:`); a build phase surfaces its CRITICAL/HIGH rules to open and account for in the deliverable's `Rule conformance` manifest: `applied` with a `file:line` or test, `deviated` with an ADR, `n/a` with a reason. When a rule and a habit conflict, the rule wins; deviating requires an ADR. `runward check --strict` verifies the manifest is complete — it checks that a decision was traced, never the quality of the code; you judge that at the gate.
16
16
  - Consult `runward/decision-matrix.md` before adding any capability: 22 arbitrations, each with a sober default and an explicit trigger. No trigger, no change.
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`.
@@ -30,6 +30,8 @@ Use this workflow once framing is decided and structure must follow: "how do we
30
30
 
31
31
  **Lock structuring choices in ADRs.** Starting topology, core language, legacy integration strategy, bounded-context boundaries: each goes through `decision-loop` — reality-check against reference implementations, sourced state of the art, challenge, durable position, written lock. A decision that is not locked does not enter the architecture note.
32
32
 
33
+ **Confront the architect craft rules at the point of deciding.** Open the CRITICAL/HIGH rules mapped to the architect phase (`runward/rules/`, `phases: [architect]`): contract governance, the hexagonal architecture and adapter pattern, the single core language, the ADR-and-journal discipline. Do not work from their names — read them. Account for each in the `Rule conformance` manifest of the architecture note: `applied` with a pointer, `deviated` with an ADR, or `n/a` with a reason. `runward check --strict` verifies that manifest.
34
+
33
35
  **Write the architecture note.** Short, readable, decided: the ports, the default topology and its triggers, what stays open (language, provider), and the target named without being built. A few pages, not a detailed design dossier.
34
36
 
35
37
  ## Definition of Done
@@ -37,6 +39,7 @@ Use this workflow once framing is decided and structure must follow: "how do we
37
39
  - Architecture note produced, boundaries first, stack open.
38
40
  - Every port named with contract and initial version; integration protocol stated.
39
41
  - One ADR per structuring choice, locked before the note mentions it.
42
+ - Every architect CRITICAL/HIGH rule accounted for in the conformance manifest (`runward check --strict`).
40
43
  - Note reviewed via `review` before circulation.
41
44
  - Deliverable form matched: the presented architecture note carries an expected delivery form (a readable PDF or HTML); ADRs and contract specs stay as repository markdown.
42
45
 
@@ -21,6 +21,8 @@ Use this workflow once the architecture is fixed and building must start: "what
21
21
 
22
22
  **Start from the reference floor, not a blank page.** The starting point is the reference floor (`floor-ts/` in the Runward repository): a clonable hexagonal scaffold that already carries the pure domain, the ports, the adapters, and the middleware chain, with a principle-to-code table mapping each principle to where it lives in the code. Clone it, implement the project's concrete adapters behind the ports fixed in `architect`, and leave intact the structure that keeps the domain testable without the model. Do not reinvent the skeleton; populate it.
23
23
 
24
+ **Confront the floor's craft rules at the point of building.** Before writing each piece, open the CRITICAL/HIGH rules mapped to the floor phase — `runward/rules/`, frontmatter `phases: [floor]`: the deterministic frontier guard, the model port and its keyless fallback, provider auto-detection, secrets boundary, prompt-injection defense, the hexagonal architecture and adapter pattern, the event-sourced journal, tool-scope atomicity. Do not work from their names — read them. Account for each in the `Rule conformance` manifest of the floor note: `applied` with a `file:line` or test, `deviated` with an ADR, or `n/a` with a reason. `runward check --strict` verifies that manifest is complete and well-formed (it checks that a decision was traced, never the quality of the code — you judge that at the gate).
25
+
24
26
  **Build exactly these six pieces, and nothing more.**
25
27
 
26
28
  1. **An entry point matched to actual use.** A minimal interface when a human operates the system (submit, review, approve, decide); an API or tool protocol when another system drives it. It is a primary adapter — plain, replaceable, never touching the domain, and never a demo showcase.
@@ -48,6 +50,7 @@ Lock any structuring decision met during the build through `decision-loop`. Writ
48
50
  - Value measured against the observable success criterion.
49
51
  - A complete trajectory replays from a single request ID.
50
52
  - Every deferral named with its trigger.
53
+ - Every floor CRITICAL/HIGH rule accounted for in the conformance manifest (`runward check --strict` clean).
51
54
  - Floor note produced and reviewed.
52
55
 
53
56
  ## Anti-patterns
@@ -35,9 +35,12 @@ The chain carries transversal concerns only — no orchestration, no business lo
35
35
 
36
36
  **Test and evaluate — both.** Build the test pyramid: unit tests without network (pure domain, mocked model adapter); consumer-driven contract tests that catch drift between schema and real data; integration through the injection container with mock adapters; behavioral evaluations at the top. Then run the continuous evaluation loop: sample the trace stream off the hot path; score hybrid — deterministic checks wherever a guarantee exists, an anchored judge model (pinned version or replayed anchor set) only for the irreducibly behavioral, abstention first. The loop is valid only under a **hold-out the optimizer never sees**; self-tuning stays inside a pre-approved, audited envelope or goes through human validation — never autonomous self-rewriting. The hard floor — safety, security, authorization, audit — stays deterministic; never assemble it from soft judgments. Promote a new model via shadow deployment: same port, real traffic, silent; measure divergence with the same evaluation; roll out in stages with instant rollback.
37
37
 
38
+ **Confront the govern craft rules.** Open the CRITICAL/HIGH rules mapped to the govern phase (`runward/rules/`, `phases: [govern]`): the evaluation loop, prompt-injection defense, the secrets boundary, fail-open/fail-closed resilience, provider fallback, retry-with-backoff, background-job guardrails. Account for each in the `Rule conformance` manifest of the threat model: `applied` with a pointer, `deviated` with an ADR, or `n/a` with a reason. `runward check --strict` verifies that manifest.
39
+
38
40
  ## Definition of Done
39
41
 
40
42
  - All transversal concerns pass through the single middleware chain; a trajectory replays from one request ID.
43
+ - Every govern CRITICAL/HIGH rule accounted for in the conformance manifest (`runward check --strict`).
41
44
  - Cost ceilings enforced with stop-and-synthesize behavior.
42
45
  - Threat model written; two-of-three trifecta rule enforced while untrusted content is in the context window.
43
46
  - Test pyramid in place; evaluation loop running with anchored judge and hold-out.