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,154 @@
|
|
|
1
|
+
// Task categories as data.
|
|
2
|
+
//
|
|
3
|
+
// The seeded set is a starting vocabulary, not a closed list: brief section 7.3
|
|
4
|
+
// says a project may add its own, and a category nobody can add is a constant
|
|
5
|
+
// wearing a table's clothes.
|
|
6
|
+
//
|
|
7
|
+
// Nothing here deletes. A category names work already filed under it, so
|
|
8
|
+
// removing the row would quietly rewrite that history; retiring keeps the name
|
|
9
|
+
// readable while taking it out of the pickable list.
|
|
10
|
+
|
|
11
|
+
import { mutate, query, create, recordActivity, currentProject, DbError } from "../db/store.mjs";
|
|
12
|
+
import { slugify } from "../model/ids.mjs";
|
|
13
|
+
|
|
14
|
+
export const E = {
|
|
15
|
+
DUPLICATE: "E_CATEGORY_EXISTS",
|
|
16
|
+
NOT_FOUND: "E_CATEGORY_NOT_FOUND",
|
|
17
|
+
SYSTEM: "E_CATEGORY_IS_SYSTEM",
|
|
18
|
+
IN_USE: "E_CATEGORY_IN_USE",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const norm = (name) => String(name ?? "").trim();
|
|
22
|
+
|
|
23
|
+
/** Every category, with how many tasks currently carry it. */
|
|
24
|
+
export async function listCategories(root, { includeRetired = true } = {}) {
|
|
25
|
+
return query(root, async (db) => {
|
|
26
|
+
const project = await currentProject(db);
|
|
27
|
+
if (!project) return [];
|
|
28
|
+
const rows = await db.all(
|
|
29
|
+
`SELECT c.*, (SELECT count(*) FROM tasks t WHERE t.category_id = c.id) AS task_count
|
|
30
|
+
FROM task_categories c
|
|
31
|
+
WHERE c.project_id = ?${includeRetired ? "" : " AND c.active = 1"}
|
|
32
|
+
ORDER BY c.active DESC, c.sequence, c.name`,
|
|
33
|
+
project.id,
|
|
34
|
+
);
|
|
35
|
+
return rows;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function createCategory(root, { name, description = null, actor = "superdev" } = {}) {
|
|
40
|
+
const clean = norm(name);
|
|
41
|
+
if (!clean) {
|
|
42
|
+
throw new DbError("E_INVALID", "A category needs a name. Say what kind of work it describes.");
|
|
43
|
+
}
|
|
44
|
+
return mutate(root, async (db) => {
|
|
45
|
+
const project = await currentProject(db);
|
|
46
|
+
if (!project) throw new DbError("E_NOT_FOUND", "This directory has no Superdev project yet. Run superdev init first.");
|
|
47
|
+
|
|
48
|
+
const clash = await db.get(
|
|
49
|
+
"SELECT id, active FROM task_categories WHERE project_id = ? AND lower(name) = lower(?)",
|
|
50
|
+
project.id, clean,
|
|
51
|
+
);
|
|
52
|
+
if (clash) {
|
|
53
|
+
throw new DbError(
|
|
54
|
+
E.DUPLICATE,
|
|
55
|
+
clash.active
|
|
56
|
+
? `This project already has a category called ${clean}.`
|
|
57
|
+
: `This project has a retired category called ${clean}. Restore it rather than creating a second one.`,
|
|
58
|
+
{ categoryId: clash.id },
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const next = (await db.value(
|
|
63
|
+
"SELECT max(sequence) FROM task_categories WHERE project_id = ?", project.id,
|
|
64
|
+
)) ?? -1;
|
|
65
|
+
|
|
66
|
+
return create(db, "task_category", {
|
|
67
|
+
project_id: project.id,
|
|
68
|
+
name: clean,
|
|
69
|
+
description: description ? String(description).trim() : null,
|
|
70
|
+
color_token: `category-${slugify(clean)}`,
|
|
71
|
+
// A category the project added is not a system one, so it can be renamed
|
|
72
|
+
// and retired freely.
|
|
73
|
+
system: 0,
|
|
74
|
+
active: 1,
|
|
75
|
+
sequence: next + 1,
|
|
76
|
+
}, {
|
|
77
|
+
projectId: project.id,
|
|
78
|
+
actor,
|
|
79
|
+
activitySummary: `Added task category ${clean}`,
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function updateCategory(root, categoryId, { name, description, actor = "superdev" } = {}) {
|
|
85
|
+
return mutate(root, async (db) => {
|
|
86
|
+
const row = await db.get("SELECT * FROM task_categories WHERE id = ?", categoryId);
|
|
87
|
+
if (!row) throw new DbError(E.NOT_FOUND, `There is no category ${categoryId}.`);
|
|
88
|
+
|
|
89
|
+
const values = {};
|
|
90
|
+
if (name !== undefined && name !== null && norm(name) && norm(name) !== row.name) {
|
|
91
|
+
if (row.system) {
|
|
92
|
+
throw new DbError(
|
|
93
|
+
E.SYSTEM,
|
|
94
|
+
`${row.name} is one of the categories Superdev seeds, so renaming it would make this project's vocabulary disagree with every other one. Add your own category instead.`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const clash = await db.get(
|
|
98
|
+
"SELECT id FROM task_categories WHERE project_id = ? AND lower(name) = lower(?) AND id <> ?",
|
|
99
|
+
row.project_id, norm(name), categoryId,
|
|
100
|
+
);
|
|
101
|
+
if (clash) throw new DbError(E.DUPLICATE, `This project already has a category called ${norm(name)}.`);
|
|
102
|
+
values.name = norm(name);
|
|
103
|
+
values.color_token = `category-${slugify(norm(name))}`;
|
|
104
|
+
}
|
|
105
|
+
// A description is editable on any category, including a seeded one: saying
|
|
106
|
+
// what a category means in this project's words is the point.
|
|
107
|
+
if (description !== undefined) {
|
|
108
|
+
values.description = description === null ? null : String(description).trim() || null;
|
|
109
|
+
}
|
|
110
|
+
if (!Object.keys(values).length) return row;
|
|
111
|
+
|
|
112
|
+
// task_categories carries no version column, so the optimistic path does not
|
|
113
|
+
// apply here. A category is a short label owned by one project; the write is
|
|
114
|
+
// still inside this transaction and still records its activity.
|
|
115
|
+
const columns = Object.keys(values);
|
|
116
|
+
await db.run(
|
|
117
|
+
`UPDATE task_categories SET ${columns.map((c) => `${c} = ?`).join(", ")} WHERE id = ?`,
|
|
118
|
+
...columns.map((c) => values[c]), categoryId,
|
|
119
|
+
);
|
|
120
|
+
await recordActivity(db, row.project_id, {
|
|
121
|
+
type: "specification_changed",
|
|
122
|
+
actor,
|
|
123
|
+
summary: `Renamed task category ${row.name} to ${values.name ?? row.name}`,
|
|
124
|
+
metadata: { categoryId, changed: columns },
|
|
125
|
+
});
|
|
126
|
+
return db.get("SELECT * FROM task_categories WHERE id = ?", categoryId);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Retire or restore. Retiring takes a category out of the pickable list and
|
|
132
|
+
* leaves every task that already carries it alone, which is why it is a status
|
|
133
|
+
* change rather than a delete.
|
|
134
|
+
*/
|
|
135
|
+
export async function setCategoryActive(root, categoryId, active, actor = "superdev") {
|
|
136
|
+
return mutate(root, async (db) => {
|
|
137
|
+
const row = await db.get("SELECT * FROM task_categories WHERE id = ?", categoryId);
|
|
138
|
+
if (!row) throw new DbError(E.NOT_FOUND, `There is no category ${categoryId}.`);
|
|
139
|
+
if (Boolean(row.active) === Boolean(active)) return row;
|
|
140
|
+
|
|
141
|
+
const inUse = await db.value("SELECT count(*) FROM tasks WHERE category_id = ?", categoryId);
|
|
142
|
+
await db.run("UPDATE task_categories SET active = ? WHERE id = ?", active ? 1 : 0, categoryId);
|
|
143
|
+
|
|
144
|
+
await recordActivity(db, row.project_id, {
|
|
145
|
+
type: "specification_changed",
|
|
146
|
+
actor,
|
|
147
|
+
summary: active
|
|
148
|
+
? `Restored task category ${row.name}`
|
|
149
|
+
: `Retired task category ${row.name}${inUse ? `, still carried by ${inUse} task(s)` : ""}`,
|
|
150
|
+
metadata: { categoryId, active: Boolean(active), taskCount: inUse },
|
|
151
|
+
});
|
|
152
|
+
return db.get("SELECT * FROM task_categories WHERE id = ?", categoryId);
|
|
153
|
+
});
|
|
154
|
+
}
|