@dzhechkov/p-replicator 1.6.0 → 1.9.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/.dz-manifest.json +59 -23
- package/CHANGELOG.md +127 -0
- package/README.md +106 -4
- package/package.json +4 -4
- package/sbom.json +112 -22
- package/src/utils.js +2 -0
- package/templates/.claude/commands/replicate.md +57 -1
- package/templates/.claude/hooks/check-docs-complete.cjs +174 -0
- package/templates/.claude/hooks/check-growth-trace.cjs +191 -0
- package/templates/.claude/hooks/statusline.cjs +1 -1
- package/templates/.claude/rules/replicate-pipeline.md +14 -4
- package/templates/.claude/rules/skill-interface-protocol.md +9 -0
- package/templates/.claude/skills/cc-toolkit-generator-enhanced/modules/03-generate-p0.md +6 -4
- package/templates/.claude/skills/cc-toolkit-generator-enhanced/modules/08-skill-composition.md +2 -2
- package/templates/.claude/skills/cc-toolkit-generator-enhanced/references/templates/feature-lifecycle.md +2 -2
- package/templates/.claude/skills/requirements-validator/SKILL.md +52 -0
- package/templates/.claude/skills/reverse-engineering-unicorn/modules/01-intelligence.md +4 -4
- package/templates/.claude/skills/reverse-engineering-unicorn/modules/02-product-customers.md +2 -2
- package/templates/.claude/skills/reverse-engineering-unicorn/modules/025-cjm-prototype.md +9 -1
- package/templates/.claude/skills/reverse-engineering-unicorn/modules/03-market-competition.md +3 -3
- package/templates/.claude/skills/reverse-engineering-unicorn/modules/04-business-finance.md +3 -3
- package/templates/.claude/skills/reverse-engineering-unicorn/modules/05-growth-engine.md +132 -12
- package/templates/.claude/skills/reverse-engineering-unicorn/modules/06-playbook-synthesis.md +1 -1
- package/templates/.claude/skills/sparc-prd-mini/SKILL.md +9 -9
- package/tests/snapshot/baseline.json +20 -18
- package/tests/unit/check-docs-complete.test.js +249 -0
- package/tests/unit/check-growth-trace.test.js +188 -0
- package/tests/unit/growth-axes-and-compliance.test.js +169 -0
- package/tests/unit/growth-gate-conditional.test.js +122 -0
- package/tests/unit/growth-module-b2b-gate.test.js +20 -2
- package/tests/unit/growth-requirements-bridge.test.js +127 -0
- package/tests/unit/module-copy-identity.test.js +76 -0
- package/tests/unit/skill-paths-prebaked.test.js +174 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* check-growth-trace.cjs — did the M5 growth analysis survive into the Specification, or was it
|
|
6
|
+
* analysed and dropped?
|
|
7
|
+
*
|
|
8
|
+
* NOT an event hook. Like `state-update.cjs` and `check-ports.cjs`, it lives here because this
|
|
9
|
+
* directory already carries plain Node utilities; nothing registers it in settings.json. This is
|
|
10
|
+
* deliberate and load-bearing: this package's hooks are NON-BLOCKING by contract (pinned by
|
|
11
|
+
* tests/unit/hooks-project-anchored.test.js, which requires exit 0), so a hook could never refuse
|
|
12
|
+
* anything — it could only print. Invoke it:
|
|
13
|
+
*
|
|
14
|
+
* node .claude/hooks/check-growth-trace.cjs [path-to-project]
|
|
15
|
+
*
|
|
16
|
+
* Exit codes — three, and the third is the point:
|
|
17
|
+
* 0 every seed row is traced into docs/Specification.md, or rejected on the record
|
|
18
|
+
* 1 the seed table carries rows and the Specification traces none of them
|
|
19
|
+
* 2 THE CHECK DID NOT RUN — no brief, no Specification, or a seed table that would not parse
|
|
20
|
+
*
|
|
21
|
+
* A checker that answers "clean" when it could not look converts an unknown into a reassurance.
|
|
22
|
+
* An ABSENT brief means Phase 0 never ran (the --from-docs entry skips it); that is exit 2, never 0
|
|
23
|
+
* and never 1. "Phase 0 did not run" is not "nothing is missing".
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const fs = require('node:fs');
|
|
27
|
+
const path = require('node:path');
|
|
28
|
+
|
|
29
|
+
const BRIEF = path.join('docs', 'product-discovery-brief.md');
|
|
30
|
+
const SPEC = path.join('docs', 'Specification.md');
|
|
31
|
+
|
|
32
|
+
/** The exact token, case-sensitive. Not a title, not a paraphrase — the same definition the
|
|
33
|
+
* validator's prose gate uses, so the two cannot disagree about what a mention is. */
|
|
34
|
+
const ID = /\bFR-GROWTH-(\d{3})\b/g;
|
|
35
|
+
|
|
36
|
+
/** A line that refuses an obligation. Shared by mentioned() and rejected() so the two rules cannot
|
|
37
|
+
* disagree about what a refusal looks like. */
|
|
38
|
+
const REJECT_WORD = /(отклон\w*|не берём|не беремся|не берем|rejected|declined|out of scope|вне области)/i;
|
|
39
|
+
|
|
40
|
+
function say(s) { process.stdout.write(s + '\n'); }
|
|
41
|
+
|
|
42
|
+
/** Exit 2 with a reason. Never merged with "clean": not-run and not-violated are different facts. */
|
|
43
|
+
function cannotCheck(reason, hint) {
|
|
44
|
+
say('⚠️ проверка НЕ выполнена: ' + reason);
|
|
45
|
+
if (hint) say(' ' + hint);
|
|
46
|
+
process.exit(2);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Read one required file. Asks about the EXACT path — never lists a directory and matches names
|
|
51
|
+
* against the listing, because a listing answers a different question than "does this file exist"
|
|
52
|
+
* and the two diverge on case, symlinks and unicode normalisation.
|
|
53
|
+
*/
|
|
54
|
+
function readRequired(root, rel, absentReason, hint) {
|
|
55
|
+
const abs = path.join(root, rel);
|
|
56
|
+
let st;
|
|
57
|
+
try { st = fs.statSync(abs); } catch { cannotCheck(absentReason, hint); }
|
|
58
|
+
if (!st.isFile()) cannotCheck(rel + ' существует, но это не файл');
|
|
59
|
+
try { return fs.readFileSync(abs, 'utf-8'); } catch (e) {
|
|
60
|
+
cannotCheck('не читается ' + rel + ': ' + ((e && e.message) || e));
|
|
61
|
+
}
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The seed rows, as the brief records them.
|
|
67
|
+
*
|
|
68
|
+
* A row is a markdown table row whose FIRST cell is an id. The template ships an example row with
|
|
69
|
+
* a placeholder id inside the module, so a row whose requirement cell is still a bracketed
|
|
70
|
+
* placeholder is a TEMPLATE row, not a real obligation, and counting it would let an untouched
|
|
71
|
+
* template look like a filled-in one.
|
|
72
|
+
*/
|
|
73
|
+
function seedRows(brief) {
|
|
74
|
+
const rows = [];
|
|
75
|
+
for (const raw of brief.split('\n')) {
|
|
76
|
+
const line = raw.trim();
|
|
77
|
+
if (!line.startsWith('|')) continue;
|
|
78
|
+
const cells = line.split('|').map((c) => c.trim());
|
|
79
|
+
// cells[0] is '' for a leading pipe; the id lives in cells[1]
|
|
80
|
+
const m = /^FR-GROWTH-(\d{3})$/.exec(cells[1] || '');
|
|
81
|
+
if (!m) continue;
|
|
82
|
+
const requirement = cells[2] || '';
|
|
83
|
+
const isPlaceholder = /^\[.*\]$/.test(requirement) || requirement === '...' || requirement === '';
|
|
84
|
+
if (isPlaceholder) continue;
|
|
85
|
+
const status = (cells[5] || cells[4] || '').toUpperCase();
|
|
86
|
+
rows.push({ id: cells[1], speculative: status.includes('SPECULATIVE') });
|
|
87
|
+
}
|
|
88
|
+
return rows;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Ids the Specification mentions, by the same definition the validator's prose gate uses.
|
|
93
|
+
*
|
|
94
|
+
* A REJECTION LINE IS NOT A MENTION. The two rules overlap on exactly the case that matters: a line
|
|
95
|
+
* reading `FR-GROWTH-001 rejected` contains the exact token, so a naive mention rule reports the
|
|
96
|
+
* obligation as carried forward — and the reason requirement on the rejection path is never reached.
|
|
97
|
+
* MEASURED before this fix: that line exited 0. Cross-family review found the reason-check hole; the
|
|
98
|
+
* hole was one layer deeper, in which of the two rules got to answer first.
|
|
99
|
+
*/
|
|
100
|
+
function mentioned(spec) {
|
|
101
|
+
const out = new Set();
|
|
102
|
+
for (const line of spec.split('\n')) {
|
|
103
|
+
if (REJECT_WORD.test(line)) continue; // a refusal is decided by rejected(), which wants a reason
|
|
104
|
+
ID.lastIndex = 0;
|
|
105
|
+
for (let m = ID.exec(line); m !== null; m = ID.exec(line)) out.add(m[0]);
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* A row may also be REJECTED on the record instead of traced — the validator's prose gate says the
|
|
112
|
+
* same. A rejection is a line naming the id together with a rejection word AND a reason marker,
|
|
113
|
+
* because "FR-GROWTH-004 не берём" with nothing after it is indistinguishable from forgetting.
|
|
114
|
+
*/
|
|
115
|
+
function rejected(brief, spec, id) {
|
|
116
|
+
const re = new RegExp('^.*\\b' + id + '\\b.*$', 'gm');
|
|
117
|
+
for (const hay of [brief, spec]) {
|
|
118
|
+
for (const line of hay.match(re) || []) {
|
|
119
|
+
const m = REJECT_WORD.exec(line);
|
|
120
|
+
if (!m) continue;
|
|
121
|
+
// The reason must live AFTER the rejection word. Scanning the whole line was a false-clean:
|
|
122
|
+
// cross-family review found that `FR-GROWTH-001 rejected` passed, because the reason pattern
|
|
123
|
+
// included a bare hyphen and the IDENTIFIER contains two of them. MEASURED before the fix —
|
|
124
|
+
// that exact line exited 0. So: look only at the tail, and never at punctuation alone.
|
|
125
|
+
const tail = line.slice(m.index + m[0].length);
|
|
126
|
+
// A reason is WORDS, not a dash. A separator may introduce it but can never be it.
|
|
127
|
+
const hasReason = /[\p{L}\p{N}][\p{L}\p{N}\s]{6,}/u.test(tail.replace(/^[\s:—–-]+/, ''));
|
|
128
|
+
if (hasReason) return true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function main() {
|
|
135
|
+
const root = process.argv[2] || '.';
|
|
136
|
+
try { if (!fs.statSync(root).isDirectory()) cannotCheck('это не каталог: ' + root); }
|
|
137
|
+
catch { cannotCheck('путь не существует: ' + root); }
|
|
138
|
+
|
|
139
|
+
const brief = readRequired(root, BRIEF,
|
|
140
|
+
'нет файла ' + BRIEF,
|
|
141
|
+
'это значит, что Фаза 0 не запускалась (вход --from-docs её пропускает) — а НЕ что требований по росту не нужно');
|
|
142
|
+
|
|
143
|
+
const rows = seedRows(brief);
|
|
144
|
+
|
|
145
|
+
// A REUSED id makes the brief malformed, and malformed is exit 2 — never a pass. The module's own
|
|
146
|
+
// rule is that a number is never reused; when it is, two distinct obligations share one token and
|
|
147
|
+
// a SINGLE mention in the Specification marks BOTH traced. Cross-family review found this, and it
|
|
148
|
+
// is the recurring shape: coverage counted over usable ITEMS instead of per POSITION.
|
|
149
|
+
const dupes = [...new Set(rows.map((r) => r.id).filter((id, i, a) => a.indexOf(id) !== i))];
|
|
150
|
+
if (dupes.length) {
|
|
151
|
+
cannotCheck('в таблице-семени повторяются идентификаторы: ' + dupes.join(', '),
|
|
152
|
+
'номер FR-GROWTH-nnn не переиспользуется — пока дубли не разведены, одно упоминание в '
|
|
153
|
+
+ 'Specification.md зачло бы сразу два разных требования');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (!rows.length) {
|
|
157
|
+
// An empty seed is a legitimate answer ("нет"), but it is not this checker's business: there is
|
|
158
|
+
// nothing to trace. Saying "clean" here would claim a check that did not happen.
|
|
159
|
+
cannotCheck('в брифе нет ни одной заполненной строки FR-GROWTH-nnn',
|
|
160
|
+
'либо M5 не запускался, либо таблица-семя осталась шаблоном — проверять нечего');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const spec = readRequired(root, SPEC, 'нет файла ' + SPEC,
|
|
164
|
+
'без спецификации не с чем сверять — это не «всё прослежено»');
|
|
165
|
+
|
|
166
|
+
const seen = mentioned(spec);
|
|
167
|
+
const missing = rows.filter((r) => !seen.has(r.id) && !rejected(brief, spec, r.id));
|
|
168
|
+
|
|
169
|
+
if (missing.length === rows.length) {
|
|
170
|
+
say('❌ ни одно требование по росту не доехало до ' + SPEC + ':');
|
|
171
|
+
for (const r of missing) say(' • ' + r.id + (r.speculative ? ' (SPECULATIVE)' : ''));
|
|
172
|
+
say(' Разбор роста сделан и выброшен — это ровно тот класс потерь, который ловит проверка.');
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
if (missing.length) {
|
|
176
|
+
say('❌ часть требований по росту потеряна (' + missing.length + ' из ' + rows.length + '):');
|
|
177
|
+
for (const r of missing) say(' • ' + r.id + (r.speculative ? ' (SPECULATIVE)' : ''));
|
|
178
|
+
say(' Каждое надо либо перенести в ' + SPEC + ', либо отклонить С ПРИЧИНОЙ — молча уронить нельзя.');
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
say('✅ все ' + rows.length + ' требований по росту прослежены в ' + SPEC + ' либо отклонены с причиной');
|
|
182
|
+
say(' Ограничение: это доказывает, что обязательство ДОНЕСЛИ, а не что его построили.');
|
|
183
|
+
process.exit(0);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
main();
|
|
188
|
+
} catch (err) {
|
|
189
|
+
// Even an unexpected failure must not read as "clean".
|
|
190
|
+
cannotCheck('внутренняя ошибка проверки: ' + String((err && err.message) || err));
|
|
191
|
+
}
|
|
@@ -236,7 +236,7 @@ function parseExpectedToolkit() {
|
|
|
236
236
|
commandsExpected: 11,
|
|
237
237
|
agentsExpected: 4, // pre-shipped only (project agents are extra)
|
|
238
238
|
rulesExpected: 6, // pre-shipped only (project rules are extra)
|
|
239
|
-
hooksExpected:
|
|
239
|
+
hooksExpected: 9, // 4 v1.4.1 hooks + statusline + state-update + 3 deliberate checks
|
|
240
240
|
};
|
|
241
241
|
}
|
|
242
242
|
|
|
@@ -32,7 +32,9 @@ absent or its prerequisites are unmet, skip the UI-clone step and log a warning.
|
|
|
32
32
|
When executing skills during the pipeline:
|
|
33
33
|
|
|
34
34
|
1. Read the skill's `SKILL.md` file from `.claude/skills/[name]/SKILL.md`
|
|
35
|
-
2. When a skill references `/mnt/skills/user/[name]/` — read from `.claude/skills/[name]/` instead
|
|
35
|
+
2. When a skill references `/mnt/skills/user/[name]/` — read from `.claude/skills/[name]/` instead.
|
|
36
|
+
*(The ten PRE-SHIPPED skills no longer contain such paths — since 1.8.0 they are pre-baked. This
|
|
37
|
+
rule is for skills you bring yourself.)*
|
|
36
38
|
3. When a skill references `/mnt/user-data/uploads/` — read from `docs/` instead
|
|
37
39
|
4. When a skill outputs to `/output/` — write to `docs/` or project root instead
|
|
38
40
|
5. `goap-research` skill name maps to `goap-research-ed25519` in this repo
|
|
@@ -58,6 +60,7 @@ All generated files go directly into the project. Never create a separate output
|
|
|
58
60
|
|
|
59
61
|
| Category | Path |
|
|
60
62
|
|----------|------|
|
|
63
|
+
| Product Discovery Brief (Phase 0) | `docs/product-discovery-brief.md` |
|
|
61
64
|
| SPARC documentation | `docs/` |
|
|
62
65
|
| Validation report | `docs/validation-report.md` |
|
|
63
66
|
| BDD scenarios | `docs/test-scenarios.md` |
|
|
@@ -154,9 +157,16 @@ are project-agnostic and can be enhanced (read by Phase 3) but never recreated.
|
|
|
154
157
|
**Rules (6):** `replicate-pipeline`, `skill-interface-protocol`, `git-workflow`,
|
|
155
158
|
`insights-capture`, `feature-lifecycle`, `docker-ports`
|
|
156
159
|
|
|
157
|
-
**Hooks
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
**Hooks (8 files in `.claude/hooks/`, cross-platform Node).** Only four are wired to an
|
|
161
|
+
event in `.claude/settings.json`; the rest are utilities you invoke deliberately, and the
|
|
162
|
+
difference matters — a hook of this package is NON-BLOCKING by contract and can only print.
|
|
163
|
+
|
|
164
|
+
*Wired to an event:* `session-insights.cjs` (SessionStart) · `autocommit-roadmap.cjs`,
|
|
165
|
+
`autocommit-insights.cjs`, `autocommit-plans.cjs` (Stop)
|
|
166
|
+
|
|
167
|
+
*Invoked deliberately, wired to nothing:* `statusline.cjs` (a statusLine, not a hook) ·
|
|
168
|
+
`state-update.cjs` (argv utility) · `check-ports.cjs` (docker-ports Правило №0, exits 0/1/2) ·
|
|
169
|
+
`check-growth-trace.cjs` (did the M5 growth seed reach `docs/Specification.md`, exits 0/1/2)
|
|
160
170
|
|
|
161
171
|
### Generated by /replicate Phase 3 (project-specific — create new)
|
|
162
172
|
|
|
@@ -39,6 +39,15 @@ view() .claude/skills/[skill-name]/references/[file].md
|
|
|
39
39
|
|
|
40
40
|
Skills originating from claude.ai use `/mnt/` paths. Apply these rewrites in order:
|
|
41
41
|
|
|
42
|
+
> **The ten skills this package ships no longer need this.** Since p-replicator 1.8.0 their paths are
|
|
43
|
+
> pre-baked: `.claude/skills/<name>/` resolves directly, with no rewrite step. The table below stays
|
|
44
|
+
> because a skill YOU bring from claude.ai still needs it — and because the toolkit generator's own
|
|
45
|
+
> output-scanning instructions describe this transform.
|
|
46
|
+
>
|
|
47
|
+
> One case the table cannot express: a skill referenced but NOT installed. Rewriting its path yields
|
|
48
|
+
> a local-looking path that resolves to nothing, which is worse than an obviously foreign one. Declare
|
|
49
|
+
> it OPTIONAL with a fallback (§6) instead.
|
|
50
|
+
|
|
42
51
|
| Source Pattern | Target Pattern | Notes |
|
|
43
52
|
|----------------|----------------|-------|
|
|
44
53
|
| `/mnt/skills/user/[name]/` | `.claude/skills/[name]/` | Skill root directories |
|
|
@@ -422,7 +422,7 @@ Copy these 6 skills from the user's skill set into `.claude/skills/`:
|
|
|
422
422
|
|---|-------|-------------|-------------|
|
|
423
423
|
| 11 | sparc-prd-mini | `/mnt/skills/user/sparc-prd-mini/` | `.claude/skills/sparc-prd-mini/` |
|
|
424
424
|
| 12 | explore | `/mnt/skills/user/explore/` | `.claude/skills/explore/` |
|
|
425
|
-
| 13 | goap-research | `/mnt/skills/user/goap-research/` | `.claude/skills/goap-research/` |
|
|
425
|
+
| 13 | goap-research | `/mnt/skills/user/goap-research/` | `.claude/skills/goap-research-ed25519/` |
|
|
426
426
|
| 14 | problem-solver-enhanced | `/mnt/skills/user/problem-solver-enhanced/` | `.claude/skills/problem-solver-enhanced/` |
|
|
427
427
|
| 15 | requirements-validator | `/mnt/skills/user/requirements-validator/` | `.claude/skills/requirements-validator/` |
|
|
428
428
|
| 16 | brutal-honesty-review | `/mnt/skills/user/brutal-honesty-review/` | `.claude/skills/brutal-honesty-review/` |
|
|
@@ -438,7 +438,7 @@ After copying, rewrite ALL `view()` paths in `sparc-prd-mini/SKILL.md`:
|
|
|
438
438
|
External skill paths (3 rewrites):
|
|
439
439
|
```
|
|
440
440
|
/mnt/skills/user/explore/SKILL.md -> .claude/skills/explore/SKILL.md
|
|
441
|
-
/mnt/skills/user/goap-research/SKILL.md -> .claude/skills/goap-research/SKILL.md
|
|
441
|
+
/mnt/skills/user/goap-research/SKILL.md -> .claude/skills/goap-research-ed25519/SKILL.md
|
|
442
442
|
/mnt/skills/user/problem-solver-enhanced/SKILL.md -> .claude/skills/problem-solver-enhanced/SKILL.md
|
|
443
443
|
```
|
|
444
444
|
|
|
@@ -458,10 +458,12 @@ Lines 951-953: Dependency Version Note -- update paths to .claude/skills/
|
|
|
458
458
|
|
|
459
459
|
**Note on `goap-research` name mapping:** The skill name `goap-research` in the
|
|
460
460
|
lifecycle context maps to `goap-research-ed25519` in this repository. Ensure the
|
|
461
|
-
correct directory name is used when copying
|
|
461
|
+
correct directory name is used when copying — the **Output paths** below therefore name
|
|
462
|
+
`goap-research-ed25519`, not `goap-research`. Until 2026-08-27 they named the short form, which is
|
|
463
|
+
the alias and never a real directory: the list contradicted the note directly above it.
|
|
462
464
|
|
|
463
465
|
**Output paths:** `.claude/skills/sparc-prd-mini/`, `.claude/skills/explore/`,
|
|
464
|
-
`.claude/skills/goap-research/`, `.claude/skills/problem-solver-enhanced/`,
|
|
466
|
+
`.claude/skills/goap-research-ed25519/`, `.claude/skills/problem-solver-enhanced/`,
|
|
465
467
|
`.claude/skills/requirements-validator/`, `.claude/skills/brutal-honesty-review/`
|
|
466
468
|
|
|
467
469
|
---
|
package/templates/.claude/skills/cc-toolkit-generator-enhanced/modules/08-skill-composition.md
CHANGED
|
@@ -201,8 +201,8 @@ FOR each copied_file IN target_skill_directory:
|
|
|
201
201
|
|
|
202
202
|
```
|
|
203
203
|
# Before (claude.ai format):
|
|
204
|
-
Read
|
|
205
|
-
Scan
|
|
204
|
+
Read `.claude/skills/explore/SKILL.md` for clarification protocol.
|
|
205
|
+
Scan `docs/` for documents.
|
|
206
206
|
Write output to `/output/validation-report.md`.
|
|
207
207
|
|
|
208
208
|
# After (Claude Code local format):
|
|
@@ -12,7 +12,7 @@ When generating the toolkit, **copy these skills from the user's skill set** int
|
|
|
12
12
|
# Source paths (Claude.ai user skills)
|
|
13
13
|
/mnt/skills/user/sparc-prd-mini/ → .claude/skills/sparc-prd-mini/
|
|
14
14
|
/mnt/skills/user/explore/ → .claude/skills/explore/
|
|
15
|
-
/mnt/skills/user/goap-research/ → .claude/skills/goap-research/
|
|
15
|
+
/mnt/skills/user/goap-research/ → .claude/skills/goap-research-ed25519/
|
|
16
16
|
/mnt/skills/user/problem-solver-enhanced/ → .claude/skills/problem-solver-enhanced/
|
|
17
17
|
/mnt/skills/user/requirements-validator/ → .claude/skills/requirements-validator/
|
|
18
18
|
/mnt/skills/user/brutal-honesty-review/ → .claude/skills/brutal-honesty-review/
|
|
@@ -26,7 +26,7 @@ After copying, rewrite ALL `view()` paths in `sparc-prd-mini/SKILL.md`:
|
|
|
26
26
|
External skill paths (3):
|
|
27
27
|
```
|
|
28
28
|
/mnt/skills/user/explore/SKILL.md → .claude/skills/explore/SKILL.md
|
|
29
|
-
/mnt/skills/user/goap-research/SKILL.md → .claude/skills/goap-research/SKILL.md
|
|
29
|
+
/mnt/skills/user/goap-research/SKILL.md → .claude/skills/goap-research-ed25519/SKILL.md
|
|
30
30
|
/mnt/skills/user/problem-solver-enhanced/SKILL.md → .claude/skills/problem-solver-enhanced/SKILL.md
|
|
31
31
|
```
|
|
32
32
|
|
|
@@ -134,6 +134,58 @@ apply additional security validation:
|
|
|
134
134
|
- Cross-tenant access attempt (if multi-tenant)
|
|
135
135
|
- Rate limiting / brute force scenario (if auth endpoint)
|
|
136
136
|
|
|
137
|
+
### Growth Traceability (scoring: +5 present / +0 not applicable / -10 applicable but absent)
|
|
138
|
+
|
|
139
|
+
Phase 0's M5 module analyses how a competitor grows and emits a `Growth Requirements Seed` table of
|
|
140
|
+
`FR-GROWTH-<nnn>` draft obligations into `docs/product-discovery-brief.md`. This criterion asks one
|
|
141
|
+
question: **did those obligations survive into `docs/Specification.md`, or were they analysed and
|
|
142
|
+
dropped?**
|
|
143
|
+
|
|
144
|
+
**APPLICABILITY — decide this FIRST, and it is not about project type.** The criterion applies when
|
|
145
|
+
**acquisition or adoption is in scope** — the same condition `/replicate` already gates M5 on
|
|
146
|
+
("If acquisition/adoption in scope (incl. B2B)"). Concretely:
|
|
147
|
+
|
|
148
|
+
| Situation | Applicable? | Score |
|
|
149
|
+
|---|:---:|---|
|
|
150
|
+
| `docs/product-discovery-brief.md` exists and its seed table has ≥1 `FR-GROWTH-nnn` row | YES | +5 traced · -10 not traced |
|
|
151
|
+
| The brief exists and its seed table says `нет` / is empty | no | +0 |
|
|
152
|
+
| No acquisition or adoption objective (internal tool, on-prem, replacement of an existing internal system) | no | +0 |
|
|
153
|
+
| `docs/product-discovery-brief.md` is ABSENT | no | +0 — see below |
|
|
154
|
+
|
|
155
|
+
**An absent brief is +0, never -10.** Absence means Phase 0 did not run (the `--from-docs` entry
|
|
156
|
+
skips it). Penalising a project for not running an optional phase would send every `--from-docs`
|
|
157
|
+
project into a permanent NEEDS WORK loop, which is the exact trap already closed for the Measurable
|
|
158
|
+
criterion. "Phase 0 did not run" is not "the growth requirements are missing".
|
|
159
|
+
|
|
160
|
+
**What TRACED means.** For each `FR-GROWTH-nnn` row in the brief, one of two things is true in
|
|
161
|
+
`docs/Specification.md`:
|
|
162
|
+
|
|
163
|
+
- the id `FR-GROWTH-nnn` appears (case-sensitive, the exact token — not a title, not a paraphrase), **or**
|
|
164
|
+
- the requirement was consciously rejected, and the rejection is written down with its reason.
|
|
165
|
+
|
|
166
|
+
A silently dropped row is the defect. A row rejected on the record is not.
|
|
167
|
+
|
|
168
|
+
| Check | Red Flags |
|
|
169
|
+
|-------|-----------|
|
|
170
|
+
| Every non-SPECULATIVE seed row is traced or rejected on the record | ids present in the brief, absent from the Specification, no rejection noted |
|
|
171
|
+
| Rejections carry a reason | "не берём" with no reason — indistinguishable from forgetting |
|
|
172
|
+
| `SPECULATIVE` rows were not promoted silently | a `[H]`-sourced row promoted to a firm requirement with no human decision recorded |
|
|
173
|
+
|
|
174
|
+
**Scoring Bonus:** +5 if every applicable seed row is traced or rejected on the record, +0 if not
|
|
175
|
+
applicable per the table above, -10 if the seed table carries rows and the Specification traces none
|
|
176
|
+
of them (BLOCKED if the score drops below 50).
|
|
177
|
+
|
|
178
|
+
**This criterion scores OUTSIDE the 100-point INVEST/SMART table**, exactly like Security. It adds no
|
|
179
|
+
weight to any existing criterion — the weight table and everything derived from it are unchanged.
|
|
180
|
+
|
|
181
|
+
**Honest limit.** This proves an obligation was CARRIED FORWARD, not that it was built, and not that
|
|
182
|
+
copying the competitor's growth move is lawful. Legality is not assessed anywhere in this pipeline.
|
|
183
|
+
|
|
184
|
+
**Deterministic counterpart.** `node .claude/hooks/check-growth-trace.cjs .` answers the same
|
|
185
|
+
question mechanically (0 traced · 1 rows present and none traced · 2 the check did not run). This
|
|
186
|
+
section is a prose gate read by a model; the utility is the deterministic one. Run it when the answer
|
|
187
|
+
has to be more than a judgement.
|
|
188
|
+
|
|
137
189
|
### BDD Scenario Generation
|
|
138
190
|
|
|
139
191
|
For each requirement, generate scenarios covering:
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
### 🔵 Режим DEEP
|
|
40
40
|
|
|
41
|
-
> ⚙️ **Перед началом:** `view(/
|
|
41
|
+
> ⚙️ **Перед началом:** `view(.claude/skills/goap-research-ed25519/SKILL.md)`
|
|
42
42
|
> Примени GOAP-методологию вместо статического списка.
|
|
43
43
|
|
|
44
44
|
**Phase 1 — State Assessment:**
|
|
@@ -110,7 +110,7 @@ confidence = base_reliability × recency_factor
|
|
|
110
110
|
### 🟣 Режим VERIFIED (Ed25519)
|
|
111
111
|
|
|
112
112
|
> ⚙️ **Перед началом:**
|
|
113
|
-
> 1. `view(/
|
|
113
|
+
> 1. `view(.claude/skills/goap-research-ed25519/SKILL.md)`
|
|
114
114
|
> 2. Установи зависимости:
|
|
115
115
|
> ```bash
|
|
116
116
|
> python3 -m venv .venv
|
|
@@ -120,8 +120,8 @@ confidence = base_reliability × recency_factor
|
|
|
120
120
|
> 3. Запусти инициализацию:
|
|
121
121
|
> ```python
|
|
122
122
|
> # Скопируй и запусти скрипт из:
|
|
123
|
-
> # /
|
|
124
|
-
> # /
|
|
123
|
+
> # .claude/skills/goap-research-ed25519/scripts/ed25519_verifier.py
|
|
124
|
+
> # .claude/skills/goap-research-ed25519/scripts/goap_planner.py
|
|
125
125
|
> ```
|
|
126
126
|
|
|
127
127
|
**Всё из режима DEEP, плюс:**
|
package/templates/.claude/skills/reverse-engineering-unicorn/modules/02-product-customers.md
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
### 🔵 Режим DEEP
|
|
38
38
|
|
|
39
39
|
> ⚙️ **Загрузи:**
|
|
40
|
-
> 1. `view(/
|
|
40
|
+
> 1. `view(.claude/skills/goap-research-ed25519/SKILL.md)` — адаптивный поиск отзывов
|
|
41
41
|
> 2. `view(references/jtbd-canvas.md)` — JTBD framework + примеры
|
|
42
42
|
|
|
43
43
|
**GOAP State Assessment:**
|
|
@@ -73,7 +73,7 @@ sample_size_factor: 1.0 (≥20 reviews), 0.8 (10-19), 0.5 (<10)
|
|
|
73
73
|
|
|
74
74
|
### 🟣 Режим VERIFIED
|
|
75
75
|
|
|
76
|
-
> ⚙️ **Дополнительно:** `view(/
|
|
76
|
+
> ⚙️ **Дополнительно:** `view(.claude/skills/goap-research-ed25519/SKILL.md)`
|
|
77
77
|
|
|
78
78
|
Всё из DEEP, плюс:
|
|
79
79
|
- Каждая цитата клиента получает `source_hash` и, где доступно, provenance signature
|
|
@@ -99,7 +99,15 @@ why_now: [из M2 Section E — 4 фактора]
|
|
|
99
99
|
|
|
100
100
|
### Step 3: Generate React Prototype
|
|
101
101
|
|
|
102
|
-
> ⚙️
|
|
102
|
+
> ⚙️ **`frontend-design` — OPTIONAL, ВНЕШНИЙ.** Этот пакет его не отгружает. Пути вида
|
|
103
|
+
> `.claude/skills/frontend-design/` здесь намеренно НЕТ: он выглядел бы рабочим и не резолвился бы,
|
|
104
|
+
> а путь, который врёт, хуже честно чужого.
|
|
105
|
+
>
|
|
106
|
+
> Если навык установлен — читайте его для design quality. **Fallback, если его нет:** стройте
|
|
107
|
+
> прототип по секции ниже, она самодостаточна; в отчёте пометьте, что оценка design quality не
|
|
108
|
+
> проводилась. Молча пропускать нельзя (см. `.claude/rules/skill-interface-protocol.md` §6).
|
|
109
|
+
>
|
|
110
|
+
> Установить: `dz init --select frontend-design`.
|
|
103
111
|
> ⚙️ `view(examples/noom-cjm-example.md)` — few-shot: структура .jsx
|
|
104
112
|
|
|
105
113
|
**Создай один .jsx файл** со следующей архитектурой:
|
package/templates/.claude/skills/reverse-engineering-unicorn/modules/03-market-competition.md
CHANGED
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
### 🔵 Режим DEEP
|
|
41
41
|
|
|
42
42
|
> ⚙️ **Загрузи перед началом:**
|
|
43
|
-
> 1. `view(/
|
|
44
|
-
> 2. `view(/
|
|
43
|
+
> 1. `view(.claude/skills/goap-research-ed25519/SKILL.md)` — для рыночного research
|
|
44
|
+
> 2. `view(.claude/skills/problem-solver-enhanced/SKILL.md)` — Modules 4, 5, 6 — для конкурентного анализа
|
|
45
45
|
|
|
46
46
|
#### PHASE A: GOAP Market Research
|
|
47
47
|
|
|
@@ -159,7 +159,7 @@ Incumbent │ (-2, +1) | (0, +2) │ Ценовая война
|
|
|
159
159
|
|
|
160
160
|
### 🟣 Режим VERIFIED (Ed25519)
|
|
161
161
|
|
|
162
|
-
> ⚙️ **Дополнительно:** `view(/
|
|
162
|
+
> ⚙️ **Дополнительно:** `view(.claude/skills/goap-research-ed25519/SKILL.md)`
|
|
163
163
|
|
|
164
164
|
Всё из режима DEEP, плюс:
|
|
165
165
|
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
### 🔵 Режим DEEP
|
|
42
42
|
|
|
43
43
|
> ⚙️ **Загрузи:**
|
|
44
|
-
> 1. `view(/
|
|
45
|
-
> 2. `view(/
|
|
44
|
+
> 1. `view(.claude/skills/goap-research-ed25519/SKILL.md)` — адаптивный research
|
|
45
|
+
> 2. `view(.claude/skills/problem-solver-enhanced/SKILL.md)` — Modules 1, 6
|
|
46
46
|
|
|
47
47
|
#### PHASE A: GOAP Financial Research
|
|
48
48
|
|
|
@@ -111,7 +111,7 @@ Physical: "Команда должна быть БОЛЬШОЙ (для скор
|
|
|
111
111
|
|
|
112
112
|
### 🟣 Режим VERIFIED
|
|
113
113
|
|
|
114
|
-
> ⚙️ **Дополнительно:** `view(/
|
|
114
|
+
> ⚙️ **Дополнительно:** `view(.claude/skills/goap-research-ed25519/SKILL.md)`
|
|
115
115
|
|
|
116
116
|
Всё из DEEP, плюс:
|
|
117
117
|
- Все benchmark числа получают source_hash; issuer-grade crypto используется только при valid signature under pinned active key
|