@dzhechkov/p-replicator 1.5.17 → 1.6.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 (85) hide show
  1. package/.dz-manifest.json +173 -65
  2. package/CHANGELOG.md +135 -0
  3. package/MULTIPLATFORM_ROADMAP.md +1 -1
  4. package/README/eng/01_quickstart.md +2 -2
  5. package/README/eng/02_user_guide.md +1 -1
  6. package/README/eng/03_admin_guide.md +2 -2
  7. package/README/eng/05_architecture.md +6 -2
  8. package/README/eng/README.md +1 -1
  9. package/README/ru/01_quickstart.md +2 -2
  10. package/README/ru/02_user_guide.md +1 -1
  11. package/README/ru/03_admin_guide.md +2 -2
  12. package/README/ru/05_architecture.md +1 -1
  13. package/README/ru/README.md +1 -1
  14. package/README/ru/html/index.html +7 -7
  15. package/README.md +41 -18
  16. package/bin/cli.js +0 -0
  17. package/package.json +11 -10
  18. package/sbom.json +347 -77
  19. package/src/utils.js +2 -0
  20. package/templates/.claude/agents/doc-validator.md +2 -1
  21. package/templates/.claude/agents/product-discoverer.md +1 -1
  22. package/templates/.claude/commands/next.md +16 -0
  23. package/templates/.claude/commands/replicate.md +126 -8
  24. package/templates/.claude/commands/start.md +19 -1
  25. package/templates/.claude/hooks/autocommit-insights.cjs +95 -10
  26. package/templates/.claude/hooks/autocommit-plans.cjs +95 -10
  27. package/templates/.claude/hooks/autocommit-roadmap.cjs +96 -13
  28. package/templates/.claude/hooks/check-ports.cjs +232 -0
  29. package/templates/.claude/hooks/session-insights.cjs +13 -1
  30. package/templates/.claude/hooks/state-update.cjs +13 -1
  31. package/templates/.claude/hooks/statusline.cjs +145 -18
  32. package/templates/.claude/rules/docker-ports.md +123 -0
  33. package/templates/.claude/rules/replicate-pipeline.md +5 -2
  34. package/templates/.claude/settings.json +5 -5
  35. package/templates/.claude/skills/cc-toolkit-generator-enhanced/modules/01-detect-parse.md +57 -14
  36. package/templates/.claude/skills/cc-toolkit-generator-enhanced/modules/02-analyze-map.md +9 -7
  37. package/templates/.claude/skills/cc-toolkit-generator-enhanced/references/enhanced-recommendations.md +6 -4
  38. package/templates/.claude/skills/cc-toolkit-generator-enhanced/references/extended-mapping.md +2 -2
  39. package/templates/.claude/skills/cc-toolkit-generator-enhanced/references/templates/ddd-agents.md +2 -2
  40. package/templates/.claude/skills/cc-toolkit-generator-enhanced/references/templates/ddd-skills.md +1 -1
  41. package/templates/.claude/skills/cc-toolkit-generator-enhanced/references/templates/enhanced-claude-md.md +2 -2
  42. package/templates/.claude/skills/cc-toolkit-generator-enhanced/references/templates/feature-suggestions.md +11 -2
  43. package/templates/.claude/skills/cc-toolkit-generator-enhanced/references/templates/start-command.md +1 -1
  44. package/templates/.claude/skills/goap-research-ed25519/SKILL.md +340 -47
  45. package/templates/.claude/skills/goap-research-ed25519/scripts/check_report_evidence.py +359 -3
  46. package/templates/.claude/skills/goap-research-ed25519/scripts/ed25519_verifier.py +386 -13
  47. package/templates/.claude/skills/goap-research-ed25519/scripts/fixture_legacy_v2_fact.json +23 -0
  48. package/templates/.claude/skills/goap-research-ed25519/scripts/fixtures_field_cases.json +133 -0
  49. package/templates/.claude/skills/goap-research-ed25519/scripts/goap_planner.py +314 -44
  50. package/templates/.claude/skills/goap-research-ed25519/scripts/learning_bridge.py +890 -303
  51. package/templates/.claude/skills/goap-research-ed25519/scripts/population_match.py +591 -0
  52. package/templates/.claude/skills/goap-research-ed25519/scripts/risk_statement.py +289 -0
  53. package/templates/.claude/skills/goap-research-ed25519/scripts/test_ed25519_verifier.py +57 -2
  54. package/templates/.claude/skills/goap-research-ed25519/scripts/test_evidence_provenance.py +969 -344
  55. package/templates/.claude/skills/goap-research-ed25519/scripts/test_goap_planner.py +420 -0
  56. package/templates/.claude/skills/goap-research-ed25519/scripts/test_population_match.py +544 -0
  57. package/templates/.claude/skills/goap-research-ed25519/scripts/test_risk_absolute.py +239 -0
  58. package/templates/.claude/skills/goap-research-ed25519/scripts/test_signature_v3.py +554 -0
  59. package/templates/.claude/skills/goap-research-ed25519/scripts/test_suite_completeness.py +90 -0
  60. package/templates/.claude/skills/requirements-validator/SKILL.md +7 -0
  61. package/templates/.claude/skills/requirements-validator/references/scoring-system.md +28 -0
  62. package/templates/.claude/skills/sparc-prd-mini/SKILL.md +143 -1
  63. package/tests/e2e/lifecycle.test.js +21 -10
  64. package/tests/snapshot/baseline.json +51 -34
  65. package/tests/snapshot/update-baseline.js +2 -1
  66. package/tests/unit/adr-decision-coverage.test.js +137 -0
  67. package/tests/unit/adr-scanner-contract.test.js +108 -0
  68. package/tests/unit/autocommit-deletion.test.js +242 -0
  69. package/tests/unit/check-ports.test.js +184 -0
  70. package/tests/unit/db-port-rule.test.js +216 -0
  71. package/tests/unit/detect-parse-anchor.test.js +109 -0
  72. package/tests/unit/external-dependency-check.test.js +209 -0
  73. package/tests/unit/growth-module-b2b-gate.test.js +104 -0
  74. package/tests/unit/hooks-project-anchored.test.js +223 -0
  75. package/tests/unit/hooks-report-failures.test.js +207 -0
  76. package/tests/unit/pipeline-file-ownership.test.js +95 -0
  77. package/tests/unit/roadmap-one-schema.test.js +179 -0
  78. package/tests/unit/sparc-reconciliation.test.js +117 -0
  79. package/tests/unit/spec-pseudocode-traceability.test.js +146 -0
  80. package/tests/unit/statusline-honest-labels.test.js +178 -0
  81. package/tests/unit/statusline-two-roots.test.js +237 -0
  82. package/tests/unit/sync-templates-guard.test.js +209 -0
  83. package/tests/unit/utils.test.js +2 -2
  84. package/tests/unit/validation-gate-teeth.test.js +158 -0
  85. package/LICENSE +0 -21
@@ -53,6 +53,34 @@ Total Score = INVEST Score (50%) + SMART Score (30%) + Quality Score (20%)
53
53
  | 50-69 | Fair | 🔶 REWORK | Significant clarification needed |
54
54
  | **0-49** | **Poor** | **🚫 BLOCKED** | **Requires complete rewrite** |
55
55
 
56
+ ### Blocking floor (overrides the total, both directions)
57
+
58
+ **The weakest link decides, never the average.** A requirement is BLOCKED — whatever its total says —
59
+ if either of these is zero:
60
+
61
+ | Criterion | Zero means | Why it vetoes |
62
+ |-----------|-----------|---------------|
63
+ | `Testable` (INVEST, 8) | no acceptance criteria exist | the gate exists to block untestable requirements |
64
+ | `Completeness` (Quality, 10) | "No AC" on the rubric above | nothing states what "done" is |
65
+
66
+ Without this floor the total alone lets an untestable requirement through. Worked case: a story with
67
+ NO acceptance criteria and NO test links loses `Testable` 8, `Completeness` 10 and `Traceability` 10,
68
+ keeps everything else, and totals **72/100** — above the 70 line, filed as "fix minor issues, then
69
+ proceed". The floor blocks it on `Testable = 0` and `Completeness = 0`.
70
+
71
+ **The floor keys on the artifact, not on the number you wrote.** The same agent scores these
72
+ criteria AND is bound by the floor, so a score is not evidence of anything — reporting `Testable = 4`
73
+ ("vague AC") on a story with no AC at all evades the veto without lying about the rubric. Therefore:
74
+
75
+ > A non-zero `Testable` or `Completeness` REQUIRES quoting the acceptance criteria being scored —
76
+ > the actual text, with its document and heading. `Testable = 4` means the AC exist and are vague:
77
+ > quote them. **No quote ⇒ the score is 0 ⇒ the floor applies.**
78
+
79
+ **The floor is CLOSED at these two.** `Measurable` and `Traceability` are deliberately NOT on it: a
80
+ requirement with no number is often correct ("the user can export the report as PDF" is specific,
81
+ testable and unmeasurable), so vetoing on `Measurable` would turn a false pass into a false block.
82
+ Widening this list needs the same kind of worked case as the one above.
83
+
56
84
  ## Quality Gate Rules
57
85
 
58
86
  ### BLOCKED (Score < 50)
@@ -382,16 +382,24 @@ view("/mnt/skills/user/problem-solver-enhanced/SKILL.md")
382
382
 
383
383
  **User Story Format:**
384
384
  ```
385
- As a [persona],
385
+ US-<nnn>: As a [persona],
386
386
  I want to [action],
387
387
  So that [benefit].
388
388
 
389
389
  Acceptance Criteria:
390
+ [SC-<story-id>-1]
390
391
  Given [context]
391
392
  When [action]
392
393
  Then [expected result]
393
394
  ```
394
395
 
396
+ Every user story carries an ID `US-<nnn>` — three digits, assigned in order, never reused even after
397
+ a story is deleted. Every acceptance scenario under it carries `SC-<US-id>-<n>`, numbered from 1
398
+ within its story: the scenarios of `US-007` are `SC-US-007-1`, `SC-US-007-2`, and so on. Phase 4
399
+ traces algorithms back to these IDs, and there is nothing to trace to if a scenario has no name — nor
400
+ anything reliable to trace to if two scenarios can end up with the same name, which is what the
401
+ never-reused rule prevents.
402
+
395
403
  **PRD Generation:**
396
404
  ```
397
405
  view("templates/prd.md")
@@ -437,6 +445,7 @@ type EntityName = {
437
445
  ## Core Algorithms
438
446
 
439
447
  ### Algorithm: [Name]
448
+ REALISES: [SC-… ids this algorithm implements, comma-separated]
440
449
  INPUT: [parameters]
441
450
  OUTPUT: [result]
442
451
 
@@ -471,6 +480,54 @@ Response (4xx/5xx):
471
480
  [Error categories and responses]
472
481
  ```
473
482
 
483
+ **Шаг 4.9 — ПОКРЫТИЕ СЦЕНАРИЕВ (обязательный, до чекпойнта).**
484
+
485
+ Re-read `Specification.md` and collect every `SC-` scenario ID. Collect every algorithm's `REALISES`
486
+ line from `Pseudocode.md`. Write a `## Scenario Coverage` block into `Pseudocode.md` — **in every
487
+ case, including the one where everything is covered**, because an absent block and a block saying
488
+ "all covered" are indistinguishable to the next reader:
489
+
490
+ ```
491
+ ## Scenario Coverage
492
+
493
+ Scenarios in Specification.md: [N] · claimed by an algorithm: [M]
494
+
495
+ Not claimed by any algorithm:
496
+ | Scenario | Reason |
497
+ |---|---|
498
+ | SC-… | ui-only |
499
+
500
+ Claimed by an algorithm but absent from Specification.md:
501
+ | Algorithm | Claimed ID |
502
+ |---|---|
503
+ | [name] | SC-… |
504
+ ```
505
+
506
+ **Both tables are required, and both may be the single word `none`.** A traceability check that runs
507
+ one way only is half a check: without the second table an algorithm can declare `REALISES: SC-US-009-3`
508
+ for a scenario nobody ever wrote, and the dangling reference reads exactly like coverage. `none` is
509
+ written out rather than left blank, because an empty table and a forgotten table look identical.
510
+
511
+ **Reasons are a CLOSED list of five**, and nothing else is accepted:
512
+
513
+ | Reason | Means |
514
+ |---|---|
515
+ | `ui-only` | realised entirely in the interface, no algorithm to write |
516
+ | `external-service` | performed by a third party, see `Architecture.md` → External Dependencies |
517
+ | `out-of-mvp-scope` | deliberately not built yet |
518
+ | `data-only` | satisfied by a schema or constraint, not by a procedure |
519
+ | `config-only` | satisfied by OUR OWN configuration — a server setting, a header, a policy file — with no procedure to write |
520
+
521
+ Free text is NOT a reason, and `N/A` is NOT a reason. A field that accepts anything records nothing:
522
+ the whole value of the list is that an unclaimed scenario has to be one of a small number of
523
+ recognisable things, and if it is none of them, the gap is real and belongs in the algorithms.
524
+
525
+ **What this establishes, and what it does not.** It establishes that a CLAIM exists and that its two
526
+ ends name each other. It does NOT establish that the algorithm's steps actually perform the check the
527
+ scenario describes — no comparison of names can. So this catches *"nobody wrote anything about this
528
+ scenario"*; it does not catch *"someone wrote a line that mentions it"*. Say so here rather than
529
+ letting a later reader assume the stronger thing.
530
+
474
531
  **[MANUAL] CP4:**
475
532
  ```
476
533
  ═══════════════════════════════════════════════════════════════
@@ -541,6 +598,51 @@ graph TB
541
598
  | Queue | | |
542
599
  | Infrastructure | | |
543
600
 
601
+ ## External Dependencies
602
+
603
+ Every capability this product needs from someone else's service. One row per capability, not one row
604
+ per vendor: "sends email" and "reports bounces" are two questions, and a provider can do one without
605
+ the other.
606
+
607
+ | Capability needed | Provider / API | Evidence | Verdict | Requirements relying on it |
608
+ |---|---|---|---|---|
609
+ | [what the product needs it to DO] | [service] | [link to the provider's own docs naming this capability] · checked [YYYY-MM-DD] | CONFIRMED | [REQ ids] |
610
+
611
+ **Evidence — what counts, and what does not.** Evidence is a link to the PROVIDER'S OWN documentation
612
+ that names the specific capability, plus the date it was checked, plus **a short verbatim QUOTE from
613
+ that page stating the capability**. These do NOT count, and each is a way this check gets faked: a
614
+ landing page or marketing page; a pricing page; recollection — "the model knows this API supports
615
+ it"; and **a URL nobody opened** — a plausible-looking link is the cheapest possible forgery, which
616
+ is exactly why the quote is required and the link alone is not enough. A capability nobody could cite
617
+ is not confirmed, and saying so is the point of the middle verdict.
618
+
619
+ **Verdicts — exactly three, because two would hide a difference that matters:**
620
+
621
+ | Verdict | Means | Consequence in Phase 2 |
622
+ |---|---|---|
623
+ | CONFIRMED | cited, and the citation names this capability | none |
624
+ | UNCONFIRMED | nobody could produce a citation | the REQUIREMENTS in that row's last column cannot enter Phase 3 — defer, remove or replace them. Unrelated work continues; the run is 🟡 CAVEATS at best and the row is NAMED in the report |
625
+ | CONTRADICTED | the provider's own docs say it cannot | 🔴 NEEDS WORK — the requirement rests on something that is not there |
626
+
627
+ `UNCONFIRMED` is not a failure to be hidden; it is the honest state of a project on a machine with no
628
+ web access. Collapsing it into CONFIRMED overstates what is known; collapsing it into CONTRADICTED
629
+ blocks work that may be perfectly fine — and would push people to write a citation that isn't one,
630
+ which is how a gate becomes theatre.
631
+
632
+ But it does not pass for free either. **The consequence is scoped to the REQUIREMENT, not to the
633
+ run:** the requirements listed in an `UNCONFIRMED` row do not enter Phase 3 until they are deferred,
634
+ removed, or rewritten onto something confirmable. Everything not resting on that capability proceeds.
635
+ Without this scoping an inventory of nothing but `UNCONFIRMED` rows would reach Phase 3 with a
636
+ caveat, and external feasibility would never have to be established at all — the check would be
637
+ optional in practice while looking mandatory on paper.
638
+
639
+ **If this product has no external dependencies**, write exactly that: *"No external dependencies —
640
+ this product calls no third-party service."* An empty section and an absent section are
641
+ indistinguishable, and only one of them means anything.
642
+
643
+ Names in the row above are PLACEHOLDERS. Do not copy a real provider or a real capability from any
644
+ example: what an API can do drifts, and a stale fact recorded as evidence is worse than none.
645
+
544
646
  ## Data Architecture
545
647
  [Data models, relationships, storage strategy]
546
648
 
@@ -551,6 +653,46 @@ graph TB
551
653
  [Horizontal/vertical scaling, bottlenecks]
552
654
  ```
553
655
 
656
+ **Шаг 5.9 — СВЕРКА С ПСЕВДОКОДОМ (обязательный, до чекпойнта).**
657
+
658
+ Фаза 4 написала модель данных ДО того, как эта фаза выбрала хранилище и технологии, и до сих пор
659
+ ничто их не сверяло. Именно отсюда берутся расхождения, которые всплывают уже в коде: поле осталось
660
+ булевым, когда схема получила перечисление; алгоритм пользуется полем, которого в схеме нет; у
661
+ статуса три значения в одном документе и пять в другом.
662
+
663
+ Перечитай в `Pseudocode.md` ДВЕ секции — `## Data Structures` и `## Core Algorithms` — и сверь их с
664
+ тем, что выбрано ЗДЕСЬ. Алгоритмы нужны обязательно: расхождение «алгоритм читает поле, которого в
665
+ схеме нет» по одним лишь структурам данных не обнаруживается. Ищи три вида расхождений:
666
+
667
+ - **смена типа** — поле объявлено одним типом, а хранилище требует другого (булево против перечисления);
668
+ - **отсутствующая колонка** — алгоритм читает или пишет поле, которого в схеме нет;
669
+ - **несовпадение набора значений** — у одного и того же поля разное число допустимых значений.
670
+
671
+ Какую сторону править — решается по РОЛИ документа, а не по старшинству. `Pseudocode.md` держит
672
+ ЛОГИЧЕСКУЮ модель (что означает поле), `Architecture.md` — ФИЗИЧЕСКУЮ (где и как оно лежит).
673
+ Поэтому: если эта фаза ввела осознанное физическое ограничение (тип хранилища, индекс, длина) —
674
+ правится `Pseudocode.md`; если выбранная технология НАРУШАЕТ требуемую семантику (теряются значения,
675
+ исчезает состояние, которым пользуется алгоритм) — меняется выбор ЗДЕСЬ, потому что требование
676
+ старше удобства реализации. Секция `## Data Architecture` этого документа остаётся на месте, но
677
+ описывает отображение на хранилище и связи, а НЕ пересказывает список полей: второй экземпляр списка
678
+ становится вторым местом, где начинается расхождение.
679
+
680
+ Результат записывается в `Architecture.md` ВСЕГДА, отдельным блоком:
681
+
682
+ ```markdown
683
+ ## Reconciliation with Pseudocode
684
+
685
+ | Сущность.поле | Вид расхождения | Что сделано |
686
+ |---|---|---|
687
+ | … | смена типа / отсутствующая колонка / несовпадение набора значений | … |
688
+ ```
689
+
690
+ Если сверка не нашла ничего — блок всё равно пишется, и он ОБЯЗАН назвать, что именно
691
+ сверялось: «Расхождений с `Pseudocode.md` не найдено. Сверены сущности: <перечисление>; алгоритмы:
692
+ <перечисление>.» Одна фраза «расхождений нет» без перечня — это церемония, которую модель напишет
693
+ не глядя; перечень делает утверждение проверяемым. Молчание не является результатом сверки: по нему
694
+ нельзя отличить «сверили и чисто» от «не сверяли».
695
+
554
696
  **[MANUAL] CP5:**
555
697
  ```
556
698
  ═══════════════════════════════════════════════════════════════
@@ -281,16 +281,24 @@ describe('e2e: unknown command', () => {
281
281
  // ---------------------------------------------------------------------------
282
282
 
283
283
  describe('e2e: --help shows correct component counts', () => {
284
- test('mentions 10 skills, 11 commands, 4 agents, 5 rules', () => {
284
+ test('--help agrees with COMPONENTS for every group', () => {
285
+ // DERIVED, not hardcoded. This assertion has now gone stale twice for the same reason — the
286
+ // comment above records "cli.js used to say 1 rule while EXPECTED_RULES had 2 entries", and
287
+ // adding the docker-ports rule broke it again with a literal 5. cli.js:57 already computes the
288
+ // numbers from COMPONENTS; a test that re-types them is a second source of truth, which is the
289
+ // very defect it was written to catch.
290
+ const { COMPONENTS } = require(path.join(PKG_DIR, 'src', 'utils.js'));
285
291
  const dir = tmpDir();
286
292
  try {
287
293
  const r = runCli(['--help'], dir);
288
294
  assert.equal(r.exitCode, 0);
289
- assert.match(r.stdout, /10\s+skills/i, 'should mention 10 skills');
290
- assert.match(r.stdout, /11\s+commands/i, 'should mention 11 commands (post v1.4)');
291
- assert.match(r.stdout, /4\s+agents/i, 'should mention 4 agents');
292
- assert.match(r.stdout, /5\s+rules/i,
293
- 'should say "5 rules" (post v1.4: + 3 generic rules)');
295
+ for (const group of ['skills', 'commands', 'agents', 'rules']) {
296
+ const n = Object.keys(COMPONENTS[group].items).length;
297
+ // singular/plural: cli.js prints "1 rule" but "6 rules"
298
+ const word = n === 1 ? group.replace(/s$/, '') : group;
299
+ assert.match(r.stdout, new RegExp(n + '\\s+' + word, 'i'),
300
+ '--help must say "' + n + ' ' + word + '" to match COMPONENTS.' + group);
301
+ }
294
302
  } finally { rmRf(dir); }
295
303
  });
296
304
  });
@@ -440,8 +448,10 @@ describe('e2e: v1.4.1 cross-platform hooks', () => {
440
448
  assert.doesNotMatch(cmd, /\|\|\s*true/,
441
449
  `bash-specific || true in: ${cmd}`);
442
450
  // Each command should invoke node + a script
443
- assert.match(cmd, /node\s+\.claude[/\\]hooks/,
444
- `expected 'node .claude/hooks/<script>.cjs', got: ${cmd}`);
451
+ // Anchored at the project root, not the drifting cwd (PR-013): still node + the exact
452
+ // script, and now additionally the anchor — strictly stronger than the old assertion.
453
+ assert.match(cmd, /node\s+"\$\{CLAUDE_PROJECT_DIR\}\/\.claude\/hooks\/[A-Za-z0-9._-]+\.cjs"/,
454
+ `expected 'node "\${CLAUDE_PROJECT_DIR}/.claude/hooks/<script>.cjs"', got: ${cmd}`);
445
455
  }
446
456
  } finally { rmRf(dir); }
447
457
  });
@@ -599,8 +609,9 @@ describe('e2e: v1.5.0 statusline dashboard', () => {
599
609
  );
600
610
  assert.ok(settings.statusLine, 'statusLine field should be present in settings.json');
601
611
  assert.equal(settings.statusLine.type, 'command');
602
- assert.match(settings.statusLine.command, /node\s+\.claude[/\\]hooks[/\\]statusline\.cjs/,
603
- 'should invoke statusline.cjs via node');
612
+ assert.match(settings.statusLine.command,
613
+ /node\s+"\$\{CLAUDE_PROJECT_DIR\}\/\.claude\/hooks\/statusline\.cjs"/,
614
+ 'should invoke statusline.cjs via node, anchored at the project root (PR-013)');
604
615
  } finally { rmRf(dir); }
605
616
  });
606
617
 
@@ -1,10 +1,10 @@
1
1
  {
2
- "generatedAt": "2026-07-19T15:43:12.046Z",
3
- "totalFiles": 119,
2
+ "generatedAt": "2026-08-27T09:01:34.335Z",
3
+ "totalFiles": 136,
4
4
  "files": {
5
- ".claude/agents/doc-validator.md": "a46651637239b4f078b5c3022ea2bf9ef4fb84ab2eb529cdc41273c42deaddf5",
5
+ ".claude/agents/doc-validator.md": "e57950758cd4764b2cb54b3f1905567e9dbc1ed20ac6ecd30998614894689f4f",
6
6
  ".claude/agents/harvest-coordinator.md": "70fa884057669902e18744915305705cf9e45e738a83d7bb5ab011a3b72d683c",
7
- ".claude/agents/product-discoverer.md": "ea341407faa6f31a152508945b24e650c5a71459bbc9e1f91cdab7621660a54d",
7
+ ".claude/agents/product-discoverer.md": "f74683fe91b4357d6fb4024ed47b4d5a129ea6375ca6b223dee97176d74acf1c",
8
8
  ".claude/agents/replicate-coordinator.md": "e86060110ab188109cf908878206543f414993e14dad01f8dc19f041ee6497a7",
9
9
  ".claude/commands/deploy.md": "27f5424ee217163c55e5e6b9322a1f0858159407bd24ebd6d6588d6c22a5f890",
10
10
  ".claude/commands/docs.md": "be03592cb3f1d61b60dc96d3e26d71281ad4eb2d4626012c080ce609a32c96e4",
@@ -12,23 +12,25 @@
12
12
  ".claude/commands/go.md": "655dc9cad37b61a9f283cef15e435c492ee7cbc88a6ce59295ac32c975dee858",
13
13
  ".claude/commands/harvest.md": "c074fe7799f594dda44c5f8166da707f25cee51b12f758dea562a8c1e6ac5dcd",
14
14
  ".claude/commands/myinsights.md": "2e73e822384f976383d9c3313940888b9853f1781d2c39a2fb89825f221149dc",
15
- ".claude/commands/next.md": "c417f86626a91d716cb9b5ed98e1445a0820055b22947da33fc90fc65fe974b2",
15
+ ".claude/commands/next.md": "1e4984306c3aa80dfc8734dc1c975dfe5fdf2cf6396ddd759e4c7635646107b8",
16
16
  ".claude/commands/plan.md": "6fef889f51168981bf4a98b8392a0d595e3d199e1cfaa8e08c0a181ec6c440e4",
17
- ".claude/commands/replicate.md": "27fb978d1b4f19169d48795c5ce1a8ad4e5b6a03e9ae478b64857cdeb9d8b4bb",
17
+ ".claude/commands/replicate.md": "13f5e2ebe109f33b63cbcd75e3cf1b94224ab066aba1b0cb10cf34f668144a8a",
18
18
  ".claude/commands/run.md": "87144dfe8c56c15ba7c117daa544d8a08b84d7205f21dafcc48d27c6c3995059",
19
- ".claude/commands/start.md": "8ebd4393caf6fb453bf607022e6209b963847dd61cb95a78e7bb5f98e039c774",
20
- ".claude/hooks/autocommit-insights.cjs": "36fa95a1cfa74098f2f222ee7038d1bd22478a42070746614eb9e2d8514cad61",
21
- ".claude/hooks/autocommit-plans.cjs": "ac831fa835557e268a73e7a039977194c638689c3c65ce8cba427535d88ec3b2",
22
- ".claude/hooks/autocommit-roadmap.cjs": "ab78ae2f163400865bee520b73b7624094bf6c32c63478dfd5d6a1715ca7f135",
23
- ".claude/hooks/session-insights.cjs": "cbb60842149fb90aaa968576f99d0695c92628377c3ca3120d28c5ff0bc692f2",
24
- ".claude/hooks/state-update.cjs": "39a20e59278e457f4ec4eadd66f3699fee43c79695934a44a4cdca0c18f6cec2",
25
- ".claude/hooks/statusline.cjs": "7e3e230f68b2ba76908127887e7f75428599dbd62826be62ed626fc054ca1e65",
19
+ ".claude/commands/start.md": "4aaebc10ca8d607d4b2b43883d82392e9788c2f183878a49fc0d1ed54d07ee95",
20
+ ".claude/hooks/autocommit-insights.cjs": "5e7cef87b24d457f25315d79fe15f0dfaf94d9269495d638817f0faee2593c6f",
21
+ ".claude/hooks/autocommit-plans.cjs": "9bb404b7f4fda5de03e6c2f16bf8939a79ec1944538767b04bcccc6cf50cc03d",
22
+ ".claude/hooks/autocommit-roadmap.cjs": "f4dcc9ffd9a3aed91dd56e011e699fcf8af903cc81594e4ab1ef61e5432a36ad",
23
+ ".claude/hooks/check-ports.cjs": "e5f2d2bd8899df27c2dfedf76128467becae1868210eb8525a1bad2869a8c78f",
24
+ ".claude/hooks/session-insights.cjs": "46f8357e3886a6d54db1ab4af969b9b8643ae5937ba59038a5651ffbcfd0d30e",
25
+ ".claude/hooks/state-update.cjs": "47146a76b768ac2273abe8f2f017856a0e28b45afaf90048148da417dd19604e",
26
+ ".claude/hooks/statusline.cjs": "1eca683baf67a17874dc5db6dfe38eb11944f550c66f46330bce0f794732245f",
27
+ ".claude/rules/docker-ports.md": "bef41c25c875479341f68783c2d64572800d4710f55401e55519245f03d22efb",
26
28
  ".claude/rules/feature-lifecycle.md": "f9ddc8c889ab7938a7207b36ae46c36be05e9b870956ef16617bf31b2f78c758",
27
29
  ".claude/rules/git-workflow.md": "7d8d2ded47fcc0fb95da3dc226efa6cb3c80d6adf7296977588c181dfce20192",
28
30
  ".claude/rules/insights-capture.md": "488d694caffe7a32915b0ec1beb7a84b223fe602722c5bb91ab8bf2785626387",
29
- ".claude/rules/replicate-pipeline.md": "2eaa40ece405b506f0b94818013e2e235be6c9fb3bd73e964dd675afc34b6535",
31
+ ".claude/rules/replicate-pipeline.md": "b65e802d32a1e50bdfcd0cfc79c78e9234eac48a94f0cd1f5647cf4fea6c0162",
30
32
  ".claude/rules/skill-interface-protocol.md": "fe18fcb9217002572f462f3a7f38de22cdd7ba0dd4e906fdcd0c0e8cfed9f2aa",
31
- ".claude/settings.json": "1afea754d42e3b2aa7cee0a17a8347ba594427b40daa293ce7b21f3dfd0607c3",
33
+ ".claude/settings.json": "b1df6cf834ccfa227f3318a70862115c17838ab31253e9d8d89381b7763e61fd",
32
34
  ".claude/skills/brutal-honesty-review/evals/brutal-honesty-review.yaml": "855c155d55575e12aab23fb3a5fb2fada74d93974ff755dfedac6f2d5bd41f13",
33
35
  ".claude/skills/brutal-honesty-review/README.md": "2a026b4af50b21456e50424fbfa089cb983fbbaa0c68024c8c17c695bea25a57",
34
36
  ".claude/skills/brutal-honesty-review/resources/assessment-rubrics.md": "dac09c91c765e2211799cc230738fb72a966f47511edb872306a906e49640cbe",
@@ -38,8 +40,8 @@
38
40
  ".claude/skills/brutal-honesty-review/scripts/assess-tests.sh": "8c6444bdb5ce97e49223cdaa6b1c58ac8fcec710cd6ee8d56de9bc677379bd88",
39
41
  ".claude/skills/brutal-honesty-review/scripts/validate-config.json": "7418284839f89735d01f50eefdb488b013e0076f6003a67683062429c14984c6",
40
42
  ".claude/skills/brutal-honesty-review/SKILL.md": "21e41129dac8e99485b501dcb3767d5f4461ce527782fa7bc71f89dabe5bd2bd",
41
- ".claude/skills/cc-toolkit-generator-enhanced/modules/01-detect-parse.md": "45441d525ff5092766b9ab743e783dbf3b25e9f9515bdda888c8ca1cc3e0a6f0",
42
- ".claude/skills/cc-toolkit-generator-enhanced/modules/02-analyze-map.md": "231ac3c42b800e26d035562633da79abd77ea90540e8d9245cc9360867dc91ab",
43
+ ".claude/skills/cc-toolkit-generator-enhanced/modules/01-detect-parse.md": "85c72f6daa5af88b4a7ff520a387f47a7c92b81cb1f0757550c8b58100a97be6",
44
+ ".claude/skills/cc-toolkit-generator-enhanced/modules/02-analyze-map.md": "5939f3fe6ae542fabb8e665dc373a20410d8de917362fcb3ecac504286f41836",
43
45
  ".claude/skills/cc-toolkit-generator-enhanced/modules/03-generate-p0.md": "b093a5d66663e2dfd6415afef7c7444409f03379f857001b811685ded410038b",
44
46
  ".claude/skills/cc-toolkit-generator-enhanced/modules/04-generate-p1.md": "081284d3858c5dd89b45fc8a2b83bbc0477843f864cbceb6d9f8c3629b198a0a",
45
47
  ".claude/skills/cc-toolkit-generator-enhanced/modules/05-generate-p2p3.md": "9535eaa5fa1be0804369aa4e8ee6f6f580839ea2c3c7b7aa51584e298a928093",
@@ -49,32 +51,47 @@
49
51
  ".claude/skills/cc-toolkit-generator-enhanced/modules/09-cross-project-learning.md": "c395bc42a40ed14c0b8fe274df516082db0490228c82aba6a56f23b8f41d3d43",
50
52
  ".claude/skills/cc-toolkit-generator-enhanced/modules/README.md": "9dbcc9c0978d06cbe31caffa909741fdb3a38d3cd1e6e98addf95628ec8394a0",
51
53
  ".claude/skills/cc-toolkit-generator-enhanced/references/claude-md-strategy.md": "88cdab1687096d58dc4450cdf81d24d00fdb493b2cc4960030b30fd57d1ca2da",
52
- ".claude/skills/cc-toolkit-generator-enhanced/references/enhanced-recommendations.md": "0a828ed5302a3436ab9c21cdeeb2ebf47329031106dfb242517ca04f226033dd",
53
- ".claude/skills/cc-toolkit-generator-enhanced/references/extended-mapping.md": "0c906fe8622ffa147a09af592ab75a8b1034b7634501e576da58e858477c3141",
54
+ ".claude/skills/cc-toolkit-generator-enhanced/references/enhanced-recommendations.md": "657e35db0cb77d3a9d1a4d01215a9b8d50441dd863593bee3a84f62aad8b00bc",
55
+ ".claude/skills/cc-toolkit-generator-enhanced/references/extended-mapping.md": "5e87c91956eabc70b4a1084b47b2c9a20ede18bb245735812ead956eafabf3af",
54
56
  ".claude/skills/cc-toolkit-generator-enhanced/references/maturity-integration.md": "aa4e743bcd0281525336a298d0489c31481f69ff1a534e1ed1d262d888937deb",
55
57
  ".claude/skills/cc-toolkit-generator-enhanced/references/security-patterns-library.md": "5f1d650c426cbd2c9536b385306605ea62a5a520ee4566d23ca7254409c672a5",
56
58
  ".claude/skills/cc-toolkit-generator-enhanced/references/templates/automation-commands.md": "23b8204fdc70b5afc5430cbe503af709a04b26716d2d2e07889283a755858fee",
57
- ".claude/skills/cc-toolkit-generator-enhanced/references/templates/ddd-agents.md": "208619880fe6fea47b25f5f31a7fc5ef27f2a80b2235c2f8c1aa2b4140f48363",
59
+ ".claude/skills/cc-toolkit-generator-enhanced/references/templates/ddd-agents.md": "c91f81da197a072b57378fd0018eea26c35d909a558bdca6f070eb60153c97b3",
58
60
  ".claude/skills/cc-toolkit-generator-enhanced/references/templates/ddd-hooks-commands.md": "d70a0c4977d322602c35c53bf04880177b5dd8f0de2b339d68a0f55993903745",
59
- ".claude/skills/cc-toolkit-generator-enhanced/references/templates/ddd-skills.md": "9cbdbc251026297ba30dca8b4311906a85ba7a8bf85fd35c41aa1dc358ec7574",
60
- ".claude/skills/cc-toolkit-generator-enhanced/references/templates/enhanced-claude-md.md": "6121b4bec44fa726a8b70d6680c17ecf428fdf937bb3e13d9ee7e3b56ad33913",
61
+ ".claude/skills/cc-toolkit-generator-enhanced/references/templates/ddd-skills.md": "2f1019d5da7d695983aee79186a47fcefccbfa24db48219c04f9bb9feb757d3a",
62
+ ".claude/skills/cc-toolkit-generator-enhanced/references/templates/enhanced-claude-md.md": "db6898b7202b84965cbff9195a6ce780cadd6aeb64adae3fbfd951443a6bc43d",
61
63
  ".claude/skills/cc-toolkit-generator-enhanced/references/templates/feature-lifecycle-ent.md": "eb9025b687f0408b33280bf5fcc6c8be9b1670a544dd90b510557b89ae6cc123",
62
64
  ".claude/skills/cc-toolkit-generator-enhanced/references/templates/feature-lifecycle.md": "c537b47e7a4ff2d692767f4aac130e2ae9b1923782106750218696e87f515feb",
63
- ".claude/skills/cc-toolkit-generator-enhanced/references/templates/feature-suggestions.md": "455fd4e4147f15175e1bb2dbfeda53d6ae0a4ac3f8d985544d0db5d24eba935d",
65
+ ".claude/skills/cc-toolkit-generator-enhanced/references/templates/feature-suggestions.md": "3b1c20d2394e180720447416767fbfae99168cf9ca846bf64907f6fe5cd906da",
64
66
  ".claude/skills/cc-toolkit-generator-enhanced/references/templates/insights-system.md": "244c2ef5f417c5d0097accf5ccfffd9de93d167efbfc6818cb9a8196139e096e",
65
67
  ".claude/skills/cc-toolkit-generator-enhanced/references/templates/mcp.md": "63d1e6dabf5bb29534e6fa11d9dd531ec55a48cda661f0faf7a29dad6f49296f",
66
- ".claude/skills/cc-toolkit-generator-enhanced/references/templates/start-command.md": "67cf259f8d22c1b94c5242c6fd48d557e97581beb162cf176eb2e6851bab1962",
68
+ ".claude/skills/cc-toolkit-generator-enhanced/references/templates/start-command.md": "e037a7e73e65e5216f95f27a255009c4c2b95f0f2d6b7c575d70813efac34438",
67
69
  ".claude/skills/cc-toolkit-generator-enhanced/SKILL.md": "26fb1a3c0961fbb1f5f7e81ec5134bbe49ba0f99175c394cdf0c6b8a35568be2",
68
70
  ".claude/skills/explore/references/questioning-techniques.md": "ec0dd00871d3abe950f9cf375216a43043827897166c4165c3fa581839851195",
69
71
  ".claude/skills/explore/references/task-brief-templates.md": "4e9292479e120afce944b747bb7b4a7226c41e9880708d620de3ea4fa4ef0249",
70
- ".claude/skills/explore/SKILL.md": "c755a7bcdfe97fb7cb0bcd7bf3b1fd8a2d238ef082967fbf87740fc808302542",
72
+ ".claude/skills/explore/SKILL.md": "2473e7961845db0d64566cd42627b374d1830664b9e302058a1b1aa466bc7361",
71
73
  ".claude/skills/goap-research-ed25519/references/ed25519-verification.md": "2742f14b472bff69c83f24d9bac5bf023bd7f9ecc3e659742ac3152a239dd68f",
72
74
  ".claude/skills/goap-research-ed25519/references/research-actions.md": "156d2f8ce342f7013bc758fe7c0d3ad3041b4f67f30dbcf8d59e091cb70d9a9c",
73
75
  ".claude/skills/goap-research-ed25519/references/source-evaluation.md": "d6a19abb6be64dc9e1f539903080029125d2d899da4de3063e75e1afb7e4906f",
74
- ".claude/skills/goap-research-ed25519/scripts/ed25519_verifier.py": "dc9edc4d7907d13b28dfa74cc86b30a27a41de707ce72f39aca0ae08f07b5703",
75
- ".claude/skills/goap-research-ed25519/scripts/goap_planner.py": "2ec359e1ddc52ca3118144532ed483dcc609e856a04b29bb191b875c60ff4260",
76
- ".claude/skills/goap-research-ed25519/scripts/test_ed25519_verifier.py": "ea6d888ac53bac3a0fe236c101f90a984edbac044d787d73c8414f1c4fc540d3",
77
- ".claude/skills/goap-research-ed25519/SKILL.md": "e23770a81922103571eb2645fb82509f7046bc7dd407a33b06f67ad2e709b9b4",
76
+ ".claude/skills/goap-research-ed25519/scripts/check_report_evidence.py": "5053e677f11d00b4dd8365a81eafa1d2c961eebd25c33f72b02455573a934a32",
77
+ ".claude/skills/goap-research-ed25519/scripts/ed25519_verifier.py": "f4a2ac9e6473201583643fe8abf47560863cec600344dad5c9df06091b4298f5",
78
+ ".claude/skills/goap-research-ed25519/scripts/evidence_fetch.py": "5f4d7cb5d6fb3106d64130b6606582eb55a4f633ef969cf7890b1de1c179345b",
79
+ ".claude/skills/goap-research-ed25519/scripts/fixture_legacy_v1_fact.json": "e613de4737145cbfb5f349fbf9f1122801ce3508b62c3a18e2e0cba26b9da5b0",
80
+ ".claude/skills/goap-research-ed25519/scripts/fixture_legacy_v2_fact.json": "3f552b47c3864e4ff7ae8c72516e98c188592c7f4f7703d09ce88b39f586ad9d",
81
+ ".claude/skills/goap-research-ed25519/scripts/fixtures_field_cases.json": "e2ee619732ab4a1b57285e57b4349f96b4158b231a5624e5264fadf69edb8983",
82
+ ".claude/skills/goap-research-ed25519/scripts/goap_planner.py": "f5cbf4784106710b363e7f29bfa538b75f488cb25e1c273ae40de9f4c2a6710b",
83
+ ".claude/skills/goap-research-ed25519/scripts/learning_bridge.py": "74f8842978ba945ff78c2bd54702415dd87122e61919571e12a19c3cf1e56131",
84
+ ".claude/skills/goap-research-ed25519/scripts/population_match.py": "bbd1d3346a6fb75d0e8526cb5d2fc8bc8613bb31ab63ffb0958d436d5e009054",
85
+ ".claude/skills/goap-research-ed25519/scripts/risk_statement.py": "320ffece816e875f65624583846f44dc99461f672a0de7cda42be5ddf29d6de5",
86
+ ".claude/skills/goap-research-ed25519/scripts/source_tiers.py": "e1aae76fad01693ab35b51466fc4369c04a5ac64230fd307e7b798dc5beeff7a",
87
+ ".claude/skills/goap-research-ed25519/scripts/test_ed25519_verifier.py": "dcba1ce538ff946d6928f30a7c5cbcc37fddf712b6181f91f94c76e20c117ac5",
88
+ ".claude/skills/goap-research-ed25519/scripts/test_evidence_provenance.py": "292bfcdcc086934905c77f1543d8400ee483166ff3ce26c79bb526c204320dbb",
89
+ ".claude/skills/goap-research-ed25519/scripts/test_goap_planner.py": "7942ada069048b7e97bf2b6e920898a58517ccec090069f347399dbf1fc37731",
90
+ ".claude/skills/goap-research-ed25519/scripts/test_population_match.py": "f33f72c0ba6305af1644e6b1a7f7635d3f33273344f19c14e7dbd2f819af0e7f",
91
+ ".claude/skills/goap-research-ed25519/scripts/test_risk_absolute.py": "ab353db189650551c374cb772ba4a3a6929e3a2618f2f5c112eca4c3f69e46b6",
92
+ ".claude/skills/goap-research-ed25519/scripts/test_signature_v3.py": "a04259296df104c9497c7b31d29556cb9a7ad4dd3339cbe3d8d32a4f53950d25",
93
+ ".claude/skills/goap-research-ed25519/scripts/test_suite_completeness.py": "727c5d5b0dad215957012276ebc146397178255077e762ed7b88a60d8178d2ab",
94
+ ".claude/skills/goap-research-ed25519/SKILL.md": "404cb696d537d29585ec35f97a86173a582cd6fcf8d5f172a4f5bbd75ec971a8",
78
95
  ".claude/skills/knowledge-extractor/examples/rate-limiting-extraction.md": "fab68772135532aaa7675dfca4ec068cfa68a847f964f872f201f08fb9ee4034",
79
96
  ".claude/skills/knowledge-extractor/modules/01-agent-review.md": "53883f182c26c710190399a23193cddb4a94b0f35bb42169a353f354aae4083a",
80
97
  ".claude/skills/knowledge-extractor/modules/02-classify.md": "3b6a59cde451fc89e2e683b7cd35f5535d12cc6072cd40ca35cf7d5f61eb78aa",
@@ -97,13 +114,13 @@
97
114
  ".claude/skills/pipeline-forge/templates/command-template.md": "b91a4ef084ba542801154c8b1fb2a086a6b404c3f7ee809ceb6ea633e2b55245",
98
115
  ".claude/skills/pipeline-forge/templates/pipeline-template.md": "952d2e1f050558dacbf86d2b2ad2c9bc671b1ce2809ce430593434998103a27c",
99
116
  ".claude/skills/pipeline-forge/templates/skill-template.md": "b92775b4d181fc70ae393645999472ddb64f7419392c12d86b4182b49308df65",
100
- ".claude/skills/problem-solver-enhanced/SKILL.md": "530623c986dee931d47314c22195ea9de50a75f2a0daecfc469fb015c3dd3415",
117
+ ".claude/skills/problem-solver-enhanced/SKILL.md": "031378aa2e10c98928e35de07d454135e73550cd0c49f0cd886d53e4208d6b9f",
101
118
  ".claude/skills/requirements-validator/assets/templates/bdd-feature-template.feature": "5b1e47f10447ce574d0eb3917b69e2613b6e3f9c48b30ff5f4cfb57758c99a1d",
102
119
  ".claude/skills/requirements-validator/references/bdd-patterns.md": "04611a8c52c81f3a6d4fc2f9661ebc56159a125b6fb44a4d18b432e2b82de6e3",
103
120
  ".claude/skills/requirements-validator/references/invest-criteria.md": "ac6976adf776b9b60c784e1a0f6a0d96dd3332b16f4c12b72d3e59f9325bb626",
104
- ".claude/skills/requirements-validator/references/scoring-system.md": "79d421c79ab2cc594e685c27178368495774a1154e2b65cdbcd2a94cc28e9dbb",
121
+ ".claude/skills/requirements-validator/references/scoring-system.md": "49afe072f31f5b4f9a33f6b59487244f494b0f5587b6cc10c797c4de59510114",
105
122
  ".claude/skills/requirements-validator/references/smart-criteria.md": "619a33fdb6bc336872fdf9f1fc91924f8ccd3c2ebef023912124756692b45aef",
106
- ".claude/skills/requirements-validator/SKILL.md": "baa5cf7257de711ad64d4233ff5a26eb4573fb75a3392fda9a75c2c2e5a73ef9",
123
+ ".claude/skills/requirements-validator/SKILL.md": "e50c5269ad181966a81c14ef596946cea67cbf4b8f8f648c90fd66ecad948933",
107
124
  ".claude/skills/reverse-engineering-unicorn/examples/noom-cjm-example.md": "01d33586e26bf093a57a7a1082bf3bdba3af801bb8348a685c0418f76987a0b0",
108
125
  ".claude/skills/reverse-engineering-unicorn/examples/noom-module1-example.md": "7009cf2e2624a1254913ad2e1ff554e7ff675358b0b99bc0632f2e12132663a3",
109
126
  ".claude/skills/reverse-engineering-unicorn/modules/01-intelligence.md": "4af16873637c26baba0d30728748108c79f5b96765de08d54fc65fe1008f4280",
@@ -116,9 +133,9 @@
116
133
  ".claude/skills/reverse-engineering-unicorn/references/blue-ocean-canvas.md": "9256455b4b0f2c8c5aecb472e69cfbeda38bed8239120b45b46beec27571f8f9",
117
134
  ".claude/skills/reverse-engineering-unicorn/references/industry-benchmarks.md": "d377f4d9e84b8b65860fb4d20ce67d928f8a8fc8ef333658f88c8c54674eed71",
118
135
  ".claude/skills/reverse-engineering-unicorn/references/jtbd-canvas.md": "7938e657af631109ca7b4752002c21ac84a7dad3a35cc522be088f814d102773",
119
- ".claude/skills/reverse-engineering-unicorn/SKILL.md": "ad667aa11254dcd0612689efc3bccd95db537720f5e5846583efe21c631a9375",
136
+ ".claude/skills/reverse-engineering-unicorn/SKILL.md": "20d6b667971f9749d091c1d47e2f75df957f259647cbb861ac54174280096c71",
120
137
  ".claude/skills/sparc-prd-mini/references/sparc-methodology.md": "9c93dafe8149590809ff6b27508d7df52c8efa7f31f8e8f8052b7124a6561fee",
121
- ".claude/skills/sparc-prd-mini/SKILL.md": "2555c4de0edce73f6c2f637db1d839900c7fa27a7d25ca88ec0cf5a70a47325d",
138
+ ".claude/skills/sparc-prd-mini/SKILL.md": "50e829635b828b444487e4b04219518a595dbd4b94f91b66fb03ddf4a7b21712",
122
139
  ".claude/skills/sparc-prd-mini/templates/CLAUDE.md": "9eeb66752cc4dec5c3c3fa5a8f7cfc3dd282f75d245bd36835f690a945b534ed",
123
140
  ".claude/skills/sparc-prd-mini/templates/prd.md": "7b4497bc76bb421fae7a07ecb46af01e021412180a394a5487a3c3c42dc004b6"
124
141
  }
@@ -44,7 +44,8 @@ function sha256(filePath) {
44
44
  function main() {
45
45
  if (!fs.existsSync(TEMPLATES)) {
46
46
  console.error(`[snapshot] templates/ not found at ${TEMPLATES}`);
47
- console.error('[snapshot] Run prepublishOnly first: node scripts/sync-templates.js');
47
+ console.error('[snapshot] templates/ ships with this package — a missing one means a broken');
48
+ console.error('[snapshot] checkout, not a missing build step. Restore it from git.');
48
49
  process.exit(1);
49
50
  }
50
51
 
@@ -0,0 +1,137 @@
1
+ 'use strict';
2
+
3
+ // /replicate writes docs/ADR.md in Phase 1 — commands/replicate.md:243, "(if applicable)" — and
4
+ // nothing ever reads it again. A decision could be written down, agreed, and quietly not built.
5
+ //
6
+ // This cannot be a script: MEASURED, `find templates -name '*.mjs' -o -name 'check*.js'` returns
7
+ // nothing — the templates carry no executable gate at all. It is a mandatory prose step held by this
8
+ // test, the shape that shipped for scenario coverage the day before.
9
+ //
10
+ // TWO TRAPS INHERITED VERBATIM from that sibling, both found the expensive way:
11
+ // - PLACEMENT. A step inside the fenced [MANUAL] checkpoint block is skipped by an AUTO run, so a
12
+ // "mandatory" step would run in half of runs. "Precedes the checkpoint text" and "outside the
13
+ // MANUAL-only block" are two different facts and only the second is the property.
14
+ // - BOTH DIRECTIONS. A one-way check lets a reference to a decision nobody wrote read exactly like
15
+ // coverage.
16
+ //
17
+ // WHAT THIS CLAIMS, and the artifact says so itself: a decision is NAMED downstream. NOT that it was
18
+ // implemented — no comparison of identifiers can establish that. The nearest precedent, the K2 gate,
19
+ // records the same limit about its own coverage check in its own source.
20
+
21
+ const { test, describe } = require('node:test');
22
+ const assert = require('node:assert/strict');
23
+ const fs = require('node:fs');
24
+ const path = require('node:path');
25
+
26
+ const REPLICATE = path.join(__dirname, '..', '..', 'templates', '.claude', 'commands',
27
+ 'replicate.md');
28
+ const read = () => fs.readFileSync(REPLICATE, 'utf-8');
29
+
30
+ /** Phase 2, from its heading to Phase 3's. */
31
+ function phase2(src) {
32
+ const start = src.indexOf('### Phase 2: VALIDATION');
33
+ const end = src.indexOf('### Phase 3', start + 1);
34
+ assert.ok(start > 0 && end > start, 'replicate.md must have a Phase 2 before Phase 3');
35
+ return { start, end, text: src.slice(start, end) };
36
+ }
37
+
38
+ describe('a recorded decision cannot be quietly left unbuilt (PR-007 G5)', () => {
39
+ test('P1 — the step is INSIDE Phase 2 and OUTSIDE the [MANUAL] checkpoint block', () => {
40
+ const src = read();
41
+ const { text } = phase2(src);
42
+ const step = text.indexOf('**Шаг 2.9 — ПОКРЫТИЕ РЕШЕНИЙ');
43
+ assert.ok(step > 0, 'the coverage step must live inside Phase 2');
44
+
45
+ const checkpoint = text.indexOf('**Checkpoint:**');
46
+ assert.ok(checkpoint > step,
47
+ 'and BEFORE the checkpoint, not after it: ' + step + ' vs ' + checkpoint);
48
+
49
+ // The checkpoint's body is a fenced block an AUTO run may skip. The step must not be in it —
50
+ // and this is asserted from the FENCE, not inferred from the ordering above, because those are
51
+ // two different facts and the sibling feature shipped the weaker one first.
52
+ const fenceStart = text.indexOf('```', checkpoint);
53
+ const fenceEnd = text.indexOf('```', fenceStart + 3);
54
+ assert.ok(fenceStart > 0 && fenceEnd > fenceStart, 'the checkpoint must have a fenced body');
55
+ assert.ok(step < fenceStart || step > fenceEnd,
56
+ 'the step sits inside the MANUAL-only fenced block, where an AUTO run skips it');
57
+ });
58
+
59
+ test('P2 — the reconciliation runs BOTH ways, and both may say none', () => {
60
+ const { text } = phase2(read());
61
+ assert.match(text, /Recorded but named nowhere:/,
62
+ 'decisions nobody mentions must be listed');
63
+ assert.match(text, /Named downstream but absent from docs\/ADR\.md:/,
64
+ 'and references matching no decision — without this, a dangling ADR-009 reads as coverage');
65
+ assert.match(text, /Both tables are required, and both may be the single word `none`/,
66
+ 'an empty table and a forgotten table look identical');
67
+ });
68
+
69
+ test('P3 — the block is required in EVERY case, including all-covered', () => {
70
+ const { text } = phase2(read());
71
+ assert.match(text, /## Decision Coverage/,
72
+ 'the required output block must be named, or "reconcile" is advice');
73
+ assert.match(text, /in every case\*\*, including\s+the one where everything is covered/,
74
+ 'an absent block and a block saying "all covered" are indistinguishable to the next reader');
75
+ });
76
+
77
+ test('P4 — three states of the ADR file, each with its own line', () => {
78
+ // Cross-family QE found two defects here. The first version had ONE empty case, so an ADR file
79
+ // that exists but records no ids was unclassified. And its sentence claimed the project "recorded
80
+ // no architectural decisions" — which absence of one FILE cannot establish; decisions may live
81
+ // where this step does not look, and asserting otherwise is a false claim in a generated report.
82
+ const { text } = phase2(read());
83
+ assert.match(text, /Three states of the ADR file/, 'all three must be enumerated');
84
+ assert.match(text, /docs\/ADR\.md is absent, so no decision ids were collected from it/,
85
+ 'the absent case must say what is absent — the FILE — and nothing more');
86
+ assert.ok(!/recorded no architectural decisions/.test(text),
87
+ 'the step must not claim what it cannot see: decisions may live elsewhere');
88
+ assert.match(text, /exists but records no decision ids/,
89
+ 'a present-but-empty ADR is a third state, not the same as an absent file');
90
+ assert.match(text, /In all three states the second table\s*\n?still runs/,
91
+ 'a dangling reference is a defect whether or not an ADR file was ever written');
92
+ });
93
+
94
+ test('P7 — the searched files are ENUMERATED, and the two self-defeating ones excluded', () => {
95
+ // The finding that mattered most: "across the SPARC documents" did not exclude docs/ADR.md, whose
96
+ // own headings contain every id — so every decision appeared named and the check passed BY
97
+ // CONSTRUCTION, on any project. And docs/validation-report.md is where this step WRITES, so
98
+ // counting it would let the previous run's output satisfy the next one.
99
+ const { text } = phase2(read());
100
+ assert.match(text, /Where to look, named file by file/,
101
+ 'the search set must be enumerated, not described');
102
+ for (const f of ['docs/PRD.md', 'docs/Specification.md', 'docs/Architecture.md']) {
103
+ assert.ok(text.includes(f), 'the search set must name: ' + f);
104
+ }
105
+ assert.match(text, /Two files are EXCLUDED/, 'and the exclusions must be explicit');
106
+ assert.match(text, /the check would pass by construction/,
107
+ 'with the reason for excluding the ADR file itself');
108
+ assert.match(text, /the check would start proving itself/,
109
+ 'and for excluding the report this step writes');
110
+ });
111
+
112
+ test('P8 — a mention is DEFINED, and a superseded decision has a policy', () => {
113
+ const { text } = phase2(read());
114
+ assert.match(text, /The exact token `ADR-<nnn>`, case-sensitive/,
115
+ '"mention" must be defined, or every reader draws a different line');
116
+ assert.match(text, /Not a title, not a paraphrase/,
117
+ 'and what does NOT count must be named too');
118
+ assert.match(text, /A superseded decision needs no current mention/,
119
+ 'an id that outlives its decision needs a stated policy, or it reads as a permanent gap');
120
+ });
121
+
122
+ test('P5 — the artifact states its own limit', () => {
123
+ // A coverage block LOOKS like proof of implementation. The backlog item demanded this restraint
124
+ // explicitly, and the limit belongs in the template a reader sees, not only in a feature report.
125
+ const { text } = phase2(read());
126
+ assert.match(text, /It does NOT establish that the decision was implemented/,
127
+ 'the limit must be written into the artifact');
128
+ assert.match(text, /the decision was written down and then forgotten/,
129
+ 'and the class it DOES catch must be named, so the claim is bounded on both sides');
130
+ });
131
+
132
+ test('P6 — the decision id has a defined form, or there is nothing to trace on', () => {
133
+ const { text } = phase2(read());
134
+ assert.match(text, /`ADR-<nnn>` — three digits, assigned in order, never\s+reused/,
135
+ 'an id without a form and a uniqueness rule is an intention, not an identifier');
136
+ });
137
+ });