@dzhechkov/p-replicator 1.5.13 → 1.5.14

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.
@@ -0,0 +1,125 @@
1
+ {
2
+ "generatedAt": "2026-07-19T15:43:12.046Z",
3
+ "totalFiles": 119,
4
+ "files": {
5
+ ".claude/agents/doc-validator.md": "a46651637239b4f078b5c3022ea2bf9ef4fb84ab2eb529cdc41273c42deaddf5",
6
+ ".claude/agents/harvest-coordinator.md": "70fa884057669902e18744915305705cf9e45e738a83d7bb5ab011a3b72d683c",
7
+ ".claude/agents/product-discoverer.md": "ea341407faa6f31a152508945b24e650c5a71459bbc9e1f91cdab7621660a54d",
8
+ ".claude/agents/replicate-coordinator.md": "e86060110ab188109cf908878206543f414993e14dad01f8dc19f041ee6497a7",
9
+ ".claude/commands/deploy.md": "27f5424ee217163c55e5e6b9322a1f0858159407bd24ebd6d6588d6c22a5f890",
10
+ ".claude/commands/docs.md": "be03592cb3f1d61b60dc96d3e26d71281ad4eb2d4626012c080ce609a32c96e4",
11
+ ".claude/commands/feature.md": "3b605c004ae6d794dee30892956dc0a9536195e828929bdaff134f3e952e87bb",
12
+ ".claude/commands/go.md": "655dc9cad37b61a9f283cef15e435c492ee7cbc88a6ce59295ac32c975dee858",
13
+ ".claude/commands/harvest.md": "c074fe7799f594dda44c5f8166da707f25cee51b12f758dea562a8c1e6ac5dcd",
14
+ ".claude/commands/myinsights.md": "2e73e822384f976383d9c3313940888b9853f1781d2c39a2fb89825f221149dc",
15
+ ".claude/commands/next.md": "c417f86626a91d716cb9b5ed98e1445a0820055b22947da33fc90fc65fe974b2",
16
+ ".claude/commands/plan.md": "6fef889f51168981bf4a98b8392a0d595e3d199e1cfaa8e08c0a181ec6c440e4",
17
+ ".claude/commands/replicate.md": "27fb978d1b4f19169d48795c5ce1a8ad4e5b6a03e9ae478b64857cdeb9d8b4bb",
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",
26
+ ".claude/rules/feature-lifecycle.md": "f9ddc8c889ab7938a7207b36ae46c36be05e9b870956ef16617bf31b2f78c758",
27
+ ".claude/rules/git-workflow.md": "7d8d2ded47fcc0fb95da3dc226efa6cb3c80d6adf7296977588c181dfce20192",
28
+ ".claude/rules/insights-capture.md": "488d694caffe7a32915b0ec1beb7a84b223fe602722c5bb91ab8bf2785626387",
29
+ ".claude/rules/replicate-pipeline.md": "2eaa40ece405b506f0b94818013e2e235be6c9fb3bd73e964dd675afc34b6535",
30
+ ".claude/rules/skill-interface-protocol.md": "fe18fcb9217002572f462f3a7f38de22cdd7ba0dd4e906fdcd0c0e8cfed9f2aa",
31
+ ".claude/settings.json": "1afea754d42e3b2aa7cee0a17a8347ba594427b40daa293ce7b21f3dfd0607c3",
32
+ ".claude/skills/brutal-honesty-review/evals/brutal-honesty-review.yaml": "855c155d55575e12aab23fb3a5fb2fada74d93974ff755dfedac6f2d5bd41f13",
33
+ ".claude/skills/brutal-honesty-review/README.md": "2a026b4af50b21456e50424fbfa089cb983fbbaa0c68024c8c17c695bea25a57",
34
+ ".claude/skills/brutal-honesty-review/resources/assessment-rubrics.md": "dac09c91c765e2211799cc230738fb72a966f47511edb872306a906e49640cbe",
35
+ ".claude/skills/brutal-honesty-review/resources/review-template.md": "95182c8605b1d821360257e1c5dbac4300bda333d861785de417cbb84090b25b",
36
+ ".claude/skills/brutal-honesty-review/schemas/output.json": "2e252a3497b86322e1a6e6bd1aca8708b44389db3a2d81a6f893d467b6351210",
37
+ ".claude/skills/brutal-honesty-review/scripts/assess-code.sh": "7e9722c1533f1b7d1a9d11a7add13ac12a2a5f0acfc0ed2cdede2bcf0dab788f",
38
+ ".claude/skills/brutal-honesty-review/scripts/assess-tests.sh": "8c6444bdb5ce97e49223cdaa6b1c58ac8fcec710cd6ee8d56de9bc677379bd88",
39
+ ".claude/skills/brutal-honesty-review/scripts/validate-config.json": "7418284839f89735d01f50eefdb488b013e0076f6003a67683062429c14984c6",
40
+ ".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/03-generate-p0.md": "b093a5d66663e2dfd6415afef7c7444409f03379f857001b811685ded410038b",
44
+ ".claude/skills/cc-toolkit-generator-enhanced/modules/04-generate-p1.md": "081284d3858c5dd89b45fc8a2b83bbc0477843f864cbceb6d9f8c3629b198a0a",
45
+ ".claude/skills/cc-toolkit-generator-enhanced/modules/05-generate-p2p3.md": "9535eaa5fa1be0804369aa4e8ee6f6f580839ea2c3c7b7aa51584e298a928093",
46
+ ".claude/skills/cc-toolkit-generator-enhanced/modules/06-package-deliver.md": "d7d7effe411b6dc885f2cff04ccc931bed06c9245ebde34c5842d130b0f1e89d",
47
+ ".claude/skills/cc-toolkit-generator-enhanced/modules/07-harvest-feedback.md": "2121fa2e93b0d0e01418d92ca12c2dd2831596ff11a1ec44b436b530198fca91",
48
+ ".claude/skills/cc-toolkit-generator-enhanced/modules/08-skill-composition.md": "1deedef5ee5c7ef1f7fd8a8fb84732d82f872724fc96697bf530c6dbd6d0850a",
49
+ ".claude/skills/cc-toolkit-generator-enhanced/modules/09-cross-project-learning.md": "c395bc42a40ed14c0b8fe274df516082db0490228c82aba6a56f23b8f41d3d43",
50
+ ".claude/skills/cc-toolkit-generator-enhanced/modules/README.md": "9dbcc9c0978d06cbe31caffa909741fdb3a38d3cd1e6e98addf95628ec8394a0",
51
+ ".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/maturity-integration.md": "aa4e743bcd0281525336a298d0489c31481f69ff1a534e1ed1d262d888937deb",
55
+ ".claude/skills/cc-toolkit-generator-enhanced/references/security-patterns-library.md": "5f1d650c426cbd2c9536b385306605ea62a5a520ee4566d23ca7254409c672a5",
56
+ ".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",
58
+ ".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/feature-lifecycle-ent.md": "eb9025b687f0408b33280bf5fcc6c8be9b1670a544dd90b510557b89ae6cc123",
62
+ ".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",
64
+ ".claude/skills/cc-toolkit-generator-enhanced/references/templates/insights-system.md": "244c2ef5f417c5d0097accf5ccfffd9de93d167efbfc6818cb9a8196139e096e",
65
+ ".claude/skills/cc-toolkit-generator-enhanced/references/templates/mcp.md": "63d1e6dabf5bb29534e6fa11d9dd531ec55a48cda661f0faf7a29dad6f49296f",
66
+ ".claude/skills/cc-toolkit-generator-enhanced/references/templates/start-command.md": "67cf259f8d22c1b94c5242c6fd48d557e97581beb162cf176eb2e6851bab1962",
67
+ ".claude/skills/cc-toolkit-generator-enhanced/SKILL.md": "26fb1a3c0961fbb1f5f7e81ec5134bbe49ba0f99175c394cdf0c6b8a35568be2",
68
+ ".claude/skills/explore/references/questioning-techniques.md": "ec0dd00871d3abe950f9cf375216a43043827897166c4165c3fa581839851195",
69
+ ".claude/skills/explore/references/task-brief-templates.md": "4e9292479e120afce944b747bb7b4a7226c41e9880708d620de3ea4fa4ef0249",
70
+ ".claude/skills/explore/SKILL.md": "c755a7bcdfe97fb7cb0bcd7bf3b1fd8a2d238ef082967fbf87740fc808302542",
71
+ ".claude/skills/goap-research-ed25519/references/ed25519-verification.md": "2742f14b472bff69c83f24d9bac5bf023bd7f9ecc3e659742ac3152a239dd68f",
72
+ ".claude/skills/goap-research-ed25519/references/research-actions.md": "156d2f8ce342f7013bc758fe7c0d3ad3041b4f67f30dbcf8d59e091cb70d9a9c",
73
+ ".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",
78
+ ".claude/skills/knowledge-extractor/examples/rate-limiting-extraction.md": "fab68772135532aaa7675dfca4ec068cfa68a847f964f872f201f08fb9ee4034",
79
+ ".claude/skills/knowledge-extractor/modules/01-agent-review.md": "53883f182c26c710190399a23193cddb4a94b0f35bb42169a353f354aae4083a",
80
+ ".claude/skills/knowledge-extractor/modules/02-classify.md": "3b6a59cde451fc89e2e683b7cd35f5535d12cc6072cd40ca35cf7d5f61eb78aa",
81
+ ".claude/skills/knowledge-extractor/modules/03-decontextualize.md": "ecb082116577cb86dfa4f43066d3c6d61b5d4a70964cb9ed4f15c6311d526347",
82
+ ".claude/skills/knowledge-extractor/modules/04-integrate.md": "15a31634dd52e87bcad78a2b612c821dcd11b91ed21f2ddb2cde741411aa287e",
83
+ ".claude/skills/knowledge-extractor/references/artifact-categories.md": "3f8c920f57476272dd4886a792c60d2439b2dabd3f9bbc3dbb3bafc731b46dfe",
84
+ ".claude/skills/knowledge-extractor/references/decontextualization-guide.md": "224ab90bfc6da35fc2bd17039e82f355eb8e1651ad89fd2b4667f7a7f41bd074",
85
+ ".claude/skills/knowledge-extractor/references/maturity-model.md": "d036d0f4d4ccbaab806f4a70a3297b7a9f0700b28f8ce9d32d43699029b814ce",
86
+ ".claude/skills/knowledge-extractor/SKILL.md": "ccfd23ead51b710c5197372e82522d17706a1a4e71143bc6f03d80f913bc0a67",
87
+ ".claude/skills/knowledge-extractor/templates/artifact-card.md": "61b77204be5099f5aa0b7179ef14409efc08873c32fb46df42069782c297521b",
88
+ ".claude/skills/knowledge-extractor/templates/harvest-report.md": "a112dde3d3fab90405ed89c1b4a665003ca70cfc995a8af6a0cf67b2476037c2",
89
+ ".claude/skills/knowledge-extractor/templates/toolkit-harvest.md": "71b4661956eb6dfb6860ff820b4a872bb243161ce4a18e03845b2bd54a70a2c8",
90
+ ".claude/skills/pipeline-forge/examples/replicate-analysis.md": "57e31a5bbf320f383e1a7fc665635ee3ad025d3825d4b1dc6c331bcd9270f146",
91
+ ".claude/skills/pipeline-forge/references/patterns-catalog.md": "94bca28d8df333005c2e8c3511586f05395a141c8c8c0225047f580cbee7e418",
92
+ ".claude/skills/pipeline-forge/references/quality-gates.md": "286a533eac25ca39429b200b66eb43b33092d3e85cd505bfa4c567f6e86b6eea",
93
+ ".claude/skills/pipeline-forge/references/self-extracted-patterns.md": "ad67e502d1b82efd646440d90a2781cf0db3732a1f94294ad0905d0f7338e0b4",
94
+ ".claude/skills/pipeline-forge/references/skill-anatomy.md": "ee91351ad53fdd924f358c4e30a291d5801e03c2c568b10e641edcb90a4ae10b",
95
+ ".claude/skills/pipeline-forge/SKILL.md": "619e4fa03b9d289cfd143b1a0f5fe8e77ddbd48d6846dcaaad601ba4702f3787",
96
+ ".claude/skills/pipeline-forge/templates/agent-template.md": "18ed69f9cce1cc4157f1e43895d6135eac3ff2a6ebd08fb2fb543658564bc3fd",
97
+ ".claude/skills/pipeline-forge/templates/command-template.md": "b91a4ef084ba542801154c8b1fb2a086a6b404c3f7ee809ceb6ea633e2b55245",
98
+ ".claude/skills/pipeline-forge/templates/pipeline-template.md": "952d2e1f050558dacbf86d2b2ad2c9bc671b1ce2809ce430593434998103a27c",
99
+ ".claude/skills/pipeline-forge/templates/skill-template.md": "b92775b4d181fc70ae393645999472ddb64f7419392c12d86b4182b49308df65",
100
+ ".claude/skills/problem-solver-enhanced/SKILL.md": "530623c986dee931d47314c22195ea9de50a75f2a0daecfc469fb015c3dd3415",
101
+ ".claude/skills/requirements-validator/assets/templates/bdd-feature-template.feature": "5b1e47f10447ce574d0eb3917b69e2613b6e3f9c48b30ff5f4cfb57758c99a1d",
102
+ ".claude/skills/requirements-validator/references/bdd-patterns.md": "04611a8c52c81f3a6d4fc2f9661ebc56159a125b6fb44a4d18b432e2b82de6e3",
103
+ ".claude/skills/requirements-validator/references/invest-criteria.md": "ac6976adf776b9b60c784e1a0f6a0d96dd3332b16f4c12b72d3e59f9325bb626",
104
+ ".claude/skills/requirements-validator/references/scoring-system.md": "79d421c79ab2cc594e685c27178368495774a1154e2b65cdbcd2a94cc28e9dbb",
105
+ ".claude/skills/requirements-validator/references/smart-criteria.md": "619a33fdb6bc336872fdf9f1fc91924f8ccd3c2ebef023912124756692b45aef",
106
+ ".claude/skills/requirements-validator/SKILL.md": "baa5cf7257de711ad64d4233ff5a26eb4573fb75a3392fda9a75c2c2e5a73ef9",
107
+ ".claude/skills/reverse-engineering-unicorn/examples/noom-cjm-example.md": "01d33586e26bf093a57a7a1082bf3bdba3af801bb8348a685c0418f76987a0b0",
108
+ ".claude/skills/reverse-engineering-unicorn/examples/noom-module1-example.md": "7009cf2e2624a1254913ad2e1ff554e7ff675358b0b99bc0632f2e12132663a3",
109
+ ".claude/skills/reverse-engineering-unicorn/modules/01-intelligence.md": "4af16873637c26baba0d30728748108c79f5b96765de08d54fc65fe1008f4280",
110
+ ".claude/skills/reverse-engineering-unicorn/modules/02-product-customers.md": "b614e43359ffe88c07d6f45abdb2d3c523fc7779052757ed95bbd31b5ce9408d",
111
+ ".claude/skills/reverse-engineering-unicorn/modules/025-cjm-prototype.md": "0ca044b769a70bcc89bdb5af496471b59104428770d49735e8255fc22da48207",
112
+ ".claude/skills/reverse-engineering-unicorn/modules/03-market-competition.md": "6c5c802ee558b5e13c80eb05e64a8197bad34192416df81ea32f3b0e1b04b259",
113
+ ".claude/skills/reverse-engineering-unicorn/modules/04-business-finance.md": "19d25e9fe9a732d963f2359748ef2c7793bd6282183f84b938351feccea88075",
114
+ ".claude/skills/reverse-engineering-unicorn/modules/05-growth-engine.md": "98e8577aa5a5472574ac9bac590b76a4a3d16f99bc67ebec2b09b604c7c1faab",
115
+ ".claude/skills/reverse-engineering-unicorn/modules/06-playbook-synthesis.md": "f72841226f929cea2c3a414f74b3f1e933e3952f1b55e6eea38081dd804a87cd",
116
+ ".claude/skills/reverse-engineering-unicorn/references/blue-ocean-canvas.md": "9256455b4b0f2c8c5aecb472e69cfbeda38bed8239120b45b46beec27571f8f9",
117
+ ".claude/skills/reverse-engineering-unicorn/references/industry-benchmarks.md": "d377f4d9e84b8b65860fb4d20ce67d928f8a8fc8ef333658f88c8c54674eed71",
118
+ ".claude/skills/reverse-engineering-unicorn/references/jtbd-canvas.md": "7938e657af631109ca7b4752002c21ac84a7dad3a35cc522be088f814d102773",
119
+ ".claude/skills/reverse-engineering-unicorn/SKILL.md": "ad667aa11254dcd0612689efc3bccd95db537720f5e5846583efe21c631a9375",
120
+ ".claude/skills/sparc-prd-mini/references/sparc-methodology.md": "9c93dafe8149590809ff6b27508d7df52c8efa7f31f8e8f8052b7124a6561fee",
121
+ ".claude/skills/sparc-prd-mini/SKILL.md": "2555c4de0edce73f6c2f637db1d839900c7fa27a7d25ca88ec0cf5a70a47325d",
122
+ ".claude/skills/sparc-prd-mini/templates/CLAUDE.md": "9eeb66752cc4dec5c3c3fa5a8f7cfc3dd282f75d245bd36835f690a945b534ed",
123
+ ".claude/skills/sparc-prd-mini/templates/prd.md": "7b4497bc76bb421fae7a07ecb46af01e021412180a394a5487a3c3c42dc004b6"
124
+ }
125
+ }
@@ -0,0 +1,89 @@
1
+ 'use strict';
2
+
3
+ const { test, describe } = require('node:test');
4
+ const assert = require('node:assert/strict');
5
+ const fs = require('node:fs');
6
+ const path = require('node:path');
7
+ const crypto = require('node:crypto');
8
+
9
+ const PKG_DIR = path.resolve(__dirname, '..', '..');
10
+ const TEMPLATES = path.join(PKG_DIR, 'templates');
11
+ const BASELINE = path.join(__dirname, 'baseline.json');
12
+
13
+ function walk(dir, base = dir, out = []) {
14
+ if (!fs.existsSync(dir)) return out;
15
+ for (const entry of fs.readdirSync(dir).sort()) {
16
+ const full = path.join(dir, entry);
17
+ const stat = fs.statSync(full);
18
+ if (stat.isDirectory()) {
19
+ walk(full, base, out);
20
+ } else {
21
+ const rel = path.relative(base, full).split(path.sep).join('/');
22
+ out.push({ rel, full });
23
+ }
24
+ }
25
+ return out;
26
+ }
27
+
28
+ function sha256(p) {
29
+ return crypto.createHash('sha256').update(fs.readFileSync(p)).digest('hex');
30
+ }
31
+
32
+ describe('snapshot: templates/', () => {
33
+ test('baseline.json exists', () => {
34
+ assert.ok(
35
+ fs.existsSync(BASELINE),
36
+ 'tests/snapshot/baseline.json missing — run `npm run snapshot:baseline` to create it'
37
+ );
38
+ });
39
+
40
+ test('current templates match recorded baseline (no drift)', () => {
41
+ const baseline = JSON.parse(fs.readFileSync(BASELINE, 'utf8'));
42
+ const current = walk(TEMPLATES);
43
+ const currentMap = {};
44
+ for (const { rel, full } of current) {
45
+ currentMap[rel] = sha256(full);
46
+ }
47
+
48
+ const baselineKeys = Object.keys(baseline.files);
49
+ const currentKeys = Object.keys(currentMap);
50
+
51
+ const missing = baselineKeys.filter((k) => !(k in currentMap));
52
+ const added = currentKeys.filter((k) => !(k in baseline.files));
53
+ const changed = baselineKeys.filter(
54
+ (k) => k in currentMap && baseline.files[k] !== currentMap[k]
55
+ );
56
+
57
+ if (missing.length || added.length || changed.length) {
58
+ const lines = [];
59
+ if (missing.length) {
60
+ lines.push(`Missing (${missing.length}):\n ${missing.slice(0, 20).join('\n ')}`);
61
+ }
62
+ if (added.length) {
63
+ lines.push(`Added (${added.length}):\n ${added.slice(0, 20).join('\n ')}`);
64
+ }
65
+ if (changed.length) {
66
+ lines.push(`Changed (${changed.length}):\n ${changed.slice(0, 20).join('\n ')}`);
67
+ }
68
+ lines.push('');
69
+ lines.push('If these template changes are intentional, regenerate the baseline:');
70
+ lines.push(' npm run snapshot:baseline');
71
+
72
+ assert.fail(lines.join('\n'));
73
+ }
74
+
75
+ assert.equal(
76
+ currentKeys.length,
77
+ baselineKeys.length,
78
+ `file count mismatch: baseline=${baselineKeys.length}, current=${currentKeys.length}`
79
+ );
80
+ });
81
+
82
+ test('every template file is non-empty', () => {
83
+ const current = walk(TEMPLATES);
84
+ for (const { rel, full } of current) {
85
+ const size = fs.statSync(full).size;
86
+ assert.ok(size > 0, `${rel} is empty (${size} bytes)`);
87
+ }
88
+ });
89
+ });
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * update-baseline.js
6
+ *
7
+ * Computes SHA-256 of every file under templates/ and writes the result to
8
+ * tests/snapshot/baseline.json. Run after intentional template changes:
9
+ *
10
+ * npm run snapshot:baseline
11
+ *
12
+ * The L3 snapshot test (tests/snapshot/templates.test.js) compares the live
13
+ * templates/ tree against this baseline and fails on any drift.
14
+ */
15
+
16
+ const fs = require('node:fs');
17
+ const path = require('node:path');
18
+ const crypto = require('node:crypto');
19
+
20
+ const PKG_DIR = path.resolve(__dirname, '..', '..');
21
+ const TEMPLATES = path.join(PKG_DIR, 'templates');
22
+ const BASELINE = path.join(__dirname, 'baseline.json');
23
+
24
+ function walk(dir, base = dir, out = []) {
25
+ if (!fs.existsSync(dir)) return out;
26
+ for (const entry of fs.readdirSync(dir).sort()) {
27
+ const full = path.join(dir, entry);
28
+ const stat = fs.statSync(full);
29
+ if (stat.isDirectory()) {
30
+ walk(full, base, out);
31
+ } else {
32
+ // Forward slashes — keeps baseline.json identical across Win/Linux/macOS.
33
+ const rel = path.relative(base, full).split(path.sep).join('/');
34
+ out.push({ rel, full });
35
+ }
36
+ }
37
+ return out;
38
+ }
39
+
40
+ function sha256(filePath) {
41
+ return crypto.createHash('sha256').update(fs.readFileSync(filePath)).digest('hex');
42
+ }
43
+
44
+ function main() {
45
+ if (!fs.existsSync(TEMPLATES)) {
46
+ console.error(`[snapshot] templates/ not found at ${TEMPLATES}`);
47
+ console.error('[snapshot] Run prepublishOnly first: node scripts/sync-templates.js');
48
+ process.exit(1);
49
+ }
50
+
51
+ const files = walk(TEMPLATES);
52
+ const sorted = files.sort((a, b) => a.rel.localeCompare(b.rel));
53
+ const fileMap = {};
54
+ for (const { rel, full } of sorted) {
55
+ fileMap[rel] = sha256(full);
56
+ }
57
+
58
+ const baseline = {
59
+ generatedAt: new Date().toISOString(),
60
+ totalFiles: sorted.length,
61
+ files: fileMap,
62
+ };
63
+
64
+ fs.writeFileSync(BASELINE, JSON.stringify(baseline, null, 2) + '\n', 'utf8');
65
+ console.log(`[snapshot] Wrote ${sorted.length} file hashes to ${path.relative(PKG_DIR, BASELINE)}`);
66
+ }
67
+
68
+ main();