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.
Files changed (182) hide show
  1. package/.claude-plugin/marketplace.json +33 -0
  2. package/.claude-plugin/plugin.json +21 -0
  3. package/.codex-plugin/plugin.json +27 -0
  4. package/CODE_OF_CONDUCT.md +109 -0
  5. package/CONTRIBUTING.md +205 -0
  6. package/LICENSE +202 -0
  7. package/NOTICE +11 -0
  8. package/README.md +1051 -0
  9. package/SECURITY.md +135 -0
  10. package/THIRD-PARTY-NOTICES.md +253 -0
  11. package/hooks/hooks.json +61 -0
  12. package/hooks/run.mjs +88 -0
  13. package/package.json +65 -0
  14. package/references/confidentiality.md +48 -0
  15. package/references/evidence-and-risk.md +73 -0
  16. package/references/operating-model.md +105 -0
  17. package/references/platform-capabilities.md +51 -0
  18. package/references/project-record.md +91 -0
  19. package/references/provider-contracts.md +102 -0
  20. package/scripts/doctor/doctor.mjs +539 -0
  21. package/scripts/privacy/scan-history.mjs +163 -0
  22. package/scripts/privacy/scan.mjs +368 -0
  23. package/scripts/validate/README.md +94 -0
  24. package/scripts/validate/common.mjs +149 -0
  25. package/scripts/validate/data-model.mjs +225 -0
  26. package/scripts/validate/dependencies.mjs +69 -0
  27. package/scripts/validate/docs-templates.mjs +99 -0
  28. package/scripts/validate/footprint.mjs +78 -0
  29. package/scripts/validate/imports.mjs +61 -0
  30. package/scripts/validate/manifests.mjs +173 -0
  31. package/scripts/validate/markdown.mjs +123 -0
  32. package/scripts/validate/migrations.mjs +187 -0
  33. package/scripts/validate/no-tests.mjs +136 -0
  34. package/scripts/validate/privacy.mjs +115 -0
  35. package/scripts/validate/record-links.mjs +127 -0
  36. package/scripts/validate/skill-commands.mjs +190 -0
  37. package/scripts/validate/skills.mjs +112 -0
  38. package/scripts/validate/specification.mjs +88 -0
  39. package/scripts/validate/style.mjs +78 -0
  40. package/scripts/validate/validate-all.mjs +175 -0
  41. package/skills/debug/SKILL.md +68 -0
  42. package/skills/decision/SKILL.md +99 -0
  43. package/skills/docs/SKILL.md +86 -0
  44. package/skills/docs/assets/fragments/api/events.md +14 -0
  45. package/skills/docs/assets/fragments/api/graphql.md +14 -0
  46. package/skills/docs/assets/fragments/api/local-only.md +13 -0
  47. package/skills/docs/assets/fragments/api/rest.md +13 -0
  48. package/skills/docs/assets/fragments/api/rpc.md +13 -0
  49. package/skills/docs/assets/fragments/async/event-bus.md +13 -0
  50. package/skills/docs/assets/fragments/async/none.md +11 -0
  51. package/skills/docs/assets/fragments/async/platform-jobs.md +13 -0
  52. package/skills/docs/assets/fragments/async/queue.md +13 -0
  53. package/skills/docs/assets/fragments/async/scheduler.md +13 -0
  54. package/skills/docs/assets/fragments/auth/detected-provider.md +15 -0
  55. package/skills/docs/assets/fragments/auth/neutral-base.md +14 -0
  56. package/skills/docs/assets/fragments/data/document.md +13 -0
  57. package/skills/docs/assets/fragments/data/external-saas.md +13 -0
  58. package/skills/docs/assets/fragments/data/key-value.md +13 -0
  59. package/skills/docs/assets/fragments/data/none.md +12 -0
  60. package/skills/docs/assets/fragments/data/sql-orm.md +13 -0
  61. package/skills/docs/assets/fragments/data/sql-plain.md +13 -0
  62. package/skills/docs/assets/fragments/env/conventional.md +13 -0
  63. package/skills/docs/assets/fragments/env/envx.md +13 -0
  64. package/skills/docs/assets/fragments/env/managed-platform.md +13 -0
  65. package/skills/docs/assets/fragments/env/none.md +11 -0
  66. package/skills/docs/assets/fragments/ui/api-only.md +13 -0
  67. package/skills/docs/assets/fragments/ui/cli.md +14 -0
  68. package/skills/docs/assets/fragments/ui/desktop.md +14 -0
  69. package/skills/docs/assets/fragments/ui/mobile.md +14 -0
  70. package/skills/docs/assets/fragments/ui/web.md +14 -0
  71. package/skills/docs/assets/templates/adr.md +62 -0
  72. package/skills/docs/assets/templates/api.md +30 -0
  73. package/skills/docs/assets/templates/architecture.md +52 -0
  74. package/skills/docs/assets/templates/change-impact-drift-report.md +29 -0
  75. package/skills/docs/assets/templates/compliance.md +29 -0
  76. package/skills/docs/assets/templates/data-schema.md +43 -0
  77. package/skills/docs/assets/templates/feature.md +43 -0
  78. package/skills/docs/assets/templates/foundations.md +55 -0
  79. package/skills/docs/assets/templates/jobs-webhooks.md +36 -0
  80. package/skills/docs/assets/templates/module-inventory.md +19 -0
  81. package/skills/docs/assets/templates/module.md +50 -0
  82. package/skills/docs/assets/templates/nfr.md +22 -0
  83. package/skills/docs/assets/templates/observability.md +28 -0
  84. package/skills/docs/assets/templates/pages-ui-actions.md +47 -0
  85. package/skills/docs/assets/templates/project-summary.md +44 -0
  86. package/skills/docs/assets/templates/roles-permissions.md +26 -0
  87. package/skills/docs/assets/templates/test-plan.md +23 -0
  88. package/skills/docs/assets/templates/workflow-state-machine.md +43 -0
  89. package/skills/docs/references/adr-authoring.md +24 -0
  90. package/skills/docs/references/apis-and-data.md +23 -0
  91. package/skills/docs/references/capability-fragments.md +25 -0
  92. package/skills/docs/references/change-tracking.md +62 -0
  93. package/skills/docs/references/diagrams.md +31 -0
  94. package/skills/docs/references/discovery.md +59 -0
  95. package/skills/docs/references/edge-cases.md +45 -0
  96. package/skills/docs/references/foundations-modules.md +18 -0
  97. package/skills/docs/references/ingestion.md +52 -0
  98. package/skills/docs/references/initialize-adopt.md +25 -0
  99. package/skills/docs/references/module-decomposition.md +38 -0
  100. package/skills/docs/references/profiles.md +60 -0
  101. package/skills/docs/references/quality-attributes.md +27 -0
  102. package/skills/docs/references/reverse-engineer.md +21 -0
  103. package/skills/docs/references/spec-depths.md +31 -0
  104. package/skills/docs/references/summarize.md +18 -0
  105. package/skills/docs/references/surfaces-and-actions.md +24 -0
  106. package/skills/docs/references/validation.md +47 -0
  107. package/skills/docs/references/workflows-and-jobs.md +25 -0
  108. package/skills/docs/scripts/ingest.mjs +984 -0
  109. package/skills/docs/scripts/profile-detect.mjs +299 -0
  110. package/skills/docs/scripts/screen.mjs +96 -0
  111. package/skills/docs/scripts/template-lint.mjs +143 -0
  112. package/skills/docs/scripts/validate-docs.mjs +363 -0
  113. package/skills/doctor/SKILL.md +167 -0
  114. package/skills/feature/SKILL.md +132 -0
  115. package/skills/init/SKILL.md +137 -0
  116. package/skills/project/SKILL.md +261 -0
  117. package/skills/project/references/commands.md +213 -0
  118. package/skills/resume/SKILL.md +79 -0
  119. package/skills/review/SKILL.md +91 -0
  120. package/skills/status/SKILL.md +85 -0
  121. package/skills/task/SKILL.md +183 -0
  122. package/src/cli/product-map.mjs +468 -0
  123. package/src/cli/render.mjs +544 -0
  124. package/src/cli.mjs +2774 -0
  125. package/src/cloud/crypto.mjs +118 -0
  126. package/src/cloud/merge.mjs +186 -0
  127. package/src/cloud/policy.mjs +115 -0
  128. package/src/cloud/sync.mjs +512 -0
  129. package/src/cloud/transport.mjs +116 -0
  130. package/src/db/connect.mjs +189 -0
  131. package/src/db/maintenance.mjs +419 -0
  132. package/src/db/migrate.mjs +188 -0
  133. package/src/db/migrations/001_initial.sql +1024 -0
  134. package/src/db/migrations/002_docs_coverage.sql +126 -0
  135. package/src/db/migrations/003_memory_retrieval_and_integrity.sql +168 -0
  136. package/src/db/migrations/004_task_categories.sql +59 -0
  137. package/src/db/migrations/005_executable_evidence.sql +32 -0
  138. package/src/db/migrations/006_module_and_feature_boundaries.sql +27 -0
  139. package/src/db/migrations/007_drop_redundant_module_users.sql +13 -0
  140. package/src/db/migrations/008_changes_assumptions_test_plans_api_services.sql +166 -0
  141. package/src/db/migrations/009_retired_documents.sql +54 -0
  142. package/src/db/migrations/010_test_plan_evidence.sql +20 -0
  143. package/src/db/migrations/011_criterion_waiver.sql +13 -0
  144. package/src/db/migrations/012_synchronization.sql +56 -0
  145. package/src/db/store.mjs +327 -0
  146. package/src/decisions/record.mjs +167 -0
  147. package/src/docs/proposals.mjs +871 -0
  148. package/src/docs/render.mjs +1424 -0
  149. package/src/docs/templates.mjs +1281 -0
  150. package/src/features/acceptance.mjs +315 -0
  151. package/src/features/specify.mjs +248 -0
  152. package/src/init/discovery.mjs +901 -0
  153. package/src/init/index.mjs +784 -0
  154. package/src/init/questions.mjs +562 -0
  155. package/src/memory/benchmark.mjs +171 -0
  156. package/src/memory/capture.mjs +135 -0
  157. package/src/memory/consolidate.mjs +255 -0
  158. package/src/memory/index.mjs +810 -0
  159. package/src/model/ids.mjs +185 -0
  160. package/src/model/screening.mjs +150 -0
  161. package/src/model/toolkit.mjs +258 -0
  162. package/src/model/vocabulary.mjs +190 -0
  163. package/src/product/assumptions.mjs +120 -0
  164. package/src/product/changes.mjs +180 -0
  165. package/src/product/test-plans.mjs +183 -0
  166. package/src/progress/index.mjs +1364 -0
  167. package/src/runtime/harness.mjs +264 -0
  168. package/src/runtime/hooks.mjs +1021 -0
  169. package/src/runtime/identity.mjs +305 -0
  170. package/src/runtime/resume.mjs +343 -0
  171. package/src/runtime/session.mjs +679 -0
  172. package/src/runtime/version.mjs +315 -0
  173. package/src/service/assets/control-center.html +206 -0
  174. package/src/service/assets/control-center.manifest.json +7 -0
  175. package/src/service/manage.mjs +542 -0
  176. package/src/service/mutations.mjs +860 -0
  177. package/src/service/read-model.mjs +1557 -0
  178. package/src/service/server.mjs +783 -0
  179. package/src/tasks/categories.mjs +154 -0
  180. package/src/tasks/derive.mjs +977 -0
  181. package/src/tasks/lifecycle.mjs +830 -0
  182. package/src/verify/index.mjs +236 -0
@@ -0,0 +1,188 @@
1
+ // Ordered migrations. Schema changes only ever arrive as a numbered file that
2
+ // runs exactly once, in order, inside a transaction, after a backup.
3
+ // Schema push is not a workflow here.
4
+
5
+ import { readdirSync, readFileSync, existsSync, mkdirSync, rmSync } from "node:fs";
6
+ import { createHash } from "node:crypto";
7
+ import { join, dirname } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { writeRaw, read, CREATE_PRAGMAS } from "./connect.mjs";
10
+
11
+ const HERE = dirname(fileURLToPath(import.meta.url));
12
+ export const MIGRATIONS_DIR = join(HERE, "migrations");
13
+
14
+ const BOOKKEEPING = `
15
+ CREATE TABLE IF NOT EXISTS applied_migrations (
16
+ version INTEGER PRIMARY KEY,
17
+ name TEXT NOT NULL,
18
+ checksum TEXT NOT NULL,
19
+ applied_at TEXT NOT NULL
20
+ );`;
21
+
22
+ export function availableMigrations(dir = MIGRATIONS_DIR) {
23
+ if (!existsSync(dir)) return [];
24
+ return readdirSync(dir)
25
+ .filter((f) => /^\d{3}_.+\.sql$/.test(f))
26
+ .sort()
27
+ .map((file) => {
28
+ const sql = readFileSync(join(dir, file), "utf8");
29
+ return {
30
+ version: Number(file.slice(0, 3)),
31
+ name: file,
32
+ sql,
33
+ checksum: createHash("sha256").update(sql).digest("hex"),
34
+ };
35
+ });
36
+ }
37
+
38
+ /**
39
+ * Split a migration file into statements. The engine executes one statement per
40
+ * exec call, and a naive split on ";" would cut triggers in half, so BEGIN/END
41
+ * blocks are tracked.
42
+ */
43
+ export function splitStatements(sql) {
44
+ const withoutComments = sql
45
+ .split("\n")
46
+ .filter((line) => !/^\s*--/.test(line))
47
+ .join("\n");
48
+ const out = [];
49
+ let buf = "";
50
+ let depth = 0;
51
+ for (const rawLine of withoutComments.split("\n")) {
52
+ const line = rawLine;
53
+ buf += line + "\n";
54
+ if (/\bBEGIN\b/i.test(line) && /CREATE\s+TRIGGER/i.test(buf)) depth = 1;
55
+ if (depth === 1 && /\bEND\s*;/i.test(line)) {
56
+ out.push(buf.trim());
57
+ buf = "";
58
+ depth = 0;
59
+ continue;
60
+ }
61
+ if (depth === 0 && /;\s*$/.test(line.trim())) {
62
+ const stmt = buf.trim();
63
+ if (stmt.replace(/;/g, "").trim()) out.push(stmt);
64
+ buf = "";
65
+ }
66
+ }
67
+ if (buf.trim().replace(/;/g, "").trim()) out.push(buf.trim());
68
+ return out;
69
+ }
70
+
71
+ export async function currentVersion(file) {
72
+ if (!existsSync(file)) return 0;
73
+ return read(file, async (db) => {
74
+ const row = await db.get("PRAGMA user_version");
75
+ return row?.user_version ?? 0;
76
+ });
77
+ }
78
+
79
+ export async function pendingMigrations(file, dir = MIGRATIONS_DIR) {
80
+ const at = await currentVersion(file);
81
+ return availableMigrations(dir).filter((m) => m.version > at);
82
+ }
83
+
84
+ /**
85
+ * Copy the database aside before a schema change. Recovery, not a record.
86
+ *
87
+ * This must be VACUUM INTO, not copyFileSync. Under journal_mode=mvcc the rows
88
+ * live in the `superdev.db-log` sidecar until checkpoint, so copying
89
+ * `superdev.db` alone yields an 8 KB header that holds no data and that the
90
+ * engine refuses to open. VACUUM INTO writes one self-contained file under an
91
+ * exclusive lock, so it cannot tear against a writer.
92
+ */
93
+ export async function backupBeforeMigration(file, label = "migration") {
94
+ if (!existsSync(file)) return null;
95
+ const dir = join(dirname(file), "backups");
96
+ mkdirSync(dir, { recursive: true });
97
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
98
+ const target = join(dir, `${label}-${stamp}.db`);
99
+ rmSync(target, { force: true }); // VACUUM INTO refuses to write over a file
100
+ await writeRaw(file, (db) => db.exec(`VACUUM INTO '${target.replace(/'/g, "''")}'`));
101
+ return target;
102
+ }
103
+
104
+ /**
105
+ * Apply every pending migration. Returns what ran, or what would run when
106
+ * `apply` is false.
107
+ */
108
+ export async function migrate(file, { apply = false, dir = MIGRATIONS_DIR } = {}) {
109
+ const fresh = !existsSync(file);
110
+ const pending = fresh ? availableMigrations(dir) : await pendingMigrations(file, dir);
111
+ if (!pending.length) {
112
+ return { applied: [], pending: [], from: await currentVersion(file), to: await currentVersion(file), backup: null };
113
+ }
114
+ if (!apply) {
115
+ const from = fresh ? 0 : await currentVersion(file);
116
+ return {
117
+ applied: [],
118
+ pending: pending.map((m) => ({ version: m.version, name: m.name, statements: splitStatements(m.sql).length })),
119
+ from,
120
+ to: pending[pending.length - 1].version,
121
+ backup: null,
122
+ };
123
+ }
124
+
125
+ // Read where we actually started, before anything moves it. Deriving it from
126
+ // the first pending migration assumes the numbering has no gaps, so a database
127
+ // at 3 with 5 pending would report having come from 4, a version it was never
128
+ // at. The dry run above reads it; the run that actually changes the database
129
+ // has more reason to be right, not less.
130
+ const from = fresh ? 0 : await currentVersion(file);
131
+
132
+ const backup = fresh ? null : await backupBeforeMigration(file);
133
+ const applied = [];
134
+
135
+ await writeRaw(file, async (db) => {
136
+ if (fresh) for (const p of CREATE_PRAGMAS) await db.exec(p);
137
+ await db.exec(BOOKKEEPING.trim());
138
+ for (const m of pending) {
139
+ await db.exec("BEGIN IMMEDIATE");
140
+ try {
141
+ for (const stmt of splitStatements(m.sql)) await db.exec(stmt);
142
+ await db.run(
143
+ "INSERT INTO applied_migrations (version, name, checksum, applied_at) VALUES (?, ?, ?, ?)",
144
+ m.version, m.name, m.checksum, new Date().toISOString(),
145
+ );
146
+ await db.exec(`PRAGMA user_version = ${m.version}`);
147
+ await db.exec("COMMIT");
148
+ applied.push({ version: m.version, name: m.name });
149
+ } catch (err) {
150
+ await db.exec("ROLLBACK").catch(() => {});
151
+ err.message = `migration ${m.name} failed: ${err.message}`;
152
+ throw err;
153
+ }
154
+ }
155
+ });
156
+
157
+ return { applied, pending: [], from, to: applied.at(-1)?.version ?? 0, backup };
158
+ }
159
+
160
+ /** Structural report used by the migration validator and `superdev db status`. */
161
+ export async function inspect(file, dir = MIGRATIONS_DIR) {
162
+ const available = availableMigrations(dir);
163
+ const exists = existsSync(file);
164
+ const at = exists ? await currentVersion(file) : 0;
165
+ const drift = [];
166
+ if (exists) {
167
+ const rows = await read(file, async (db) => {
168
+ try {
169
+ return await db.all("SELECT version, name, checksum FROM applied_migrations ORDER BY version");
170
+ } catch {
171
+ return [];
172
+ }
173
+ });
174
+ for (const row of rows) {
175
+ const known = available.find((m) => m.version === row.version);
176
+ if (!known) drift.push({ version: row.version, problem: "applied migration is not in the migration directory" });
177
+ else if (known.checksum !== row.checksum) drift.push({ version: row.version, problem: "migration file changed after it was applied" });
178
+ }
179
+ }
180
+ return {
181
+ databaseExists: exists,
182
+ version: at,
183
+ latest: available.at(-1)?.version ?? 0,
184
+ available: available.map((m) => ({ version: m.version, name: m.name })),
185
+ pending: available.filter((m) => m.version > at).map((m) => ({ version: m.version, name: m.name })),
186
+ drift,
187
+ };
188
+ }