create-claude-cabinet 0.36.0 → 0.38.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/lib/cli.js +6 -2
- package/lib/engagement-setup.js +119 -11
- package/package.json +1 -1
- package/templates/cabinet/qa-dimensions-template.yaml +103 -0
- package/templates/engagement/__tests__/engagement.test.mjs +334 -29
- package/templates/engagement/__tests__/pibdb-adapter.test.mjs +19 -0
- package/templates/engagement/app-guide-template.md +82 -0
- package/templates/engagement/engagement-schema.md +475 -321
- package/templates/engagement/engagement.mjs +74 -18
- package/templates/engagement/pib-db-patches/pib-db-lib.mjs +91 -28
- package/templates/engagement/pib-db-patches/pib-db-schema.sql +3 -0
- package/templates/engagement/pibdb-adapter.mjs +9 -0
- package/templates/engagement/sql-constants.mjs +27 -0
- package/templates/scripts/pib-db-lib.mjs +22 -5
- package/templates/scripts/qa-dimensions-validator.cjs +102 -0
- package/templates/skills/cc-upgrade/SKILL.md +18 -0
- package/templates/skills/checklist-discover/SKILL.md +264 -0
- package/templates/skills/collab-client/SKILL.md +188 -0
- package/templates/skills/collab-consultant/SKILL.md +219 -0
- package/templates/skills/debrief/SKILL.md +13 -2
- package/templates/skills/debrief/phases/checklist-feedback.md +116 -0
- package/templates/skills/engagement/SKILL.md +3 -238
- package/templates/skills/engagement-add/SKILL.md +2 -103
- package/templates/skills/engagement-create/SKILL.md +2 -216
- package/templates/skills/engagement-edit/SKILL.md +2 -115
- package/templates/skills/engagement-help/SKILL.md +5 -174
- package/templates/skills/engagement-message/SKILL.md +3 -75
- package/templates/skills/engagement-progress/SKILL.md +3 -51
- package/templates/skills/engagement-status/SKILL.md +3 -125
- package/templates/skills/engagement-sync/SKILL.md +2 -451
- package/templates/skills/execute/SKILL.md +14 -0
- package/templates/skills/execute/phases/post-impl-checklist.md +137 -0
- package/templates/skills/guide/SKILL.md +98 -0
- package/templates/skills/orient/phases/checklist-status.md +42 -0
- package/templates/skills/setup-accounts/SKILL.md +502 -0
- package/templates/skills/validate/phases/validators.md +12 -0
package/lib/cli.js
CHANGED
|
@@ -486,7 +486,7 @@ const MODULES = {
|
|
|
486
486
|
mandatory: false,
|
|
487
487
|
default: true,
|
|
488
488
|
lean: true,
|
|
489
|
-
templates: ['skills/plan', 'skills/execute', 'skills/generate-plan-groups', 'skills/execute-group', 'workflows/execute-group-implement.js', 'workflows/execute-group-complete.js', 'skills/investigate', 'cabinet/checkpoint-protocol.md'],
|
|
489
|
+
templates: ['skills/plan', 'skills/execute', 'skills/execute/phases/post-impl-checklist.md', 'skills/debrief/phases/checklist-feedback.md', 'skills/checklist-discover', 'skills/generate-plan-groups', 'skills/execute-group', 'workflows/execute-group-implement.js', 'workflows/execute-group-complete.js', 'skills/investigate', 'cabinet/checkpoint-protocol.md', 'cabinet/qa-dimensions-template.yaml', 'scripts/qa-dimensions-validator.cjs', 'skills/orient/phases/checklist-status.md'],
|
|
490
490
|
},
|
|
491
491
|
'compliance': {
|
|
492
492
|
name: 'Compliance Stack (rules + enforcement)',
|
|
@@ -595,13 +595,15 @@ const MODULES = {
|
|
|
595
595
|
},
|
|
596
596
|
engagement: {
|
|
597
597
|
name: 'Engagement management (with secure credential handoff)',
|
|
598
|
-
description: 'Ongoing client-engagement management built on pib-db: per-recipient packets (rendered projections of the work backlog), role-gated billing, client feedback flowing back as events, and secure credential handoff (encrypted capture via OS dialog, pluggable email/MCP/file transport).
|
|
598
|
+
description: 'Ongoing client-engagement management built on pib-db: per-recipient packets (rendered projections of the work backlog), role-gated billing, client feedback flowing back as events, and secure credential handoff (encrypted capture via OS dialog, pluggable email/MCP/file transport). Three primary skills across consultant and client sides, plus redirect stubs. Requires work-tracking (the pib-db adapter is the engine\'s data source).',
|
|
599
599
|
mandatory: false,
|
|
600
600
|
default: false,
|
|
601
601
|
lean: false,
|
|
602
602
|
requires: ['work-tracking'],
|
|
603
603
|
postInstall: 'engagement-setup',
|
|
604
604
|
templates: [
|
|
605
|
+
'skills/collab-client',
|
|
606
|
+
'skills/collab-consultant',
|
|
605
607
|
'skills/engagement',
|
|
606
608
|
'skills/engagement-progress',
|
|
607
609
|
'skills/engagement-help',
|
|
@@ -611,6 +613,8 @@ const MODULES = {
|
|
|
611
613
|
'skills/engagement-add',
|
|
612
614
|
'skills/engagement-status',
|
|
613
615
|
'skills/engagement-sync',
|
|
616
|
+
'skills/setup-accounts',
|
|
617
|
+
'skills/guide',
|
|
614
618
|
'engagement',
|
|
615
619
|
],
|
|
616
620
|
},
|
package/lib/engagement-setup.js
CHANGED
|
@@ -5,11 +5,16 @@
|
|
|
5
5
|
* Dispatched from cli.js's postInstall pipeline. Two responsibilities:
|
|
6
6
|
*
|
|
7
7
|
* 1. FILE OVERLAY — copy the engagement-inclusive pib-db files over the
|
|
8
|
-
* base versions.
|
|
9
|
-
* the installed file
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* base versions. For pib-db-lib.mjs, the decision is marker-aware:
|
|
9
|
+
* we check whether the installed file already contains engagement code
|
|
10
|
+
* (not just its SCHEMA_VERSION number). This handles three cases:
|
|
11
|
+
* a. Installed file has engagement code + version >= patch → skip
|
|
12
|
+
* b. Installed file lacks engagement code + version <= patch → copy
|
|
13
|
+
* c. Installed file lacks engagement code + version > patch → BASE
|
|
14
|
+
* AHEAD: the base work-tracking module advanced past the patch
|
|
15
|
+
* without a coordinated engagement patch bump. Copying stale
|
|
16
|
+
* patch code over a newer base would drop base migrations.
|
|
17
|
+
* Emit a warning and skip both overlay and schema-ensure.
|
|
13
18
|
*
|
|
14
19
|
* 2. SCHEMA ENSURE — after the overlay, open pib.db and call migrate()
|
|
15
20
|
* so existing DBs advance to the patch's schema version. Also runs an
|
|
@@ -18,8 +23,19 @@
|
|
|
18
23
|
* engagement — the v5 migration entry is gated out, so this direct
|
|
19
24
|
* exec is the only path to creating the table).
|
|
20
25
|
*
|
|
21
|
-
*
|
|
22
|
-
* The engagement patch
|
|
26
|
+
* SCHEMA VERSIONING COORDINATION RULES:
|
|
27
|
+
* - The engagement patch's SCHEMA_VERSION must always be >= the base
|
|
28
|
+
* work-tracking SCHEMA_VERSION (the patch is a superset).
|
|
29
|
+
* - When base advances, the patch must advance in the same CC release.
|
|
30
|
+
* - Migrations shared by both base and patch use column-existence
|
|
31
|
+
* checks or IF NOT EXISTS to be idempotent.
|
|
32
|
+
* - A base-ahead state (base version > patch version) is an error
|
|
33
|
+
* indicating an uncoordinated upgrade. The overlay refuses to copy
|
|
34
|
+
* and skips schema-ensure to avoid mismatched lib/DB state.
|
|
35
|
+
*
|
|
36
|
+
* The base pib-db templates (owned by work-tracking) ship schema v1-v6.
|
|
37
|
+
* The engagement patch ships v1-v8 (v5=engagement_events, v6=projects.tags,
|
|
38
|
+
* v7=client-facing copy columns, v8=engagement_events.visibility).
|
|
23
39
|
*/
|
|
24
40
|
|
|
25
41
|
const fs = require('fs');
|
|
@@ -27,12 +43,17 @@ const path = require('path');
|
|
|
27
43
|
|
|
28
44
|
const FILES = ['pib-db-lib.mjs', 'pib-db-mcp-server.mjs', 'pib-db-schema.sql', 'pib-db.mjs'];
|
|
29
45
|
const VERSION_RE = /export const SCHEMA_VERSION\s*=\s*(\d+)/;
|
|
46
|
+
const ENGAGEMENT_MARKER_RE = /engagement_events/;
|
|
30
47
|
|
|
31
48
|
function parseSchemaVersion(content) {
|
|
32
49
|
const m = content.match(VERSION_RE);
|
|
33
50
|
return m ? parseInt(m[1], 10) : 0;
|
|
34
51
|
}
|
|
35
52
|
|
|
53
|
+
function hasEngagementCode(content) {
|
|
54
|
+
return ENGAGEMENT_MARKER_RE.test(content);
|
|
55
|
+
}
|
|
56
|
+
|
|
36
57
|
function setupEngagement({ dryRun, projectDir } = {}) {
|
|
37
58
|
const results = [];
|
|
38
59
|
const scriptsDir = path.join(projectDir, 'scripts');
|
|
@@ -43,7 +64,7 @@ function setupEngagement({ dryRun, projectDir } = {}) {
|
|
|
43
64
|
return { results };
|
|
44
65
|
}
|
|
45
66
|
|
|
46
|
-
// --- Step 1: File overlay (
|
|
67
|
+
// --- Step 1: File overlay (marker-aware for pib-db-lib.mjs) ---
|
|
47
68
|
|
|
48
69
|
const patchLibPath = path.join(patchDir, 'pib-db-lib.mjs');
|
|
49
70
|
let patchVersion = 0;
|
|
@@ -52,6 +73,7 @@ function setupEngagement({ dryRun, projectDir } = {}) {
|
|
|
52
73
|
}
|
|
53
74
|
|
|
54
75
|
let filesUpdated = false;
|
|
76
|
+
let baseAhead = false;
|
|
55
77
|
for (const file of FILES) {
|
|
56
78
|
const target = path.join(scriptsDir, file);
|
|
57
79
|
const source = path.join(patchDir, file);
|
|
@@ -67,9 +89,22 @@ function setupEngagement({ dryRun, projectDir } = {}) {
|
|
|
67
89
|
}
|
|
68
90
|
|
|
69
91
|
if (file === 'pib-db-lib.mjs') {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
92
|
+
const installedContent = fs.readFileSync(target, 'utf8');
|
|
93
|
+
const installedVersion = parseSchemaVersion(installedContent);
|
|
94
|
+
const isEngagementInclusive = hasEngagementCode(installedContent);
|
|
95
|
+
|
|
96
|
+
if (isEngagementInclusive && installedVersion >= patchVersion) {
|
|
97
|
+
results.push(`${file}: engagement-inclusive v${installedVersion} >= patch v${patchVersion} — skipped`);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!isEngagementInclusive && installedVersion > patchVersion) {
|
|
102
|
+
baseAhead = true;
|
|
103
|
+
results.push(
|
|
104
|
+
`${file}: BASE AHEAD — installed base v${installedVersion} > patch v${patchVersion}. ` +
|
|
105
|
+
`The engagement patch must be updated to match. Overlay skipped to avoid dropping base migrations. ` +
|
|
106
|
+
`Fix: bump the engagement patch SCHEMA_VERSION to >= ${installedVersion} in the same CC release.`
|
|
107
|
+
);
|
|
73
108
|
continue;
|
|
74
109
|
}
|
|
75
110
|
} else {
|
|
@@ -89,6 +124,13 @@ function setupEngagement({ dryRun, projectDir } = {}) {
|
|
|
89
124
|
}
|
|
90
125
|
|
|
91
126
|
// --- Step 2: Schema ensure (migrate + idempotent engagement_events) ---
|
|
127
|
+
// Skipped entirely when base-ahead is detected — running migrations
|
|
128
|
+
// against a mismatched library/DB pair would under-migrate the DB.
|
|
129
|
+
|
|
130
|
+
if (baseAhead) {
|
|
131
|
+
results.push('schema-ensure: skipped — base-ahead state detected (see overlay warning above)');
|
|
132
|
+
return { results };
|
|
133
|
+
}
|
|
92
134
|
|
|
93
135
|
const dbPath = path.join(projectDir, 'pib.db');
|
|
94
136
|
if (!dryRun && fs.existsSync(dbPath) && fs.existsSync(path.join(scriptsDir, 'pib-db-lib.mjs'))) {
|
|
@@ -122,6 +164,12 @@ function setupEngagement({ dryRun, projectDir } = {}) {
|
|
|
122
164
|
// later adds engagement. Their v5 migration entry (engagement_events)
|
|
123
165
|
// is gated out by user_version, and the execSync migrate above won't
|
|
124
166
|
// create it either. This direct exec is the only path.
|
|
167
|
+
//
|
|
168
|
+
// SOURCE OF TRUTH: templates/engagement/sql-constants.mjs
|
|
169
|
+
// This inline copy exists because engagement-setup.js is CJS and
|
|
170
|
+
// can't import() ESM synchronously. The drift-guard test
|
|
171
|
+
// (test/pib-db-engagement/sql-constants-drift.test.js) verifies
|
|
172
|
+
// this stays in sync with sql-constants.mjs.
|
|
125
173
|
try {
|
|
126
174
|
db.exec(`CREATE TABLE IF NOT EXISTS engagement_events (
|
|
127
175
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -133,6 +181,7 @@ function setupEngagement({ dryRun, projectDir } = {}) {
|
|
|
133
181
|
author TEXT NOT NULL,
|
|
134
182
|
verdict TEXT CHECK(verdict IS NULL OR verdict IN ('approve','object','comment','none')),
|
|
135
183
|
body TEXT CHECK(body IS NULL OR length(body) <= 10000),
|
|
184
|
+
visibility TEXT NOT NULL DEFAULT 'internal' CHECK(visibility IN ('client','internal')),
|
|
136
185
|
addressed INTEGER NOT NULL DEFAULT 0 CHECK(addressed IN (0,1)),
|
|
137
186
|
created_at TEXT NOT NULL CHECK(created_at GLOB '????-??-??T*'),
|
|
138
187
|
CHECK(kind NOT IN ('client_feedback','approval')
|
|
@@ -141,10 +190,69 @@ function setupEngagement({ dryRun, projectDir } = {}) {
|
|
|
141
190
|
db.exec("CREATE INDEX IF NOT EXISTS idx_engagement_events_eng ON engagement_events(engagement, created_at DESC)");
|
|
142
191
|
db.exec("CREATE INDEX IF NOT EXISTS idx_engagement_events_tgt ON engagement_events(target_fid, created_at DESC)");
|
|
143
192
|
db.exec("CREATE INDEX IF NOT EXISTS idx_engagement_events_dedup ON engagement_events(packet_id, target_fid, verdict)");
|
|
193
|
+
// Defensive idempotent ALTER: an engagement_events table created by a
|
|
194
|
+
// prior install (before the visibility column existed) won't get the
|
|
195
|
+
// column from CREATE IF NOT EXISTS. Add it here; swallow "duplicate
|
|
196
|
+
// column" when it's already present.
|
|
197
|
+
try {
|
|
198
|
+
db.exec("ALTER TABLE engagement_events ADD COLUMN visibility TEXT NOT NULL DEFAULT 'internal' CHECK(visibility IN ('client','internal'))");
|
|
199
|
+
} catch (e) {
|
|
200
|
+
if (!/duplicate column/i.test(e.message || '')) throw e;
|
|
201
|
+
}
|
|
144
202
|
results.push('schema-ensure: engagement_events table ensured (idempotent)');
|
|
145
203
|
} catch (e) {
|
|
146
204
|
results.push(`schema-ensure: engagement_events ensure failed — ${e.message}`);
|
|
147
205
|
}
|
|
206
|
+
|
|
207
|
+
// Data migration — extract client-facing copy from notes into columns.
|
|
208
|
+
// Idempotent: skips rows where any client column is already populated.
|
|
209
|
+
// Uses synchronous DB operations (better-sqlite3) so no async needed.
|
|
210
|
+
try {
|
|
211
|
+
const hasClientCols = db.prepare("PRAGMA table_info(actions)").all()
|
|
212
|
+
.some(c => c.name === 'client_title');
|
|
213
|
+
if (hasClientCols) {
|
|
214
|
+
const actionRows = db.prepare(
|
|
215
|
+
"SELECT fid, notes FROM actions WHERE notes LIKE '%client-facing%' AND client_title IS NULL AND client_body IS NULL AND client_generated_at IS NULL"
|
|
216
|
+
).all();
|
|
217
|
+
const projRows = db.prepare(
|
|
218
|
+
"SELECT fid, notes FROM projects WHERE notes LIKE '%client-facing%' AND client_title IS NULL AND client_body IS NULL AND client_generated_at IS NULL"
|
|
219
|
+
).all();
|
|
220
|
+
|
|
221
|
+
const copyRe = /<!--\s*client-facing\s*\n([\s\S]*?)-->/;
|
|
222
|
+
const genRe = /<!--\s*cc-generated:(\S+)\s+status:(\S+)\s*-->/;
|
|
223
|
+
const updateA = db.prepare("UPDATE actions SET client_title = ?, client_body = ?, client_generated_at = ?, client_generated_status = ? WHERE fid = ?");
|
|
224
|
+
const updateP = db.prepare("UPDATE projects SET client_title = ?, client_body = ?, client_generated_at = ?, client_generated_status = ? WHERE fid = ?");
|
|
225
|
+
|
|
226
|
+
let migrated = 0;
|
|
227
|
+
for (const { fid, notes } of [...actionRows, ...projRows]) {
|
|
228
|
+
if (!notes) continue;
|
|
229
|
+
const copyMatch = notes.match(copyRe);
|
|
230
|
+
const genMatch = notes.match(genRe);
|
|
231
|
+
if (!copyMatch && !genMatch) continue;
|
|
232
|
+
|
|
233
|
+
let title = null, body = null, genAt = null, genStatus = null;
|
|
234
|
+
if (copyMatch) {
|
|
235
|
+
const lines = copyMatch[1].split('\n').map(l => l.trim()).filter(Boolean);
|
|
236
|
+
title = lines[0] || null;
|
|
237
|
+
body = lines.slice(1).join('\n').trim() || null;
|
|
238
|
+
}
|
|
239
|
+
if (genMatch) {
|
|
240
|
+
genAt = genMatch[1] || null;
|
|
241
|
+
genStatus = genMatch[2] || null;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const stmt = actionRows.some(r => r.fid === fid) ? updateA : updateP;
|
|
245
|
+
stmt.run(title, body, genAt, genStatus, fid);
|
|
246
|
+
migrated++;
|
|
247
|
+
}
|
|
248
|
+
if (migrated > 0) {
|
|
249
|
+
results.push(`data-migration: migrated client-facing copy for ${migrated} row(s)`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
} catch (e) {
|
|
253
|
+
results.push(`data-migration: client copy migration failed — ${e.message}`);
|
|
254
|
+
}
|
|
255
|
+
|
|
148
256
|
db.close();
|
|
149
257
|
} catch (e) {
|
|
150
258
|
if (/Cannot find module|MODULE_NOT_FOUND/.test(e.message || '')) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Change-Impact QA Dimensions — starter template.
|
|
2
|
+
#
|
|
3
|
+
# To ACTIVATE the change-impact checklist, copy this file to:
|
|
4
|
+
# .claude/cabinet/qa-dimensions.yaml
|
|
5
|
+
# and customize the dimensions for your project. The /execute
|
|
6
|
+
# post-impl-checklist phase looks for `qa-dimensions.yaml` (no
|
|
7
|
+
# `-template` suffix) and stays silent until that file exists.
|
|
8
|
+
#
|
|
9
|
+
# How it works: after implementation, the phase reads the git diff,
|
|
10
|
+
# matches each changed file against every dimension's `paths` globs,
|
|
11
|
+
# and surfaces the matched dimensions' checks as context for the
|
|
12
|
+
# pre-commit cabinet sweep (Checkpoint 3). QA is the primary consumer.
|
|
13
|
+
#
|
|
14
|
+
# ── Schema ────────────────────────────────────────────────────────
|
|
15
|
+
# dimensions: # top-level map; keys are dimension names
|
|
16
|
+
# <dimension-name>:
|
|
17
|
+
# paths: # list of glob patterns (REQUIRED, >=1)
|
|
18
|
+
# - "glob/pattern/**"
|
|
19
|
+
# severity: high # high | moderate | info (REQUIRED)
|
|
20
|
+
# checks: # list of checks (REQUIRED, >=1)
|
|
21
|
+
# - tag: run # run | review
|
|
22
|
+
# check: "text" # what to verify
|
|
23
|
+
#
|
|
24
|
+
# ── Glob matching rules (canonical — the phase follows these) ───────
|
|
25
|
+
# * A leading "./" is stripped from both pattern and path before
|
|
26
|
+
# matching. Diff paths are repo-relative with no "./".
|
|
27
|
+
# * "*" matches within ONE path segment (no "/"). "src/api/*"
|
|
28
|
+
# matches "src/api/foo.js" but NOT "src/api/v2/foo.js".
|
|
29
|
+
# * "**" matches across segments (subtree). "src/api/**" matches
|
|
30
|
+
# "src/api/foo.js" AND "src/api/v2/foo.js".
|
|
31
|
+
# * A trailing "/" means "this directory and below": "src/api/" is
|
|
32
|
+
# treated as "src/api/**".
|
|
33
|
+
# * A bare extension glob like "*.md" is UNROOTED — it matches that
|
|
34
|
+
# extension at any depth. For root-only, use an explicit prefix:
|
|
35
|
+
# "README.md" or "docs/*.md" instead of bare "*.md".
|
|
36
|
+
#
|
|
37
|
+
# ── severity meanings ───────────────────────────────────────────────
|
|
38
|
+
# high — a miss here ships a real bug; sweep should treat as blocking
|
|
39
|
+
# moderate — worth checking; sweep treats as advisory
|
|
40
|
+
# info — reminder/nudge; never blocking
|
|
41
|
+
#
|
|
42
|
+
# The examples below are illustrative. Delete or replace them.
|
|
43
|
+
|
|
44
|
+
dimensions:
|
|
45
|
+
# ── Replace the example paths below with your project's real paths. ──
|
|
46
|
+
# The dimension *concepts* are broadly useful; the glob patterns are
|
|
47
|
+
# placeholders. Run /checklist-discover to auto-detect your project's
|
|
48
|
+
# paths and generate a tailored qa-dimensions.yaml.
|
|
49
|
+
|
|
50
|
+
data-coherence:
|
|
51
|
+
paths:
|
|
52
|
+
- "**/*schema*"
|
|
53
|
+
- "**/*migration*"
|
|
54
|
+
- "**/*.sql"
|
|
55
|
+
- "**/models/**"
|
|
56
|
+
severity: high
|
|
57
|
+
checks:
|
|
58
|
+
- tag: run
|
|
59
|
+
check: "Run schema validation if any schema or migration file changed."
|
|
60
|
+
- tag: review
|
|
61
|
+
check: "Verify referential integrity for any new foreign keys or cross-store references."
|
|
62
|
+
- tag: review
|
|
63
|
+
check: "Confirm any migration handles existing rows, not just fresh installs."
|
|
64
|
+
|
|
65
|
+
api-drift:
|
|
66
|
+
paths:
|
|
67
|
+
- "**/routes*"
|
|
68
|
+
- "**/api/**"
|
|
69
|
+
- "src/**"
|
|
70
|
+
- "**/index.mjs"
|
|
71
|
+
severity: high
|
|
72
|
+
checks:
|
|
73
|
+
- tag: run
|
|
74
|
+
check: "Grep the changed files for exported symbols; confirm the public surface is intentional."
|
|
75
|
+
- tag: review
|
|
76
|
+
check: "Check downstream consumers of any changed or removed export."
|
|
77
|
+
|
|
78
|
+
test-staleness:
|
|
79
|
+
paths:
|
|
80
|
+
- "**/test*/**"
|
|
81
|
+
- "**/*.test.*"
|
|
82
|
+
- "**/*.spec.*"
|
|
83
|
+
- "**/factories/**"
|
|
84
|
+
- "**/fixtures/**"
|
|
85
|
+
severity: high
|
|
86
|
+
checks:
|
|
87
|
+
- tag: run
|
|
88
|
+
check: "Run the test suite if any test, factory, or fixture file changed."
|
|
89
|
+
- tag: review
|
|
90
|
+
check: "If a model's validations or associations changed, verify factories still produce valid records."
|
|
91
|
+
- tag: review
|
|
92
|
+
check: "If behavior changed, check whether existing specs assert on the old behavior."
|
|
93
|
+
|
|
94
|
+
knowledge-layer:
|
|
95
|
+
paths:
|
|
96
|
+
- "**/docs/**"
|
|
97
|
+
- "**/*guide*"
|
|
98
|
+
- "**/README*"
|
|
99
|
+
- "**/CHANGELOG*"
|
|
100
|
+
severity: moderate
|
|
101
|
+
checks:
|
|
102
|
+
- tag: review
|
|
103
|
+
check: "If user-facing behavior or vocabulary changed, check whether docs or guides need updating."
|