superdev-cli 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/.claude-plugin/marketplace.json +33 -0
- package/.claude-plugin/plugin.json +21 -0
- package/.codex-plugin/plugin.json +27 -0
- package/CODE_OF_CONDUCT.md +109 -0
- package/CONTRIBUTING.md +205 -0
- package/LICENSE +202 -0
- package/NOTICE +11 -0
- package/README.md +1051 -0
- package/SECURITY.md +135 -0
- package/THIRD-PARTY-NOTICES.md +253 -0
- package/hooks/hooks.json +61 -0
- package/hooks/run.mjs +88 -0
- package/package.json +65 -0
- package/references/confidentiality.md +48 -0
- package/references/evidence-and-risk.md +73 -0
- package/references/operating-model.md +105 -0
- package/references/platform-capabilities.md +51 -0
- package/references/project-record.md +91 -0
- package/references/provider-contracts.md +102 -0
- package/scripts/doctor/doctor.mjs +539 -0
- package/scripts/privacy/scan-history.mjs +163 -0
- package/scripts/privacy/scan.mjs +368 -0
- package/scripts/validate/README.md +94 -0
- package/scripts/validate/common.mjs +149 -0
- package/scripts/validate/data-model.mjs +225 -0
- package/scripts/validate/dependencies.mjs +69 -0
- package/scripts/validate/docs-templates.mjs +99 -0
- package/scripts/validate/footprint.mjs +78 -0
- package/scripts/validate/imports.mjs +61 -0
- package/scripts/validate/manifests.mjs +173 -0
- package/scripts/validate/markdown.mjs +123 -0
- package/scripts/validate/migrations.mjs +187 -0
- package/scripts/validate/no-tests.mjs +136 -0
- package/scripts/validate/privacy.mjs +115 -0
- package/scripts/validate/record-links.mjs +127 -0
- package/scripts/validate/skill-commands.mjs +190 -0
- package/scripts/validate/skills.mjs +112 -0
- package/scripts/validate/specification.mjs +88 -0
- package/scripts/validate/style.mjs +78 -0
- package/scripts/validate/validate-all.mjs +175 -0
- package/skills/debug/SKILL.md +68 -0
- package/skills/decision/SKILL.md +99 -0
- package/skills/docs/SKILL.md +86 -0
- package/skills/docs/assets/fragments/api/events.md +14 -0
- package/skills/docs/assets/fragments/api/graphql.md +14 -0
- package/skills/docs/assets/fragments/api/local-only.md +13 -0
- package/skills/docs/assets/fragments/api/rest.md +13 -0
- package/skills/docs/assets/fragments/api/rpc.md +13 -0
- package/skills/docs/assets/fragments/async/event-bus.md +13 -0
- package/skills/docs/assets/fragments/async/none.md +11 -0
- package/skills/docs/assets/fragments/async/platform-jobs.md +13 -0
- package/skills/docs/assets/fragments/async/queue.md +13 -0
- package/skills/docs/assets/fragments/async/scheduler.md +13 -0
- package/skills/docs/assets/fragments/auth/detected-provider.md +15 -0
- package/skills/docs/assets/fragments/auth/neutral-base.md +14 -0
- package/skills/docs/assets/fragments/data/document.md +13 -0
- package/skills/docs/assets/fragments/data/external-saas.md +13 -0
- package/skills/docs/assets/fragments/data/key-value.md +13 -0
- package/skills/docs/assets/fragments/data/none.md +12 -0
- package/skills/docs/assets/fragments/data/sql-orm.md +13 -0
- package/skills/docs/assets/fragments/data/sql-plain.md +13 -0
- package/skills/docs/assets/fragments/env/conventional.md +13 -0
- package/skills/docs/assets/fragments/env/envx.md +13 -0
- package/skills/docs/assets/fragments/env/managed-platform.md +13 -0
- package/skills/docs/assets/fragments/env/none.md +11 -0
- package/skills/docs/assets/fragments/ui/api-only.md +13 -0
- package/skills/docs/assets/fragments/ui/cli.md +14 -0
- package/skills/docs/assets/fragments/ui/desktop.md +14 -0
- package/skills/docs/assets/fragments/ui/mobile.md +14 -0
- package/skills/docs/assets/fragments/ui/web.md +14 -0
- package/skills/docs/assets/templates/adr.md +62 -0
- package/skills/docs/assets/templates/api.md +30 -0
- package/skills/docs/assets/templates/architecture.md +52 -0
- package/skills/docs/assets/templates/change-impact-drift-report.md +29 -0
- package/skills/docs/assets/templates/compliance.md +29 -0
- package/skills/docs/assets/templates/data-schema.md +43 -0
- package/skills/docs/assets/templates/feature.md +43 -0
- package/skills/docs/assets/templates/foundations.md +55 -0
- package/skills/docs/assets/templates/jobs-webhooks.md +36 -0
- package/skills/docs/assets/templates/module-inventory.md +19 -0
- package/skills/docs/assets/templates/module.md +50 -0
- package/skills/docs/assets/templates/nfr.md +22 -0
- package/skills/docs/assets/templates/observability.md +28 -0
- package/skills/docs/assets/templates/pages-ui-actions.md +47 -0
- package/skills/docs/assets/templates/project-summary.md +44 -0
- package/skills/docs/assets/templates/roles-permissions.md +26 -0
- package/skills/docs/assets/templates/test-plan.md +23 -0
- package/skills/docs/assets/templates/workflow-state-machine.md +43 -0
- package/skills/docs/references/adr-authoring.md +24 -0
- package/skills/docs/references/apis-and-data.md +23 -0
- package/skills/docs/references/capability-fragments.md +25 -0
- package/skills/docs/references/change-tracking.md +62 -0
- package/skills/docs/references/diagrams.md +31 -0
- package/skills/docs/references/discovery.md +59 -0
- package/skills/docs/references/edge-cases.md +45 -0
- package/skills/docs/references/foundations-modules.md +18 -0
- package/skills/docs/references/ingestion.md +52 -0
- package/skills/docs/references/initialize-adopt.md +25 -0
- package/skills/docs/references/module-decomposition.md +38 -0
- package/skills/docs/references/profiles.md +60 -0
- package/skills/docs/references/quality-attributes.md +27 -0
- package/skills/docs/references/reverse-engineer.md +21 -0
- package/skills/docs/references/spec-depths.md +31 -0
- package/skills/docs/references/summarize.md +18 -0
- package/skills/docs/references/surfaces-and-actions.md +24 -0
- package/skills/docs/references/validation.md +47 -0
- package/skills/docs/references/workflows-and-jobs.md +25 -0
- package/skills/docs/scripts/ingest.mjs +984 -0
- package/skills/docs/scripts/profile-detect.mjs +299 -0
- package/skills/docs/scripts/screen.mjs +96 -0
- package/skills/docs/scripts/template-lint.mjs +143 -0
- package/skills/docs/scripts/validate-docs.mjs +363 -0
- package/skills/doctor/SKILL.md +167 -0
- package/skills/feature/SKILL.md +132 -0
- package/skills/init/SKILL.md +137 -0
- package/skills/project/SKILL.md +261 -0
- package/skills/project/references/commands.md +213 -0
- package/skills/resume/SKILL.md +79 -0
- package/skills/review/SKILL.md +91 -0
- package/skills/status/SKILL.md +85 -0
- package/skills/task/SKILL.md +183 -0
- package/src/cli/product-map.mjs +468 -0
- package/src/cli/render.mjs +544 -0
- package/src/cli.mjs +2774 -0
- package/src/cloud/crypto.mjs +118 -0
- package/src/cloud/merge.mjs +186 -0
- package/src/cloud/policy.mjs +115 -0
- package/src/cloud/sync.mjs +512 -0
- package/src/cloud/transport.mjs +116 -0
- package/src/db/connect.mjs +189 -0
- package/src/db/maintenance.mjs +419 -0
- package/src/db/migrate.mjs +188 -0
- package/src/db/migrations/001_initial.sql +1024 -0
- package/src/db/migrations/002_docs_coverage.sql +126 -0
- package/src/db/migrations/003_memory_retrieval_and_integrity.sql +168 -0
- package/src/db/migrations/004_task_categories.sql +59 -0
- package/src/db/migrations/005_executable_evidence.sql +32 -0
- package/src/db/migrations/006_module_and_feature_boundaries.sql +27 -0
- package/src/db/migrations/007_drop_redundant_module_users.sql +13 -0
- package/src/db/migrations/008_changes_assumptions_test_plans_api_services.sql +166 -0
- package/src/db/migrations/009_retired_documents.sql +54 -0
- package/src/db/migrations/010_test_plan_evidence.sql +20 -0
- package/src/db/migrations/011_criterion_waiver.sql +13 -0
- package/src/db/migrations/012_synchronization.sql +56 -0
- package/src/db/store.mjs +327 -0
- package/src/decisions/record.mjs +167 -0
- package/src/docs/proposals.mjs +871 -0
- package/src/docs/render.mjs +1424 -0
- package/src/docs/templates.mjs +1281 -0
- package/src/features/acceptance.mjs +315 -0
- package/src/features/specify.mjs +248 -0
- package/src/init/discovery.mjs +901 -0
- package/src/init/index.mjs +784 -0
- package/src/init/questions.mjs +562 -0
- package/src/memory/benchmark.mjs +171 -0
- package/src/memory/capture.mjs +135 -0
- package/src/memory/consolidate.mjs +255 -0
- package/src/memory/index.mjs +810 -0
- package/src/model/ids.mjs +185 -0
- package/src/model/screening.mjs +150 -0
- package/src/model/toolkit.mjs +258 -0
- package/src/model/vocabulary.mjs +190 -0
- package/src/product/assumptions.mjs +120 -0
- package/src/product/changes.mjs +180 -0
- package/src/product/test-plans.mjs +183 -0
- package/src/progress/index.mjs +1364 -0
- package/src/runtime/harness.mjs +264 -0
- package/src/runtime/hooks.mjs +1021 -0
- package/src/runtime/identity.mjs +305 -0
- package/src/runtime/resume.mjs +343 -0
- package/src/runtime/session.mjs +679 -0
- package/src/runtime/version.mjs +315 -0
- package/src/service/assets/control-center.html +206 -0
- package/src/service/assets/control-center.manifest.json +7 -0
- package/src/service/manage.mjs +542 -0
- package/src/service/mutations.mjs +860 -0
- package/src/service/read-model.mjs +1557 -0
- package/src/service/server.mjs +783 -0
- package/src/tasks/categories.mjs +154 -0
- package/src/tasks/derive.mjs +977 -0
- package/src/tasks/lifecycle.mjs +830 -0
- package/src/verify/index.mjs +236 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
-- Storage for Docs template fields that version 1 left homeless. Without these
|
|
2
|
+
-- the renderer would have to invent a place to keep them, which is how a second
|
|
3
|
+
-- writable source of truth gets created by accident.
|
|
4
|
+
|
|
5
|
+
-- foundations.md asks for explicit non-goals and a project-level scope. Feature
|
|
6
|
+
-- scope does not roll up to answer "what is deliberately out of scope".
|
|
7
|
+
CREATE TABLE project_scope_items (
|
|
8
|
+
id TEXT PRIMARY KEY,
|
|
9
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
10
|
+
direction TEXT NOT NULL CHECK (direction IN ('in','out','non_goal')),
|
|
11
|
+
statement TEXT NOT NULL,
|
|
12
|
+
why TEXT,
|
|
13
|
+
horizon TEXT,
|
|
14
|
+
sequence INTEGER NOT NULL DEFAULT 0
|
|
15
|
+
);
|
|
16
|
+
CREATE INDEX project_scope_items_project ON project_scope_items(project_id, direction, sequence);
|
|
17
|
+
|
|
18
|
+
-- foundations.md requires a glossary. One meaning per term.
|
|
19
|
+
CREATE TABLE glossary_terms (
|
|
20
|
+
id TEXT PRIMARY KEY,
|
|
21
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
22
|
+
term TEXT NOT NULL,
|
|
23
|
+
meaning TEXT NOT NULL,
|
|
24
|
+
source_ref TEXT,
|
|
25
|
+
UNIQUE (project_id, term)
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
-- architecture.md's runtime pieces table. Modules are a logical decomposition,
|
|
29
|
+
-- not a runtime topology, so they cannot answer "runs where, talks to what".
|
|
30
|
+
CREATE TABLE runtime_pieces (
|
|
31
|
+
id TEXT PRIMARY KEY,
|
|
32
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
33
|
+
name TEXT NOT NULL,
|
|
34
|
+
runs_where TEXT,
|
|
35
|
+
evidence_ref TEXT,
|
|
36
|
+
sequence INTEGER NOT NULL DEFAULT 0,
|
|
37
|
+
UNIQUE (project_id, name)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
CREATE TABLE runtime_piece_edges (
|
|
41
|
+
from_piece_id TEXT NOT NULL REFERENCES runtime_pieces(id) ON DELETE CASCADE,
|
|
42
|
+
to_piece_id TEXT NOT NULL REFERENCES runtime_pieces(id) ON DELETE CASCADE,
|
|
43
|
+
protocol TEXT,
|
|
44
|
+
PRIMARY KEY (from_piece_id, to_piece_id)
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
-- The ADR template carries four relationship statuses that version 1 could not
|
|
48
|
+
-- store. Partial supersession needs its exact scope, not just a pointer.
|
|
49
|
+
CREATE TABLE decision_links (
|
|
50
|
+
id TEXT PRIMARY KEY,
|
|
51
|
+
decision_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
|
52
|
+
target_type TEXT NOT NULL CHECK (target_type IN
|
|
53
|
+
('decision','feature','module','workflow','document','api_operation','data_entity','nfr')),
|
|
54
|
+
target_id TEXT NOT NULL,
|
|
55
|
+
relationship TEXT NOT NULL CHECK (relationship IN
|
|
56
|
+
('supersedes','partially_supersedes','amends','relates_to','governs')),
|
|
57
|
+
scope_note TEXT,
|
|
58
|
+
created_at TEXT NOT NULL,
|
|
59
|
+
-- A partial supersession without its scope is the ambiguity the ADR
|
|
60
|
+
-- lifecycle exists to prevent.
|
|
61
|
+
CHECK (relationship <> 'partially_supersedes' OR scope_note IS NOT NULL)
|
|
62
|
+
);
|
|
63
|
+
CREATE INDEX decision_links_decision ON decision_links(decision_id);
|
|
64
|
+
CREATE INDEX decision_links_target ON decision_links(target_type, target_id);
|
|
65
|
+
|
|
66
|
+
-- A time-boxed decision needs an expiry, and it cannot be derived from
|
|
67
|
+
-- acceptance. An expired decision stops governing and starts asking.
|
|
68
|
+
ALTER TABLE decisions ADD COLUMN expires_at TEXT;
|
|
69
|
+
|
|
70
|
+
-- roles.md asks for Role, Who, and Primary goals. Two columns forced one of the
|
|
71
|
+
-- three into free prose.
|
|
72
|
+
ALTER TABLE roles ADD COLUMN who TEXT;
|
|
73
|
+
ALTER TABLE roles ADD COLUMN primary_goals TEXT;
|
|
74
|
+
|
|
75
|
+
-- Not every generated file is an authored projection. A changelog, a status
|
|
76
|
+
-- report and a drift report are derived views: they are rewritten every time
|
|
77
|
+
-- and must never be trapped behind an edit proposal. Without this distinction
|
|
78
|
+
-- one stray manual edit would permanently block regeneration of a report whose
|
|
79
|
+
-- whole purpose is to be current.
|
|
80
|
+
ALTER TABLE documents ADD COLUMN regeneration_mode TEXT NOT NULL DEFAULT 'authored_projection';
|
|
81
|
+
|
|
82
|
+
-- A project-wide revision would mark every document stale on any unrelated
|
|
83
|
+
-- write, so freshness is per document: a hash of the ordered records that fed
|
|
84
|
+
-- the render.
|
|
85
|
+
ALTER TABLE documents ADD COLUMN source_fingerprint TEXT;
|
|
86
|
+
|
|
87
|
+
-- Capability areas gain a catalog so the readiness checklist, the foundations
|
|
88
|
+
-- stack slots and the architecture boundaries share one shape and one query.
|
|
89
|
+
-- The table is rebuilt rather than altered because the uniqueness rule changes,
|
|
90
|
+
-- which is exactly the case an ordered migration exists to handle.
|
|
91
|
+
CREATE TABLE capability_areas_v2 (
|
|
92
|
+
id TEXT PRIMARY KEY,
|
|
93
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
94
|
+
catalog TEXT NOT NULL DEFAULT 'readiness'
|
|
95
|
+
CHECK (catalog IN ('readiness','stack_slot','boundary')),
|
|
96
|
+
scope_type TEXT NOT NULL DEFAULT 'project'
|
|
97
|
+
CHECK (scope_type IN ('project','module','feature')),
|
|
98
|
+
scope_id TEXT,
|
|
99
|
+
area TEXT NOT NULL,
|
|
100
|
+
state TEXT NOT NULL DEFAULT 'awaiting_decision'
|
|
101
|
+
CHECK (state IN ('specified','awaiting_decision','not_applicable','deferred')),
|
|
102
|
+
choice TEXT,
|
|
103
|
+
evidence_ref TEXT,
|
|
104
|
+
decision_id TEXT REFERENCES decisions(id) ON DELETE SET NULL,
|
|
105
|
+
reason TEXT,
|
|
106
|
+
owner TEXT,
|
|
107
|
+
revisit_trigger TEXT,
|
|
108
|
+
consequence TEXT,
|
|
109
|
+
question_id TEXT REFERENCES questions(id) ON DELETE SET NULL,
|
|
110
|
+
sequence INTEGER NOT NULL DEFAULT 0,
|
|
111
|
+
updated_at TEXT NOT NULL,
|
|
112
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
113
|
+
CHECK (state = 'specified' OR reason IS NOT NULL),
|
|
114
|
+
UNIQUE (project_id, catalog, scope_type, scope_id, area)
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
INSERT INTO capability_areas_v2
|
|
118
|
+
(id, project_id, catalog, scope_type, scope_id, area, state, reason, owner,
|
|
119
|
+
revisit_trigger, consequence, question_id, sequence, updated_at, version)
|
|
120
|
+
SELECT id, project_id, 'readiness', 'project', NULL, area, state, reason, owner,
|
|
121
|
+
revisit_trigger, consequence, question_id, sequence, updated_at, version
|
|
122
|
+
FROM capability_areas;
|
|
123
|
+
|
|
124
|
+
DROP TABLE capability_areas;
|
|
125
|
+
|
|
126
|
+
ALTER TABLE capability_areas_v2 RENAME TO capability_areas;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
-- Memory retrieval, link integrity, idempotent capture and honest verification.
|
|
2
|
+
--
|
|
3
|
+
-- Measured on the engine before designing this: under MVCC every virtual table
|
|
4
|
+
-- is refused outright ("Virtual tables are not supported in MVCC mode"), and
|
|
5
|
+
-- under WAL the bundled build reports "no such module: fts5" and "no such
|
|
6
|
+
-- module: rtree". So full-text retrieval is an inverted index in ordinary
|
|
7
|
+
-- tables, not FTS5, and not a scan over the newest N rows.
|
|
8
|
+
|
|
9
|
+
-- ------------------------------------------------------- inverted term index
|
|
10
|
+
|
|
11
|
+
-- One row per (memory, term, field). Retrieval selects candidates through the
|
|
12
|
+
-- term index and only then applies recency, authority and epistemic weighting,
|
|
13
|
+
-- so a relevant memory stays reachable no matter how old it is or how many
|
|
14
|
+
-- newer ones exist.
|
|
15
|
+
CREATE TABLE memory_search_terms (
|
|
16
|
+
memory_id TEXT NOT NULL REFERENCES memory_entries(id) ON DELETE CASCADE,
|
|
17
|
+
term TEXT NOT NULL,
|
|
18
|
+
field TEXT NOT NULL CHECK (field IN ('title','content','source_ref')),
|
|
19
|
+
frequency INTEGER NOT NULL DEFAULT 1,
|
|
20
|
+
field_weight REAL NOT NULL DEFAULT 1.0,
|
|
21
|
+
PRIMARY KEY (memory_id, term, field)
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
-- The lookup direction: term first. Without this the index is a scan wearing a
|
|
25
|
+
-- table's clothes.
|
|
26
|
+
CREATE INDEX memory_search_terms_term ON memory_search_terms(term, memory_id);
|
|
27
|
+
|
|
28
|
+
-- --------------------------------------------------------- idempotent capture
|
|
29
|
+
|
|
30
|
+
-- A hook, a compaction and a handoff all retry. Without a deterministic key the
|
|
31
|
+
-- same observation lands three times and recall starts reporting its own echo
|
|
32
|
+
-- as corroboration.
|
|
33
|
+
ALTER TABLE memory_entries ADD COLUMN dedupe_key TEXT;
|
|
34
|
+
ALTER TABLE memory_entries ADD COLUMN source_event_id TEXT;
|
|
35
|
+
ALTER TABLE memory_entries ADD COLUMN content_hash TEXT;
|
|
36
|
+
|
|
37
|
+
-- Deliberately scoped to an explicit key rather than to the content hash: two
|
|
38
|
+
-- genuinely different observations may be worded alike, and collapsing those
|
|
39
|
+
-- would lose real information. Only a caller-supplied key claims "this is the
|
|
40
|
+
-- same delivery".
|
|
41
|
+
CREATE UNIQUE INDEX memory_entries_dedupe
|
|
42
|
+
ON memory_entries(project_id, dedupe_key) WHERE dedupe_key IS NOT NULL;
|
|
43
|
+
|
|
44
|
+
CREATE INDEX memory_entries_source_event
|
|
45
|
+
ON memory_entries(source_event_id) WHERE source_event_id IS NOT NULL;
|
|
46
|
+
|
|
47
|
+
-- --------------------------------------------------------- honest verification
|
|
48
|
+
|
|
49
|
+
-- Rebuilt rather than altered: target_type gains a CHECK, and every link now
|
|
50
|
+
-- captures what the target looked like when the memory was written. Existence
|
|
51
|
+
-- alone can never prove a recalled fact is still true, so the version and
|
|
52
|
+
-- fingerprint recorded here are what later distinguishes verified from
|
|
53
|
+
-- needs_review.
|
|
54
|
+
CREATE TABLE memory_links_v2 (
|
|
55
|
+
memory_id TEXT NOT NULL REFERENCES memory_entries(id) ON DELETE CASCADE,
|
|
56
|
+
target_type TEXT NOT NULL CHECK (target_type IN (
|
|
57
|
+
'task','feature','workflow','workflow_step','decision',
|
|
58
|
+
'branch','verification_evidence','module','milestone',
|
|
59
|
+
'goal','surface','ui_action','api_operation','data_entity',
|
|
60
|
+
'integration','question','work_session')),
|
|
61
|
+
target_id TEXT NOT NULL,
|
|
62
|
+
relationship TEXT NOT NULL DEFAULT 'about',
|
|
63
|
+
target_version INTEGER,
|
|
64
|
+
target_fingerprint TEXT,
|
|
65
|
+
created_at TEXT,
|
|
66
|
+
PRIMARY KEY (memory_id, target_type, target_id)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
INSERT INTO memory_links_v2 (memory_id, target_type, target_id, relationship)
|
|
70
|
+
SELECT memory_id, target_type, target_id, relationship FROM memory_links
|
|
71
|
+
WHERE target_type IN (
|
|
72
|
+
'task','feature','workflow','workflow_step','decision','branch',
|
|
73
|
+
'verification_evidence','module','milestone','goal','surface','ui_action',
|
|
74
|
+
'api_operation','data_entity','integration','question','work_session');
|
|
75
|
+
|
|
76
|
+
DROP TABLE memory_links;
|
|
77
|
+
|
|
78
|
+
ALTER TABLE memory_links_v2 RENAME TO memory_links;
|
|
79
|
+
|
|
80
|
+
-- Reverse lookup: "what do we remember about this record". Structured recall
|
|
81
|
+
-- filters through here, not only through the direct task and feature columns.
|
|
82
|
+
CREATE INDEX memory_links_reverse ON memory_links(target_type, target_id, memory_id);
|
|
83
|
+
|
|
84
|
+
-- ------------------------------------------------------------ link integrity
|
|
85
|
+
|
|
86
|
+
-- A link to a record that does not exist is not a weak link, it is a false one.
|
|
87
|
+
-- SQLite cannot express a foreign key whose table depends on a column value, so
|
|
88
|
+
-- each supported type gets its own guard.
|
|
89
|
+
CREATE TRIGGER memory_links_task_exists
|
|
90
|
+
BEFORE INSERT ON memory_links
|
|
91
|
+
WHEN NEW.target_type = 'task' AND NOT EXISTS (SELECT 1 FROM tasks WHERE id = NEW.target_id)
|
|
92
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
93
|
+
|
|
94
|
+
CREATE TRIGGER memory_links_feature_exists
|
|
95
|
+
BEFORE INSERT ON memory_links
|
|
96
|
+
WHEN NEW.target_type = 'feature' AND NOT EXISTS (SELECT 1 FROM features WHERE id = NEW.target_id)
|
|
97
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
98
|
+
|
|
99
|
+
CREATE TRIGGER memory_links_workflow_exists
|
|
100
|
+
BEFORE INSERT ON memory_links
|
|
101
|
+
WHEN NEW.target_type = 'workflow' AND NOT EXISTS (SELECT 1 FROM workflows WHERE id = NEW.target_id)
|
|
102
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
103
|
+
|
|
104
|
+
CREATE TRIGGER memory_links_workflow_step_exists
|
|
105
|
+
BEFORE INSERT ON memory_links
|
|
106
|
+
WHEN NEW.target_type = 'workflow_step' AND NOT EXISTS (SELECT 1 FROM workflow_steps WHERE id = NEW.target_id)
|
|
107
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
108
|
+
|
|
109
|
+
CREATE TRIGGER memory_links_decision_exists
|
|
110
|
+
BEFORE INSERT ON memory_links
|
|
111
|
+
WHEN NEW.target_type = 'decision' AND NOT EXISTS (SELECT 1 FROM decisions WHERE id = NEW.target_id)
|
|
112
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
113
|
+
|
|
114
|
+
CREATE TRIGGER memory_links_branch_exists
|
|
115
|
+
BEFORE INSERT ON memory_links
|
|
116
|
+
WHEN NEW.target_type = 'branch' AND NOT EXISTS (SELECT 1 FROM branches WHERE id = NEW.target_id)
|
|
117
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
118
|
+
|
|
119
|
+
CREATE TRIGGER memory_links_evidence_exists
|
|
120
|
+
BEFORE INSERT ON memory_links
|
|
121
|
+
WHEN NEW.target_type = 'verification_evidence' AND NOT EXISTS (SELECT 1 FROM verification_evidence WHERE id = NEW.target_id)
|
|
122
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
123
|
+
|
|
124
|
+
CREATE TRIGGER memory_links_module_exists
|
|
125
|
+
BEFORE INSERT ON memory_links
|
|
126
|
+
WHEN NEW.target_type = 'module' AND NOT EXISTS (SELECT 1 FROM modules WHERE id = NEW.target_id)
|
|
127
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
128
|
+
|
|
129
|
+
CREATE TRIGGER memory_links_milestone_exists
|
|
130
|
+
BEFORE INSERT ON memory_links
|
|
131
|
+
WHEN NEW.target_type = 'milestone' AND NOT EXISTS (SELECT 1 FROM milestones WHERE id = NEW.target_id)
|
|
132
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
133
|
+
|
|
134
|
+
CREATE TRIGGER memory_links_goal_exists
|
|
135
|
+
BEFORE INSERT ON memory_links
|
|
136
|
+
WHEN NEW.target_type = 'goal' AND NOT EXISTS (SELECT 1 FROM goals WHERE id = NEW.target_id)
|
|
137
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
138
|
+
|
|
139
|
+
CREATE TRIGGER memory_links_session_exists
|
|
140
|
+
BEFORE INSERT ON memory_links
|
|
141
|
+
WHEN NEW.target_type = 'work_session' AND NOT EXISTS (SELECT 1 FROM work_sessions WHERE id = NEW.target_id)
|
|
142
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
143
|
+
|
|
144
|
+
CREATE TRIGGER memory_links_question_exists
|
|
145
|
+
BEFORE INSERT ON memory_links
|
|
146
|
+
WHEN NEW.target_type = 'question' AND NOT EXISTS (SELECT 1 FROM questions WHERE id = NEW.target_id)
|
|
147
|
+
BEGIN SELECT RAISE(ABORT, 'E_MEMORY_LINK_ORPHAN'); END;
|
|
148
|
+
|
|
149
|
+
-- ------------------------------------------------------------ embedding seam
|
|
150
|
+
|
|
151
|
+
-- The seam, kept separate and empty. The embedding column on memory_entries was
|
|
152
|
+
-- a placeholder that looked like a finished vector design and was not: it had no
|
|
153
|
+
-- provider, no model, no dimensions, and nothing recording which content it was
|
|
154
|
+
-- computed from. This table is the honest shape. Nothing populates it in this
|
|
155
|
+
-- release, and this engine has no vector index, so any future recall through it
|
|
156
|
+
-- is a bounded scan and must say so.
|
|
157
|
+
CREATE TABLE memory_embeddings (
|
|
158
|
+
memory_id TEXT NOT NULL REFERENCES memory_entries(id) ON DELETE CASCADE,
|
|
159
|
+
provider TEXT NOT NULL,
|
|
160
|
+
model TEXT NOT NULL,
|
|
161
|
+
dimensions INTEGER NOT NULL,
|
|
162
|
+
content_hash TEXT NOT NULL,
|
|
163
|
+
embedding BLOB,
|
|
164
|
+
generated_at TEXT,
|
|
165
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
166
|
+
CHECK (status IN ('pending','ready','stale','failed')),
|
|
167
|
+
PRIMARY KEY (memory_id, provider, model)
|
|
168
|
+
);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
-- More task categories, and a place for a category to say what it means.
|
|
2
|
+
--
|
|
3
|
+
-- The original twelve came from brief section 7.3, but derivation produces work
|
|
4
|
+
-- the twelve could not describe: proving rollout and rollback was filed under
|
|
5
|
+
-- Infrastructure, and a surface with its actions under Feature. A category that
|
|
6
|
+
-- does not describe the work is worse than no category, because it is a label
|
|
7
|
+
-- people learn to ignore.
|
|
8
|
+
--
|
|
9
|
+
-- The descriptions are written out here rather than read from the vocabulary
|
|
10
|
+
-- module because a migration cannot import application code. The module stays
|
|
11
|
+
-- the source for newly created projects; this is the one-time backfill for
|
|
12
|
+
-- projects that already exist.
|
|
13
|
+
|
|
14
|
+
ALTER TABLE task_categories ADD COLUMN description TEXT;
|
|
15
|
+
|
|
16
|
+
-- Meanings for the categories already seeded.
|
|
17
|
+
UPDATE task_categories SET description = 'New product behavior somebody asked for.' WHERE name = 'Feature' AND description IS NULL;
|
|
18
|
+
UPDATE task_categories SET description = 'Existing behavior made better without changing what it is.' WHERE name = 'Improvement' AND description IS NULL;
|
|
19
|
+
UPDATE task_categories SET description = 'Behavior that does not match what was accepted.' WHERE name = 'Bug' AND description IS NULL;
|
|
20
|
+
UPDATE task_categories SET description = 'Internal change with no change in behavior.' WHERE name = 'Refactor' AND description IS NULL;
|
|
21
|
+
UPDATE task_categories SET description = 'Finding something out before deciding what to build.' WHERE name = 'Investigation' AND description IS NULL;
|
|
22
|
+
UPDATE task_categories SET description = 'Keeping the written record in step with the product.' WHERE name = 'Documentation' AND description IS NULL;
|
|
23
|
+
UPDATE task_categories SET description = 'Work at the boundary with something outside this product.' WHERE name = 'Integration' AND description IS NULL;
|
|
24
|
+
UPDATE task_categories SET description = 'Moving data or schema from one shape to another.' WHERE name = 'Migration' AND description IS NULL;
|
|
25
|
+
UPDATE task_categories SET description = 'The ground the product runs on.' WHERE name = 'Infrastructure' AND description IS NULL;
|
|
26
|
+
UPDATE task_categories SET description = 'Protecting the product, its data and the people in it.' WHERE name = 'Security' AND description IS NULL;
|
|
27
|
+
UPDATE task_categories SET description = 'Work that raises confidence rather than adding behavior.' WHERE name = 'Quality' AND description IS NULL;
|
|
28
|
+
UPDATE task_categories SET description = 'Agreed as worth doing, not yet scheduled.' WHERE name = 'Backlog' AND description IS NULL;
|
|
29
|
+
|
|
30
|
+
-- The nine additions, seeded for every project that already exists. Sequence
|
|
31
|
+
-- continues from whatever that project already had, so a project that added its
|
|
32
|
+
-- own categories does not have them reordered underneath it.
|
|
33
|
+
INSERT INTO task_categories (id, project_id, name, description, system, active, sequence)
|
|
34
|
+
SELECT
|
|
35
|
+
'TC-' || substr('0000' || CAST(
|
|
36
|
+
(SELECT count(*) FROM task_categories x WHERE x.project_id = p.id) + n.ord AS TEXT
|
|
37
|
+
), -4),
|
|
38
|
+
p.id, n.name, n.description, 1, 1,
|
|
39
|
+
(SELECT coalesce(max(x.sequence), -1) FROM task_categories x WHERE x.project_id = p.id) + n.ord
|
|
40
|
+
FROM projects p
|
|
41
|
+
CROSS JOIN (
|
|
42
|
+
SELECT 1 AS ord, 'Design' AS name, 'Surfaces, actions and how the product presents itself.' AS description
|
|
43
|
+
UNION ALL SELECT 2, 'Testing', 'Product tests derived from the accepted test plan.'
|
|
44
|
+
UNION ALL SELECT 3, 'Performance', 'Meeting a declared speed or capacity target.'
|
|
45
|
+
UNION ALL SELECT 4, 'Accessibility', 'Making the product operable by everyone who uses it.'
|
|
46
|
+
UNION ALL SELECT 5, 'Observability', 'Signals that prove the product is working in the open.'
|
|
47
|
+
UNION ALL SELECT 6, 'Data', 'Modelling the entities and relationships the product owns.'
|
|
48
|
+
UNION ALL SELECT 7, 'Release', 'Getting the work out, and being able to take it back.'
|
|
49
|
+
UNION ALL SELECT 8, 'Compliance', 'Obligations under a regime this project has declared.'
|
|
50
|
+
UNION ALL SELECT 9, 'Chore', 'Routine upkeep that keeps the project healthy.'
|
|
51
|
+
) n
|
|
52
|
+
WHERE NOT EXISTS (
|
|
53
|
+
SELECT 1 FROM task_categories e WHERE e.project_id = p.id AND e.name = n.name
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
-- A category a project added itself is never silently removed, so retiring one
|
|
57
|
+
-- has to be a status change rather than a delete. `active` already carries that;
|
|
58
|
+
-- this index makes the common read, the pickable list, cheap.
|
|
59
|
+
CREATE INDEX task_categories_active ON task_categories(project_id, active, sequence);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-- Evidence that can be checked again.
|
|
2
|
+
--
|
|
3
|
+
-- verification_evidence already carried status ('current', 'stale',
|
|
4
|
+
-- 'superseded'), stale_at and content_hash, so the design always intended
|
|
5
|
+
-- evidence to go out of date. Nothing ever marked it. Evidence was a sentence
|
|
6
|
+
-- written once and believed forever, which is the same shape as every other
|
|
7
|
+
-- failure found in this codebase: an intention recorded on one side with no
|
|
8
|
+
-- mechanism on the other.
|
|
9
|
+
--
|
|
10
|
+
-- A claim that carries the command which proved it can be checked again. That
|
|
11
|
+
-- turns honesty from something asserted at one moment into something the
|
|
12
|
+
-- product keeps checking, and it is the only way a completed task can notice
|
|
13
|
+
-- that the ground moved under it.
|
|
14
|
+
--
|
|
15
|
+
-- check_command is nullable on purpose. Reading a screenshot, confirming a
|
|
16
|
+
-- decision with the owner, watching a migration run: these are real
|
|
17
|
+
-- verifications that no command reproduces. Requiring one would push people to
|
|
18
|
+
-- invent commands, which is worse than admitting a check is manual.
|
|
19
|
+
|
|
20
|
+
ALTER TABLE verification_evidence ADD COLUMN check_command TEXT;
|
|
21
|
+
|
|
22
|
+
-- When the command was last run, and what happened. Distinct from recorded_at,
|
|
23
|
+
-- which is when the claim was first made: the gap between the two is exactly
|
|
24
|
+
-- the question "is this still true?".
|
|
25
|
+
ALTER TABLE verification_evidence ADD COLUMN last_checked_at TEXT;
|
|
26
|
+
ALTER TABLE verification_evidence ADD COLUMN last_check_result TEXT
|
|
27
|
+
CHECK (last_check_result IS NULL OR last_check_result IN ('pass', 'fail', 'error'));
|
|
28
|
+
|
|
29
|
+
-- Finding stale evidence is a scan over everything current that carries a
|
|
30
|
+
-- command, so it gets an index rather than a table walk on every run.
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_recheck
|
|
32
|
+
ON verification_evidence (status, check_command);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-- What a module excludes, and what a feature is for.
|
|
2
|
+
--
|
|
3
|
+
-- Section 8.3 step 4 of the requirements document asks, for every module, "What
|
|
4
|
+
-- is explicitly outside its scope?". There was nowhere to put the answer.
|
|
5
|
+
-- Features carry scope_in_json and scope_out_json; modules carried neither, so
|
|
6
|
+
-- the boundary that makes a module a module had to be folded into its purpose
|
|
7
|
+
-- as prose or dropped.
|
|
8
|
+
--
|
|
9
|
+
-- A module without a stated boundary is the failure the document names in
|
|
10
|
+
-- section 3: unclear architecture, and work that drifts because nobody wrote
|
|
11
|
+
-- down where one part stops.
|
|
12
|
+
|
|
13
|
+
ALTER TABLE modules ADD COLUMN out_of_scope TEXT;
|
|
14
|
+
|
|
15
|
+
-- Which people this module serves, from the same interview. Kept as text rather
|
|
16
|
+
-- than a link table because the answer is usually a sentence naming a role, and
|
|
17
|
+
-- a role row may not exist yet at discovery time.
|
|
18
|
+
ALTER TABLE modules ADD COLUMN primary_users TEXT;
|
|
19
|
+
|
|
20
|
+
-- Section 8.3 step 5 asks for a feature's user problem and intended outcome
|
|
21
|
+
-- before anything else. user_statement holds the first; the table already has
|
|
22
|
+
-- user_value for the second. Without it a feature is a title and a purpose,
|
|
23
|
+
-- which is what makes a specification thin enough to build the wrong thing.
|
|
24
|
+
--
|
|
25
|
+
-- features.user_statement already exists, so only the module columns are added
|
|
26
|
+
-- here. This migration is named for both because the boundary question is one
|
|
27
|
+
-- question asked at two levels.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- Remove a column that duplicated one already there.
|
|
2
|
+
--
|
|
3
|
+
-- 006 added modules.primary_users without checking that modules.primary_users_json
|
|
4
|
+
-- already held the same answer. Two columns for "which people this module serves"
|
|
5
|
+
-- is worse than either alone: a reader has to work out which one is filled, and a
|
|
6
|
+
-- writer has to guess which one is read.
|
|
7
|
+
--
|
|
8
|
+
-- The column was added and dropped without ever being written to, so nothing is
|
|
9
|
+
-- lost. It is dropped in its own migration rather than by editing 006, because
|
|
10
|
+
-- an applied migration's checksum is recorded and changing the file after the
|
|
11
|
+
-- fact is exactly the drift the migration validator exists to catch.
|
|
12
|
+
|
|
13
|
+
ALTER TABLE modules DROP COLUMN primary_users;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
-- The four objects the requirements document names and the schema never built.
|
|
2
|
+
--
|
|
3
|
+
-- Section 6.1 defines each of them, 14.1 lists each as a record the local
|
|
4
|
+
-- database must store, and none of them existed. The record could name them and
|
|
5
|
+
-- nothing could hold one, so four capabilities the document promises had no
|
|
6
|
+
-- place to live: recording what altered accepted scope, recording a reversible
|
|
7
|
+
-- answer with its review trigger, recording how a feature will be verified, and
|
|
8
|
+
-- grouping API operations under the boundary that owns them.
|
|
9
|
+
|
|
10
|
+
-- A recorded alteration to accepted product scope or behaviour.
|
|
11
|
+
--
|
|
12
|
+
-- Section 6.2 says a Change must record the affected records and the reason,
|
|
13
|
+
-- and 14.2 says changes must preserve audit history. Activity events already
|
|
14
|
+
-- record that something happened; a change records that accepted scope moved
|
|
15
|
+
-- and why, which is a different claim and the one a reader asks about later.
|
|
16
|
+
CREATE TABLE changes (
|
|
17
|
+
id TEXT PRIMARY KEY,
|
|
18
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
19
|
+
summary TEXT NOT NULL,
|
|
20
|
+
reason TEXT NOT NULL,
|
|
21
|
+
-- What kind of movement this was, so a reader can tell a widening from a
|
|
22
|
+
-- correction without reading every one.
|
|
23
|
+
change_type TEXT NOT NULL DEFAULT 'scope_changed'
|
|
24
|
+
CHECK (change_type IN ('scope_added', 'scope_removed', 'behavior_changed',
|
|
25
|
+
'contract_changed', 'correction', 'scope_changed')),
|
|
26
|
+
requested_by TEXT,
|
|
27
|
+
decided_by TEXT,
|
|
28
|
+
-- The decision that authorised it, when one did. A change that contradicts an
|
|
29
|
+
-- accepted decision without superseding it is the drift this product exists
|
|
30
|
+
-- to prevent.
|
|
31
|
+
decision_id TEXT REFERENCES decisions(id) ON DELETE SET NULL,
|
|
32
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
33
|
+
session_id TEXT,
|
|
34
|
+
status TEXT NOT NULL DEFAULT 'recorded'
|
|
35
|
+
CHECK (status IN ('proposed', 'recorded', 'reverted')),
|
|
36
|
+
created_at TEXT NOT NULL,
|
|
37
|
+
version INTEGER NOT NULL DEFAULT 1
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
-- Which records a change moved. Polymorphic because a change can touch a
|
|
41
|
+
-- feature, a workflow, an entity or an operation, and one column cannot
|
|
42
|
+
-- reference six tables.
|
|
43
|
+
CREATE TABLE change_targets (
|
|
44
|
+
change_id TEXT NOT NULL REFERENCES changes(id) ON DELETE CASCADE,
|
|
45
|
+
target_type TEXT NOT NULL,
|
|
46
|
+
target_id TEXT NOT NULL,
|
|
47
|
+
-- What moved about it, in plain language: "acceptance criterion added",
|
|
48
|
+
-- "purpose rewritten". Without this the link says something changed and never
|
|
49
|
+
-- what.
|
|
50
|
+
what_changed TEXT,
|
|
51
|
+
PRIMARY KEY (change_id, target_type, target_id)
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
-- A reversible answer used temporarily.
|
|
55
|
+
--
|
|
56
|
+
-- Section 8.4 says "I do not know" is a valid answer, that Superdev may
|
|
57
|
+
-- recommend a reversible assumption, and that it must record the assumption and
|
|
58
|
+
-- its review trigger. Without somewhere to put one, an assumption becomes an
|
|
59
|
+
-- undocumented guess that nobody knows to revisit.
|
|
60
|
+
CREATE TABLE assumptions (
|
|
61
|
+
id TEXT PRIMARY KEY,
|
|
62
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
63
|
+
statement TEXT NOT NULL,
|
|
64
|
+
-- Why this was assumed rather than decided. An assumption with no reason is
|
|
65
|
+
-- indistinguishable from a decision nobody wrote down.
|
|
66
|
+
why_assumed TEXT NOT NULL,
|
|
67
|
+
-- What would make this worth revisiting. Required, because an assumption with
|
|
68
|
+
-- no trigger is never reviewed and quietly becomes a fact.
|
|
69
|
+
review_trigger TEXT NOT NULL,
|
|
70
|
+
-- What breaks if the assumption turns out wrong.
|
|
71
|
+
consequence_if_wrong TEXT,
|
|
72
|
+
scope_type TEXT,
|
|
73
|
+
scope_id TEXT,
|
|
74
|
+
question_id TEXT REFERENCES questions(id) ON DELETE SET NULL,
|
|
75
|
+
status TEXT NOT NULL DEFAULT 'holding'
|
|
76
|
+
CHECK (status IN ('holding', 'confirmed', 'overturned', 'expired')),
|
|
77
|
+
-- Set when the assumption stops holding, with what replaced it.
|
|
78
|
+
resolved_by TEXT,
|
|
79
|
+
resolved_at TEXT,
|
|
80
|
+
resolution TEXT,
|
|
81
|
+
created_at TEXT NOT NULL,
|
|
82
|
+
updated_at TEXT NOT NULL,
|
|
83
|
+
version INTEGER NOT NULL DEFAULT 1
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
-- The agreed verification strategy for a feature or a workflow.
|
|
87
|
+
--
|
|
88
|
+
-- Section 9.3 gates task completion on "product tests defined by the accepted
|
|
89
|
+
-- test plan" passing, and 7.2 requires generated test plan documents. The gate
|
|
90
|
+
-- named a document that could not exist. Section 20.2 says the strategy is the
|
|
91
|
+
-- product's own rather than one universal style, so the kinds are open text
|
|
92
|
+
-- with a check on the ones the document names.
|
|
93
|
+
CREATE TABLE test_plans (
|
|
94
|
+
id TEXT PRIMARY KEY,
|
|
95
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
96
|
+
feature_id TEXT REFERENCES features(id) ON DELETE CASCADE,
|
|
97
|
+
workflow_id TEXT REFERENCES workflows(id) ON DELETE CASCADE,
|
|
98
|
+
module_id TEXT REFERENCES modules(id) ON DELETE CASCADE,
|
|
99
|
+
name TEXT NOT NULL,
|
|
100
|
+
strategy TEXT NOT NULL,
|
|
101
|
+
-- What running it looks like, so someone else can run it.
|
|
102
|
+
how_to_run TEXT,
|
|
103
|
+
-- What counts as passing, in terms a person can check.
|
|
104
|
+
passing_condition TEXT,
|
|
105
|
+
status TEXT NOT NULL DEFAULT 'draft'
|
|
106
|
+
CHECK (status IN ('draft', 'accepted', 'superseded')),
|
|
107
|
+
created_at TEXT NOT NULL,
|
|
108
|
+
updated_at TEXT NOT NULL,
|
|
109
|
+
version INTEGER NOT NULL DEFAULT 1
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
-- The individual checks a plan is made of.
|
|
113
|
+
CREATE TABLE test_plan_cases (
|
|
114
|
+
id TEXT PRIMARY KEY,
|
|
115
|
+
test_plan_id TEXT NOT NULL REFERENCES test_plans(id) ON DELETE CASCADE,
|
|
116
|
+
name TEXT NOT NULL,
|
|
117
|
+
kind TEXT NOT NULL DEFAULT 'manual_check',
|
|
118
|
+
-- What this case proves. A case that names no expectation proves nothing.
|
|
119
|
+
expectation TEXT NOT NULL,
|
|
120
|
+
-- A command that runs it, when one exists. Null is honest for a check a
|
|
121
|
+
-- person performs, and matches how verification_evidence treats the same
|
|
122
|
+
-- question.
|
|
123
|
+
command TEXT,
|
|
124
|
+
sequence INTEGER NOT NULL DEFAULT 0
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
-- A logical API boundary.
|
|
128
|
+
--
|
|
129
|
+
-- Section 6.1 defines an API Service as the boundary and an API Operation as a
|
|
130
|
+
-- concrete endpoint within one. Only operations were stored, so every operation
|
|
131
|
+
-- was loose rather than grouped under the thing that owns it.
|
|
132
|
+
CREATE TABLE api_services (
|
|
133
|
+
id TEXT PRIMARY KEY,
|
|
134
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
135
|
+
module_id TEXT REFERENCES modules(id) ON DELETE SET NULL,
|
|
136
|
+
name TEXT NOT NULL,
|
|
137
|
+
purpose TEXT,
|
|
138
|
+
style TEXT NOT NULL DEFAULT 'rest'
|
|
139
|
+
CHECK (style IN ('rest', 'graphql', 'rpc', 'events', 'local-only')),
|
|
140
|
+
base_path TEXT,
|
|
141
|
+
auth_requirement TEXT,
|
|
142
|
+
versioning TEXT,
|
|
143
|
+
status TEXT NOT NULL DEFAULT 'specified',
|
|
144
|
+
sequence INTEGER NOT NULL DEFAULT 0,
|
|
145
|
+
created_at TEXT NOT NULL,
|
|
146
|
+
updated_at TEXT NOT NULL,
|
|
147
|
+
version INTEGER NOT NULL DEFAULT 1
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
-- Operations belong to the boundary that exposes them. Nullable, because an
|
|
151
|
+
-- operation recorded before its service is still worth having.
|
|
152
|
+
ALTER TABLE api_operations ADD COLUMN api_service_id TEXT REFERENCES api_services(id) ON DELETE SET NULL;
|
|
153
|
+
|
|
154
|
+
-- A change is a historical claim about what moved and when. Revising one
|
|
155
|
+
-- rewrites the audit trail that 14.2 requires be preserved, so the same
|
|
156
|
+
-- append-only rule that guards activity events guards these.
|
|
157
|
+
CREATE TRIGGER changes_no_update BEFORE UPDATE ON changes
|
|
158
|
+
BEGIN SELECT RAISE(ABORT, 'E_APPEND_ONLY'); END;
|
|
159
|
+
CREATE TRIGGER changes_no_delete BEFORE DELETE ON changes
|
|
160
|
+
BEGIN SELECT RAISE(ABORT, 'E_APPEND_ONLY'); END;
|
|
161
|
+
|
|
162
|
+
CREATE INDEX IF NOT EXISTS idx_changes_project ON changes (project_id, created_at);
|
|
163
|
+
CREATE INDEX IF NOT EXISTS idx_change_targets_target ON change_targets (target_type, target_id);
|
|
164
|
+
CREATE INDEX IF NOT EXISTS idx_assumptions_status ON assumptions (project_id, status);
|
|
165
|
+
CREATE INDEX IF NOT EXISTS idx_test_plans_feature ON test_plans (feature_id);
|
|
166
|
+
CREATE INDEX IF NOT EXISTS idx_api_operations_service ON api_operations (api_service_id);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
-- A document whose record no longer exists.
|
|
2
|
+
--
|
|
3
|
+
-- docs generate already noticed these and skipped them, which left them in the
|
|
4
|
+
-- table marked generated at whatever revision they were last written. Freshness
|
|
5
|
+
-- then counted them behind forever and no later run could clear it: five
|
|
6
|
+
-- documents from an earlier schema sat at revision 681 while the documentation
|
|
7
|
+
-- check confirmed all 295 files matched the database. Two checks disagreeing
|
|
8
|
+
-- about the same files is worse than either being wrong.
|
|
9
|
+
--
|
|
10
|
+
-- retired says what is true. The row stays queryable so what was once
|
|
11
|
+
-- documented is still answerable, and freshness stops counting it as work
|
|
12
|
+
-- outstanding, because a document for a deleted record is not behind. It is
|
|
13
|
+
-- finished with.
|
|
14
|
+
--
|
|
15
|
+
-- SQLite cannot alter a CHECK constraint, so the table is rebuilt. Columns are
|
|
16
|
+
-- listed explicitly rather than copied with a wildcard, because a silent column
|
|
17
|
+
-- mismatch here would lose documentation state.
|
|
18
|
+
|
|
19
|
+
CREATE TABLE documents_next (
|
|
20
|
+
id TEXT PRIMARY KEY,
|
|
21
|
+
project_id TEXT NOT NULL,
|
|
22
|
+
kind TEXT NOT NULL,
|
|
23
|
+
scope_type TEXT NOT NULL,
|
|
24
|
+
scope_id TEXT,
|
|
25
|
+
path TEXT NOT NULL,
|
|
26
|
+
template TEXT,
|
|
27
|
+
database_revision INTEGER NOT NULL DEFAULT 0,
|
|
28
|
+
generated_body TEXT,
|
|
29
|
+
generated_hash TEXT,
|
|
30
|
+
manual_hash TEXT,
|
|
31
|
+
sync_status TEXT NOT NULL DEFAULT 'generated'
|
|
32
|
+
CHECK (sync_status IN ('generated', 'manual_edit_pending', 'accepted',
|
|
33
|
+
'rejected', 'missing', 'retired')),
|
|
34
|
+
generated_at TEXT,
|
|
35
|
+
regeneration_mode TEXT NOT NULL DEFAULT 'authored_projection',
|
|
36
|
+
source_fingerprint TEXT,
|
|
37
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
38
|
+
UNIQUE (project_id, path)
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
INSERT INTO documents_next (
|
|
42
|
+
id, project_id, kind, scope_type, scope_id, path, template, database_revision,
|
|
43
|
+
generated_body, generated_hash, manual_hash, sync_status, generated_at,
|
|
44
|
+
regeneration_mode, source_fingerprint)
|
|
45
|
+
SELECT
|
|
46
|
+
id, project_id, kind, scope_type, scope_id, path, template, database_revision,
|
|
47
|
+
generated_body, generated_hash, manual_hash, sync_status, generated_at,
|
|
48
|
+
regeneration_mode, source_fingerprint
|
|
49
|
+
FROM documents;
|
|
50
|
+
|
|
51
|
+
DROP TABLE documents;
|
|
52
|
+
ALTER TABLE documents_next RENAME TO documents;
|
|
53
|
+
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_documents_sync ON documents (sync_status);
|