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.
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/commands/verity/architect.md +58 -0
- package/commands/verity/build.md +61 -0
- package/commands/verity/docs.md +37 -0
- package/commands/verity/golive.md +32 -0
- package/commands/verity/map.md +22 -0
- package/commands/verity/plan.md +67 -0
- package/commands/verity/review.md +50 -0
- package/commands/verity/security.md +36 -0
- package/commands/verity/ship.md +67 -0
- package/commands/verity/sre.md +31 -0
- package/commands/verity/test.md +29 -0
- package/commands/verity/verify.md +31 -0
- package/commands/verity/vision.md +55 -0
- package/package.json +31 -0
- package/verity/bin/lib/adr.cjs +67 -0
- package/verity/bin/lib/catalog.cjs +81 -0
- package/verity/bin/lib/config.cjs +119 -0
- package/verity/bin/lib/contract.cjs +57 -0
- package/verity/bin/lib/core.cjs +63 -0
- package/verity/bin/lib/golive.cjs +49 -0
- package/verity/bin/lib/handoff.cjs +72 -0
- package/verity/bin/lib/identity.cjs +112 -0
- package/verity/bin/lib/install.cjs +109 -0
- package/verity/bin/lib/ledger.cjs +244 -0
- package/verity/bin/lib/map.cjs +77 -0
- package/verity/bin/lib/recovery.cjs +37 -0
- package/verity/bin/lib/release.cjs +131 -0
- package/verity/bin/lib/review.cjs +74 -0
- package/verity/bin/lib/scaffold.cjs +66 -0
- package/verity/bin/lib/security.cjs +44 -0
- package/verity/bin/lib/smoke.cjs +170 -0
- package/verity/bin/lib/stage.cjs +180 -0
- package/verity/bin/lib/status.cjs +117 -0
- package/verity/bin/verity.cjs +190 -0
- package/verity/design-guides/contracts-first.md +32 -0
- package/verity/design-guides/features/helper-bot.md +61 -0
- package/verity/design-guides/stack-and-topology.md +38 -0
- package/verity/templates/LICENSE.tmpl +21 -0
- package/verity/templates/README.md.tmpl +14 -0
- package/verity/templates/STATUS.md.tmpl +27 -0
- package/verity/templates/adr.md.tmpl +21 -0
- package/verity/templates/bug_report.yml.tmpl +44 -0
- package/verity/templates/ci.yml.tmpl +36 -0
- package/verity/templates/contract.md.tmpl +21 -0
- package/verity/templates/gitignore.tmpl +9 -0
- package/verity/templates/handoff-brief.md.tmpl +32 -0
- package/verity/templates/handoff-readme.md.tmpl +21 -0
- package/verity/templates/recovery-plan.md.tmpl +29 -0
- package/verity/templates/security-invariants.md.tmpl +14 -0
- package/verity/templates/smoke.json.tmpl +21 -0
- 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,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
|