verity-framework 0.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.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/commands/verity/architect.md +58 -0
  4. package/commands/verity/build.md +61 -0
  5. package/commands/verity/docs.md +37 -0
  6. package/commands/verity/golive.md +32 -0
  7. package/commands/verity/map.md +22 -0
  8. package/commands/verity/plan.md +67 -0
  9. package/commands/verity/review.md +50 -0
  10. package/commands/verity/security.md +36 -0
  11. package/commands/verity/ship.md +67 -0
  12. package/commands/verity/sre.md +31 -0
  13. package/commands/verity/test.md +29 -0
  14. package/commands/verity/verify.md +31 -0
  15. package/commands/verity/vision.md +55 -0
  16. package/package.json +31 -0
  17. package/verity/bin/lib/adr.cjs +67 -0
  18. package/verity/bin/lib/catalog.cjs +81 -0
  19. package/verity/bin/lib/config.cjs +119 -0
  20. package/verity/bin/lib/contract.cjs +57 -0
  21. package/verity/bin/lib/core.cjs +63 -0
  22. package/verity/bin/lib/golive.cjs +49 -0
  23. package/verity/bin/lib/handoff.cjs +72 -0
  24. package/verity/bin/lib/identity.cjs +112 -0
  25. package/verity/bin/lib/install.cjs +109 -0
  26. package/verity/bin/lib/ledger.cjs +244 -0
  27. package/verity/bin/lib/map.cjs +77 -0
  28. package/verity/bin/lib/recovery.cjs +37 -0
  29. package/verity/bin/lib/release.cjs +131 -0
  30. package/verity/bin/lib/review.cjs +74 -0
  31. package/verity/bin/lib/scaffold.cjs +66 -0
  32. package/verity/bin/lib/security.cjs +44 -0
  33. package/verity/bin/lib/smoke.cjs +170 -0
  34. package/verity/bin/lib/stage.cjs +180 -0
  35. package/verity/bin/lib/status.cjs +117 -0
  36. package/verity/bin/verity.cjs +190 -0
  37. package/verity/design-guides/contracts-first.md +32 -0
  38. package/verity/design-guides/features/helper-bot.md +61 -0
  39. package/verity/design-guides/stack-and-topology.md +38 -0
  40. package/verity/templates/LICENSE.tmpl +21 -0
  41. package/verity/templates/README.md.tmpl +14 -0
  42. package/verity/templates/STATUS.md.tmpl +27 -0
  43. package/verity/templates/adr.md.tmpl +21 -0
  44. package/verity/templates/bug_report.yml.tmpl +44 -0
  45. package/verity/templates/ci.yml.tmpl +36 -0
  46. package/verity/templates/contract.md.tmpl +21 -0
  47. package/verity/templates/gitignore.tmpl +9 -0
  48. package/verity/templates/handoff-brief.md.tmpl +32 -0
  49. package/verity/templates/handoff-readme.md.tmpl +21 -0
  50. package/verity/templates/recovery-plan.md.tmpl +29 -0
  51. package/verity/templates/security-invariants.md.tmpl +14 -0
  52. package/verity/templates/smoke.json.tmpl +21 -0
  53. package/verity/templates/stage.md.tmpl +28 -0
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ // Verity CLI dispatcher — the deterministic "notebook" layer (framework-spec.md §9).
3
+ // READ-ONLY w.r.t. integration state; performs framework-conventional acts and
4
+ // authors the few writable artifacts. JSON by default; --raw for plain values;
5
+ // --cwd to target another project directory.
6
+ const fs = require('node:fs');
7
+ const os = require('node:os');
8
+ const path = require('node:path');
9
+
10
+ const core = require('./lib/core.cjs');
11
+ const config = require('./lib/config.cjs');
12
+ const identity = require('./lib/identity.cjs');
13
+ const scaffold = require('./lib/scaffold.cjs');
14
+ const install = require('./lib/install.cjs');
15
+ const adr = require('./lib/adr.cjs');
16
+ const contract = require('./lib/contract.cjs');
17
+ const catalog = require('./lib/catalog.cjs');
18
+ const stage = require('./lib/stage.cjs');
19
+ const ledger = require('./lib/ledger.cjs');
20
+ const review = require('./lib/review.cjs');
21
+ const release = require('./lib/release.cjs');
22
+ const status = require('./lib/status.cjs');
23
+ const security = require('./lib/security.cjs');
24
+ const handoff = require('./lib/handoff.cjs');
25
+ const map = require('./lib/map.cjs');
26
+ const recovery = require('./lib/recovery.cjs');
27
+ const golive = require('./lib/golive.cjs');
28
+ const smoke = require('./lib/smoke.cjs');
29
+
30
+ function parseArgs(argv) {
31
+ const positional = [];
32
+ const flags = {};
33
+ for (let i = 0; i < argv.length; i += 1) {
34
+ const a = argv[i];
35
+ if (a === '--raw') {
36
+ flags.raw = true;
37
+ } else if (a === '--json') {
38
+ flags.json = true;
39
+ } else if (a === '--cwd') {
40
+ i += 1;
41
+ flags.cwd = argv[i];
42
+ } else if (a.startsWith('--')) {
43
+ const key = a.slice(2);
44
+ const next = argv[i + 1];
45
+ if (next !== undefined && !next.startsWith('--')) {
46
+ i += 1;
47
+ flags[key] = next;
48
+ } else {
49
+ flags[key] = true;
50
+ }
51
+ } else {
52
+ positional.push(a);
53
+ }
54
+ }
55
+ return { positional, flags };
56
+ }
57
+
58
+ function emit(result, flags) {
59
+ if (flags.raw) {
60
+ const raw = result && typeof result === 'object' && 'raw' in result ? result.raw : result;
61
+ let text = '';
62
+ if (raw === null || raw === undefined) {
63
+ text = '';
64
+ } else if (typeof raw === 'object') {
65
+ // A structured result with no scalar `raw` — emit compact JSON, never "[object Object]".
66
+ text = JSON.stringify(raw);
67
+ } else {
68
+ text = String(raw);
69
+ }
70
+ process.stdout.write(`${text}\n`);
71
+ return;
72
+ }
73
+ const json = JSON.stringify(result, null, 2);
74
+ // Large payloads spill to a tempfile (the 1.4 convention) so we never blow a
75
+ // consumer's buffer; the caller reads the @file: path.
76
+ if (json.length > 50000) {
77
+ const tmp = path.join(os.tmpdir(), `verity-${process.pid}-${Date.now()}.json`);
78
+ fs.writeFileSync(tmp, json);
79
+ process.stdout.write(`@file:${tmp}\n`);
80
+ return;
81
+ }
82
+ process.stdout.write(`${json}\n`);
83
+ }
84
+
85
+ const COMMANDS = {
86
+ slug(rest) {
87
+ const slug = core.generateSlug(rest.join(' '));
88
+ return { slug, validation: core.validateSlug(slug), raw: slug };
89
+ },
90
+ timestamp() {
91
+ const ts = new Date().toISOString();
92
+ return { timestamp: ts, raw: ts };
93
+ },
94
+ 'verify-path'(rest, flags) {
95
+ const base = flags.cwd || process.cwd();
96
+ const target = path.resolve(base, rest[0] || '');
97
+ const exists = fs.existsSync(target);
98
+ return { path: target, exists, raw: String(exists) };
99
+ },
100
+ config(rest, flags) {
101
+ return config.dispatch(rest, flags);
102
+ },
103
+ identity(rest, flags) {
104
+ return identity.dispatch(rest, flags);
105
+ },
106
+ scaffold(rest, flags) {
107
+ return scaffold.dispatch(rest, flags);
108
+ },
109
+ install(rest, flags) {
110
+ return install.dispatch(rest, flags);
111
+ },
112
+ adr(rest, flags) {
113
+ return adr.dispatch(rest, flags);
114
+ },
115
+ contract(rest, flags) {
116
+ return contract.dispatch(rest, flags);
117
+ },
118
+ guides(rest) {
119
+ return catalog.guidesDispatch(rest);
120
+ },
121
+ feature(rest) {
122
+ return catalog.featureDispatch(rest);
123
+ },
124
+ stage(rest, flags) {
125
+ return stage.dispatch(rest, flags);
126
+ },
127
+ state(rest, flags) {
128
+ return ledger.dispatch(rest, flags);
129
+ },
130
+ review(rest, flags) {
131
+ return review.dispatch(rest, flags);
132
+ },
133
+ release(rest, flags) {
134
+ return release.dispatch(rest, flags);
135
+ },
136
+ status(rest, flags) {
137
+ return status.dispatch(rest, flags);
138
+ },
139
+ security(rest, flags) {
140
+ return security.dispatch(rest, flags);
141
+ },
142
+ handoff(rest, flags) {
143
+ return handoff.dispatch(rest, flags);
144
+ },
145
+ map(rest, flags) {
146
+ return map.dispatch(rest, flags);
147
+ },
148
+ recovery(rest, flags) {
149
+ return recovery.dispatch(rest, flags);
150
+ },
151
+ golive(rest, flags) {
152
+ return golive.dispatch(rest, flags);
153
+ },
154
+ smoke(rest, flags) {
155
+ return smoke.dispatch(rest, flags);
156
+ },
157
+ };
158
+
159
+ function main() {
160
+ const { positional, flags } = parseArgs(process.argv.slice(2));
161
+ const noun = positional[0];
162
+
163
+ if (!noun || noun === 'help') {
164
+ emit(
165
+ {
166
+ commands: Object.keys(COMMANDS),
167
+ usage: 'verity <command> [args] [--raw] [--cwd <dir>]',
168
+ },
169
+ flags,
170
+ );
171
+ return;
172
+ }
173
+
174
+ const handler = COMMANDS[noun];
175
+ if (!handler) {
176
+ process.stderr.write(
177
+ `${JSON.stringify({ error: `unknown command: ${noun}`, commands: Object.keys(COMMANDS) })}\n`,
178
+ );
179
+ process.exit(1);
180
+ }
181
+
182
+ try {
183
+ emit(handler(positional.slice(1), flags), flags);
184
+ } catch (err) {
185
+ process.stderr.write(`${JSON.stringify({ error: err.message })}\n`);
186
+ process.exit(1);
187
+ }
188
+ }
189
+
190
+ main();
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Contracts-First Design
3
+ topic: architecture
4
+ applies-to: new, existing
5
+ ---
6
+
7
+ # Contracts-First Design
8
+
9
+ > A **recommendation** with one hard rule: once a contract is frozen, you do not
10
+ > break it.
11
+
12
+ ## The rule
13
+
14
+ Define the interface contracts between components (wire format, auth, schema,
15
+ envelope) **early**, freeze them at **v1**, and make every later change **additive**.
16
+ A breaking change is a *new contract*, not an edit — so consumers never shift under
17
+ each other's feet.
18
+
19
+ ## Why it carries production work
20
+
21
+ In a real multi-stage build, a frozen contract is what lets later stages — and
22
+ *other agents* — extend the system safely without re-litigating the core. Iteration
23
+ becomes "additive, contract-compatible stages" instead of risky re-architecture
24
+ against already-deployed code.
25
+
26
+ ## How to apply
27
+
28
+ - For each seam between components, run `verity contract new <name>` and fill in
29
+ Exposes / Consumes / Schema.
30
+ - Reviewer/Integrator verifies every PR against the frozen contracts.
31
+ - If a stage genuinely needs a new seam, the Intake/Planner issues a *new* contract;
32
+ the existing one is never reopened.
@@ -0,0 +1,61 @@
1
+ ---
2
+ title: In-App Help Agent
3
+ id: helper-bot
4
+ topic: feature
5
+ applies-to: new, existing
6
+ ---
7
+
8
+ # Drop-in Feature: In-App Help Agent
9
+
10
+ > Feature #1 in the catalog. An *application* feature Verity can scaffold into the
11
+ > app being built (NOT a framework agent). The Architect offers it; if accepted,
12
+ > its stages fold into the Intake/Planner's backlog.
13
+
14
+ ## What it is
15
+
16
+ A help surface inside the product: a restricted **mode of the app's own chat loop**,
17
+ isolated by a separate, read-only tool registry. It answers user questions with real
18
+ evidence, drafts GitHub issues (human-confirmed), and accretes a living FAQ.
19
+
20
+ ## Applicability / prerequisites
21
+
22
+ - The app has (or will have) a chat/LLM loop and a web UI surface.
23
+ - Structured, queryable logs (or a place to add them).
24
+ - A GitHub repo (for issue drafting) and a CI/CD pipeline (Verity provides this).
25
+
26
+ ## Architectural requirements (→ ADRs)
27
+
28
+ - Structured JSON logging the agent can read (`logs/app.log` or equivalent).
29
+ - A `?` help entry point opening an isolated help session (separate window/panel).
30
+ - A **separate, least-privilege tool registry** for help mode (security by construction).
31
+ - A baked **read-only source snapshot** (`git archive HEAD`) so the bot reasons from
32
+ the *deployed* code — freshness becomes a build property, not a maintenance chore.
33
+
34
+ ## Reusable pattern (parameterized by the app's log schema + repo)
35
+
36
+ - Help = restricted mode of the main chat loop (not a new service).
37
+ - Caller-scoped, **non-widenable** log reads (the model can't query other users).
38
+ - **Draft-then-confirm** external actions (issue filing is human-in-the-loop).
39
+ - A read/append markdown FAQ as lightweight institutional memory.
40
+
41
+ ## Stages injected — new-app recipe
42
+
43
+ 1. Structured JSON logging. 2. Architecture-doc/source-snapshot wiring. 3. Help UI
44
+ (`?` → isolated session). 4. Help-mode agent + restricted tool registry. 5. Draft
45
+ GitHub issue endpoint (auth + label + rate-limit + redact). 6. FAQ read/append + batch job.
46
+
47
+ ## Stages injected — retrofit recipe
48
+
49
+ 1. Point the agent at existing log output (add a formatter if unstructured).
50
+ 2. Write the architecture/source grounding. 3. Drop in a floating help widget at the
51
+ app-shell level. 4. Backend wiring (agent + GitHub hook + FAQ) without touching app code.
52
+
53
+ ## Conflicts / deps
54
+
55
+ - Depends on the CI/CD spine (Verity) for the source-snapshot bake at release.
56
+ - No conflicts with other catalog features.
57
+
58
+ ## Config knobs
59
+
60
+ - `HELP_ENABLED` kill-switch (default off — ship dark, enable by flag).
61
+ - FAQ recency/TTL weighting.
@@ -0,0 +1,38 @@
1
+ ---
2
+ title: Stack & Topology Selection
3
+ topic: architecture
4
+ applies-to: new, existing
5
+ ---
6
+
7
+ # Stack & Topology Selection
8
+
9
+ > A **recommendation**, not a mandate. Deviate when the project justifies it — and
10
+ > record the deviation as an ADR (`verity adr new`).
11
+
12
+ ## Default lean
13
+
14
+ - **Boring, well-supported stacks** over novel ones. The cost of a production
15
+ project is operations over years, not the first week of coding.
16
+ - **Server-rendered + progressive enhancement** before a SPA, unless the UX truly
17
+ needs a rich client. Fewer moving parts, fewer build steps, fewer ways to ship a
18
+ blank page (the "HTMX stub" class of failure).
19
+ - **Pin dependencies and commit the lockfile** from day one — non-reproducible
20
+ builds are silent drift.
21
+
22
+ ## Topology
23
+
24
+ - Start as a **modular monolith**. Split a service out only when there is a real
25
+ reason (independent scaling, a hard team/ownership boundary, a different runtime).
26
+ - Every service you add multiplies the CI build matrix, the image set, and the
27
+ deploy surface. The slug extends per-service: `ghcr.io/<owner>/<slug>-<service>`.
28
+
29
+ ## Walking skeleton first
30
+
31
+ Before feature work, prove a **thinnest end-to-end slice** that is green in CI,
32
+ deployed, and UI-smoked. Wiring the real test/deploy environment first kills the
33
+ "9 stages done before CI ever ran green" failure at the root.
34
+
35
+ ## When to deviate
36
+
37
+ If the team's expertise, an existing codebase, or a hard requirement points
38
+ elsewhere, choose it — and write the ADR capturing *guide said X, we chose Y, because Z*.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) {{year}} {{owner}}
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,14 @@
1
+ # {{name}}
2
+
3
+ {{description}}
4
+
5
+ > Scaffolded by [Verity](https://github.com/seanerama/verity-framework) — prompt to production, proven.
6
+
7
+ ## Status
8
+
9
+ See [`STATUS.md`](STATUS.md) for live runtime state (deployed version, environments).
10
+
11
+ ## Project identity
12
+
13
+ - **slug:** `{{slug}}`
14
+ - **images:** `{{image_prefix}}`
@@ -0,0 +1,27 @@
1
+ # {{name}} — Status & Handoff
2
+
3
+ > Runtime/ops truth (framework-spec §4.6). Owned by the **Release/Deploy Operator**,
4
+ > updated on every deploy. Records secret **locations** only — never values.
5
+
6
+ **As of:** not yet deployed
7
+
8
+ ## TL;DR
9
+
10
+ Scaffolded by Verity. Nothing deployed yet.
11
+
12
+ ## Live deployment
13
+
14
+ - (none)
15
+
16
+ ## Images
17
+
18
+ - prefix: `{{image_prefix}}`
19
+ - (no releases yet)
20
+
21
+ ## Secrets
22
+
23
+ - (none configured) — when set, list NAMES + on-disk LOCATIONS only, never values.
24
+
25
+ ## Coordination notes
26
+
27
+ - (none)
@@ -0,0 +1,21 @@
1
+ # {{number}}. {{title}}
2
+
3
+ - **Status:** {{status}}
4
+ - **Date:** {{date}}
5
+
6
+ ## Context
7
+
8
+ (Why is this decision needed? What forces are at play?)
9
+
10
+ ## Decision
11
+
12
+ (What did we decide?)
13
+
14
+ ## Alternatives considered
15
+
16
+ (What did the design guide recommend? What viable alternatives existed, and why did
17
+ we choose this one over them? — recommend-not-mandate, framework-spec §4.3.)
18
+
19
+ ## Consequences
20
+
21
+ (Trade-offs accepted. What does this make easier or harder later?)
@@ -0,0 +1,44 @@
1
+ name: "Bug report"
2
+ description: "A defect found during testing or use. Filed by an agent, operator, or user."
3
+ title: "[bug] "
4
+ labels: ["bug", "needs-triage"]
5
+ body:
6
+ - type: textarea
7
+ id: summary
8
+ attributes:
9
+ label: Summary
10
+ description: "One or two sentences — what's wrong."
11
+ validations:
12
+ required: true
13
+ - type: textarea
14
+ id: steps
15
+ attributes:
16
+ label: Steps to reproduce
17
+ description: "Numbered, from a known state."
18
+ validations:
19
+ required: true
20
+ - type: textarea
21
+ id: expected
22
+ attributes:
23
+ label: Expected result
24
+ validations:
25
+ required: true
26
+ - type: textarea
27
+ id: actual
28
+ attributes:
29
+ label: Actual result
30
+ description: "What happened instead. Include any error text verbatim."
31
+ validations:
32
+ required: true
33
+ - type: input
34
+ id: environment
35
+ attributes:
36
+ label: Environment
37
+ description: "URL + client, and roughly when (UTC helps)."
38
+ validations:
39
+ required: true
40
+ - type: input
41
+ id: filed_by
42
+ attributes:
43
+ label: Filed by
44
+ description: "Which machine / agent / person found this."
@@ -0,0 +1,36 @@
1
+ name: CI
2
+ # {{name}} — Verity hygiene gate (stack-agnostic).
3
+ # Honestly green on a fresh scaffold: secret-scan + a structure check, no faked
4
+ # pass. Lint and test gates are added when the Architect chooses the stack and the
5
+ # walking skeleton lands (the progressive gate — framework-spec §3).
6
+ on:
7
+ pull_request:
8
+ push:
9
+ branches: [main]
10
+ permissions:
11
+ contents: read
12
+ pull-requests: read # gitleaks lists PR commits via the API on pull_request
13
+ concurrency:
14
+ group: ci-${{ github.ref }}
15
+ cancel-in-progress: true
16
+ jobs:
17
+ structure:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - name: Required files present
22
+ run: |
23
+ for f in README.md LICENSE; do
24
+ test -f "$f" || { echo "missing required file: $f"; exit 1; }
25
+ done
26
+ echo "structure ok"
27
+ secret-scan:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 0
33
+ - name: Gitleaks
34
+ uses: gitleaks/gitleaks-action@v2
35
+ env:
36
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,21 @@
1
+ # Contract: {{name}}
2
+
3
+ - **Status:** frozen v1
4
+ - **Owner:** (which component owns this contract)
5
+
6
+ ## Exposes
7
+
8
+ (The interface this provides to others — endpoints, methods, events.)
9
+
10
+ ## Consumes
11
+
12
+ (What this needs from other components.)
13
+
14
+ ## Schema / wire
15
+
16
+ (Concrete shapes: request/response, auth/JWT, the envelope format.)
17
+
18
+ ## Versioning
19
+
20
+ Frozen at **v1**. Changes are **additive only** — a breaking change is a NEW
21
+ contract, not an edit (framework-spec §4.3). Every consumer depends on this shape.
@@ -0,0 +1,9 @@
1
+ node_modules/
2
+ dist/
3
+ *.tgz
4
+ .DS_Store
5
+ .env
6
+ .env.*
7
+ !.env.*.example
8
+ # Verity's derived state cache — never authoritative (framework-spec §5)
9
+ .verity-cache/
@@ -0,0 +1,32 @@
1
+ # Handoff — {{title}}
2
+
3
+ **For:** the agent picking up `{{slug}}`. Orient via `docs/handoff/README.md` first.
4
+
5
+ ## What we're building
6
+
7
+ (One paragraph: the feature and its boundary — what it touches, what it does not.)
8
+
9
+ ## Scope decisions already settled (do NOT re-litigate)
10
+
11
+ > The single highest-leverage section: it lets an independent worker build the RIGHT
12
+ > thing with no clarification round-trip. Be specific.
13
+
14
+ 1.
15
+ 2.
16
+ 3.
17
+
18
+ ## Build plan
19
+
20
+ 1.
21
+
22
+ ## Security checklist (the reviewer will verify against source)
23
+
24
+ See `docs/security-invariants.md`; call out anything feature-specific here.
25
+
26
+ ## Out of scope (don't build now)
27
+
28
+ -
29
+
30
+ ## Pointers
31
+
32
+ `docs/handoff/README.md` → `STATUS.md` → `docs/ARCHITECTURE.md`. Frozen contracts in `contracts/`.
@@ -0,0 +1,21 @@
1
+ # Handoff — agent quickstart
2
+
3
+ Reading order for an agent (or person) joining this project cold — this is what makes
4
+ "rejoin with zero setup" real (framework-spec §6, H5):
5
+
6
+ 1. **`STATUS.md`** — what's live right now (deployed version, environments).
7
+ 2. **`docs/ARCHITECTURE.md`** — how the system works.
8
+ 3. **The brief in this folder** for the feature you're picking up.
9
+ 4. **`verity state view`** — what's done and what's unblocked next.
10
+
11
+ ## The working loop
12
+
13
+ ```
14
+ verity stage branch <N> # branch for the stage
15
+ # implement + write tests (incl. UI-smoke if user-facing)
16
+ verity stage pr <N> --issue <M>
17
+ # CI must be all-green
18
+ /verity:review # a DIFFERENT reviewer verifies against source + merges
19
+ ```
20
+
21
+ You never merge your own work. Contracts are frozen — additive changes only.
@@ -0,0 +1,29 @@
1
+ # Recovery Plan
2
+
3
+ > Owned by the **SRE** (framework-spec §6, Role 10). Steady-state readiness — NOT the
4
+ > deploy act (that's the Release/Deploy Operator).
5
+
6
+ ## Rollback
7
+
8
+ - Re-pin the previous image digests and re-run the project's `deploy.sh`.
9
+ - Safe because migrations are **additive-only** (an image rollback never strands the schema).
10
+ - Back up the env before every deploy (`.env.bak.pre-<version>`).
11
+
12
+ ## Backup coverage (every persistent store listed — backed up OR acceptable-loss)
13
+
14
+ - [ ] Database — backed up (PITR / scheduled)
15
+ - [ ] (other volumes) — backed up, or **explicitly** marked acceptable-loss
16
+ (no silent gaps — the un-backed-up-FAQ-volume lesson)
17
+
18
+ ## Intermittent environment ("asleep vs incident")
19
+
20
+ - If health/SSH is unreachable: is the environment deallocated on a schedule? Start it
21
+ first. Only treat it as an incident once confirmed up. (This is a NORMAL state.)
22
+
23
+ ## Secret lifecycle
24
+
25
+ - [ ] Rotation schedule defined; no never-rotated/exposed credentials at go-live.
26
+
27
+ ## Incident response
28
+
29
+ - Triage → mitigate (often: an Operator rollback) → file an issue → post-incident note.
@@ -0,0 +1,14 @@
1
+ # Security Invariants
2
+
3
+ > Defined by the **Security Auditor**; ENFORCED by the **Reviewer** on every PR
4
+ > (framework-spec §6). Verify each against the ACTUAL diff/source — not the PR
5
+ > description. Edit this list as the system's threat surface grows.
6
+
7
+ - [ ] Least-privilege tool/permission registries — a mode is never offered tools it doesn't need
8
+ - [ ] Caller-scoped reads are NON-WIDENABLE (a user can only ever see their own data)
9
+ - [ ] Path / symlink confinement on any file access
10
+ - [ ] External or consequential actions are draft-then-confirm, never autonomous
11
+ - [ ] No secrets in the repo, image, or source snapshot (names/locations only)
12
+ - [ ] Migrations are additive (no destructive schema change)
13
+ - [ ] AuthN/AuthZ enforced on every new endpoint
14
+ - [ ] Inputs validated; outputs escaped (no injection / XSS)
@@ -0,0 +1,21 @@
1
+ {
2
+ "baseUrl": "http://localhost:8080",
3
+ "flows": [
4
+ {
5
+ "name": "home page loads and renders",
6
+ "steps": [
7
+ { "goto": "/" },
8
+ { "expectSelector": "body" }
9
+ ]
10
+ },
11
+ {
12
+ "name": "example: the help button actually opens help",
13
+ "steps": [
14
+ { "goto": "/" },
15
+ { "click": "#help-button" },
16
+ { "expectSelector": "#help-panel" },
17
+ { "expectText": "How can I help" }
18
+ ]
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,28 @@
1
+ # Stage {{number}}: {{title}}
2
+
3
+ - **Type:** {{type}}
4
+ - **Depends on:** {{depends_on}}
5
+
6
+ ## Objectives
7
+
8
+ (What this stage accomplishes — the smallest shippable unit of value.)
9
+
10
+ ## What to build
11
+
12
+ (Files, components, endpoints.)
13
+
14
+ ## Interface contracts
15
+
16
+ - **Exposes:** (what this provides to other stages)
17
+ - **Consumes:** (what this needs — reference frozen `contracts/`)
18
+
19
+ ## Testing requirements
20
+
21
+ (Unit / integration / contract tests. For user-facing work, author the UI-smoke asset
22
+ the Operator runs post-deploy.)
23
+
24
+ ## Acceptance conditions
25
+
26
+ {{acceptance}}
27
+
28
+ ## Pipeline test: NO