syntropic 0.8.1 → 0.9.1

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/README.md CHANGED
@@ -1,127 +1,127 @@
1
1
  # syntropic
2
2
 
3
- A development methodology for AI-assisted coding. Works with **Claude Code**, **Cursor**, **Windsurf**, **GitHub Copilot**, and **OpenAI Codex**.
3
+ **Ship better software. Prove it on your own code first.**
4
4
 
5
- One command gives your AI coding tools a disciplined development pipeline so they research before they plan, plan before they build, and review before they ship.
5
+ A development methodology for AI-assisted coding. Works with **Claude Code**, **Cursor**, **Windsurf**, **GitHub Copilot**, and **OpenAI Codex**.
6
6
 
7
- ## Quick Start
7
+ ## Try Before You Install
8
8
 
9
9
  ```bash
10
- npx syntropic init my-project
10
+ npx syntropic audit
11
11
  ```
12
12
 
13
- Or add to an existing project:
13
+ Analyses your last 20 git commits for process issues — localhost references, env files in git, commit discipline, fix ratios, governance docs. No install needed. Nothing sent anywhere. See what the methodology catches on **your** code.
14
+
15
+ ## Install
14
16
 
15
17
  ```bash
16
- cd my-project
17
18
  npx syntropic init
18
19
  ```
19
20
 
20
- You'll be asked which AI tools you use. The CLI generates a minimal instruction file for each:
21
+ You get: a disciplined development pipeline, governance doc templates, and a connection to the PRISM methodology network — so your rules stay current as the methodology evolves.
21
22
 
22
- | Tool | File Generated |
23
- |------|---------------|
24
- | Claude Code | `CLAUDE.md` |
25
- | Cursor | `.cursorrules` |
26
- | Windsurf | `.windsurfrules` |
27
- | GitHub Copilot | `.github/copilot-instructions.md` |
28
- | OpenAI Codex | `AGENTS.md` |
23
+ ## What You Get
29
24
 
30
- ## How It Works
25
+ **Evergreen Rules** battle-tested development rules fetched fresh at every cycle:
31
26
 
32
- **Server-served, client-computed.** Your instruction file contains a single bootstrap rule (EG13) that tells your AI tool to fetch the full methodology from the Syntropic server at the start of every development cycle. All rules, agents, and learning data are served fresh — always up to date, zero local files to maintain.
27
+ | Rule | What it prevents | Real-world save |
28
+ |------|-----------------|-----------------|
29
+ | **EG1: Pre-flight** | Localhost refs, broken builds reaching production | Caught 3 localhost references pre-deploy |
30
+ | **EG7: Pipeline** | AI jumping to code without research or planning | Structured 123 features across Full/Lightweight/Minimum cycles |
31
+ | **EG8: Test first** | Untested changes reaching production users | Every fix caught on test page — 12 verified promotions |
32
+ | **EG10: Env hygiene** | Env var corruption (trailing newlines, wrong formats) | Prevented silent API failures across 6 providers |
33
+ | **EG11: Prod sync** | Access control divergence between test and production | Caught lockout bug before 8+ users were affected |
34
+ | **EG14: Doc discipline** | Lost decisions, repeated mistakes, no project memory | Backlog, issues, and ADRs updated every cycle |
33
35
 
34
- Your LLM does all the compute. Syntropic serves the methodology but runs zero inference. Your data stays on your machine.
36
+ **Governance Docs** project management templates your AI assistant reads before every cycle:
35
37
 
36
- ## What You Get
38
+ ```
39
+ .claude/docs/NORTH_STAR.md Your vision, goals, and design principles
40
+ .claude/docs/BACKLOG.md Prioritised work with status tracking
41
+ .claude/docs/ISSUES.md Bug log and iteration tracker
42
+ .claude/docs/adr/ Architectural Decision Records
43
+ ```
37
44
 
38
- **Evergreen Rules (EG1-EG13)** — fetched at runtime from the PRISM network:
45
+ **Pipeline Agents** — research, dev, plan, qa, devops, security — fetched from the PRISM network so they're always up to date.
39
46
 
40
- - **EG1: Pre-Flight Loop** — build must pass, no localhost refs, verify after deploy
41
- - **EG2: Ship and Iterate** — bias to action, only pause for destructive/expensive/irreversible
42
- - **EG3: Hypothesis-Driven Debugging** — state hypothesis, test without code changes, only code if confirmed
43
- - **EG7: Implementation Pipeline** — scale process to task size (Full / Lightweight / Minimum cycle)
44
- - **EG8: Live Site Testing** — test page first, promote to production with approval
45
- - **EG9: Session Continuity** — re-read rules on reset, verify state before proceeding
46
- - **EG13: PRISM Sync** — fetch methodology at cycle start, report at cycle end
47
+ **Health Check** — daily GitHub Action with auto-remediation (npm audit fix PRs).
47
48
 
48
- **Generic Agents** (Claude Code, Codex) — dev, qa, research, plan, devops, security — served from the PRISM network, never cached to disk
49
+ ## Track Record
49
50
 
50
- **Health Check** daily GitHub Action with auto-remediation (npm audit fix PRs)
51
+ Built in production on a real product (27 AI agents, 8-lens analyser, CLI, 7 free tools) over 10 weeks:
51
52
 
52
- **PRISM Network** anonymous networked learning. Your AI tool fetches the latest methodology intelligence at cycle start, and optionally reports anonymous structural metadata at cycle end. Every user's cycles improve the methodology for everyone. Zero inference cost — your LLM does all compute.
53
+ - **123 features shipped**, each through a structured pipeline
54
+ - **12 test→production promotions** — every feature verified on test page first
55
+ - **3 bug classes prevented** by specific EG rules before reaching users
56
+ - **0 undetected production incidents** after methodology adoption
53
57
 
54
- ## Commands
58
+ ## Trust & Privacy
55
59
 
56
- ```bash
57
- # Scaffold a new project
58
- npx syntropic init my-project
60
+ **Everything is local.** Your `.claude/` directory — rules, agents, governance docs — lives in your repo. It's yours.
59
61
 
60
- # Select specific tools
61
- npx syntropic init my-project --tools claude,cursor
62
+ **Telemetry is metadata only.** PRISM learns from anonymous structural metadata about development cycles — never from your code, file contents, or project details. This metadata is what drives methodology improvements: which cycle weights work best for which project shapes, where pipelines break down, what patterns lead to first-pass success.
62
63
 
63
- # Customise project URLs (optional sensible defaults applied)
64
- npx syntropic init my-project --name "My App" --domain myapp.com --test-url /staging --prod-url /
64
+ **What's collected:** cycle weight, phases run, success/failure, tool used, OS, framework detected, file count bucket (1-5 / 6-20 / 21+), governance doc presence.
65
+ **Never collected:** file contents, file names, code, diffs, commit messages, project names, identity, API keys.
65
66
 
66
- # Add a tool to an existing project
67
- npx syntropic add cursor
68
- npx syntropic add windsurf copilot
67
+ **Why it matters.** The PRISM network grows exponentially with contributors. Every anonymous report adds signal — which cycle weights work for which project shapes, where pipelines break down, what patterns lead to first-pass success. More contributors = better data = smarter rules for everyone.
69
68
 
70
- # Run a local health check (EG1 pre-flight)
71
- npx syntropic health
69
+ **Contributors get more.** When telemetry is enabled, your PRISM sync fetches live network benchmarks — real success rates, iteration counts, and pattern intelligence computed from aggregate data across all contributors. When telemetry is disabled, you still get the full EG rules and agents, but benchmarks are static baselines only. No account needed — your identity is a double-hashed device fingerprint ([pseudonymisation details](https://zenodo.org/records/17894441)).
72
70
 
73
- # Manage anonymous telemetry (opt-out, default on)
74
- npx syntropic telemetry status
75
- npx syntropic telemetry disable
76
- npx syntropic telemetry enable
71
+ | | Community (telemetry off) | Contributor (telemetry on) |
72
+ |---|---|---|
73
+ | EG rules | Full | Full |
74
+ | Pipeline agents | Full | Full |
75
+ | Governance docs | Full | Full |
76
+ | Benchmarks | Static baselines | **Live network data** |
77
+ | Pattern intelligence | Frozen snapshot | **Updated from aggregate reports** |
78
+ | Network benefit | None | **Your reports improve rules for everyone** |
77
79
 
78
- # Submit a PRISM cycle report (CLI handles hashing + signing)
79
- npx syntropic report --weight lightweight --phases research,plan,dev,qa,test --success true --iterations 1
80
- ```
80
+ Default: on. Opt out anytime:
81
81
 
82
- ## Existing Projects
83
-
84
- Running `syntropic init` in a project that already has a `CLAUDE.md` or `.cursorrules` will **append** the methodology to your existing file — it never overwrites. A `<!-- syntropic -->` marker prevents duplicate rules on re-runs.
85
-
86
- ## The Methodology
82
+ ```bash
83
+ syntropic telemetry disable
84
+ ```
87
85
 
88
- The core idea: AI coding tools are powerful but undisciplined. Without rules, they jump straight to code, skip investigation, retry failed approaches, and introduce regressions.
86
+ **Clean exit.** Remove everything syntropic added (preserves your governance docs):
89
87
 
90
- Syntropic gives them a process:
88
+ ```bash
89
+ syntropic remove
90
+ ```
91
91
 
92
- 1. **Research** understand the problem before proposing solutions
93
- 2. **Plan** — break work into sequenced steps, identify risks
94
- 3. **Build** — implement with minimal changes, match existing patterns
95
- 4. **Review** — check security, quality, and correctness
96
- 5. **Verify** — test on a live URL, not just locally
92
+ **Inspect the output.** Run `npm pack` on the package everything that ships is plain text templates. The methodology is served from a [public API endpoint](https://www.syntropicworks.com/api/v1/prism/config) you can curl yourself.
97
93
 
98
- Scale the process to the task. A typo fix doesn't need research. A new feature does.
94
+ ## Commands
99
95
 
100
- ## Privacy
96
+ ```bash
97
+ syntropic audit # Analyse git history (no install needed)
98
+ syntropic init [project-name] # Install methodology + docs
99
+ syntropic add cursor windsurf # Add tools to existing project
100
+ syntropic remove # Clean uninstall (preserves docs)
101
+ syntropic health # Run pre-flight checks
102
+ syntropic report # Submit anonymous cycle report
103
+ syntropic telemetry status # Check telemetry setting
104
+ syntropic analyse # Deep-dive analysis (8 philosophy lenses)
105
+ ```
101
106
 
102
- Syntropic collects pseudonymised usage patterns to improve the methodology for everyone. **Default: on (opt-out).**
107
+ ## How It Works
103
108
 
104
- **What is collected:** cycle weight, phases run, success/failure, iteration count, tool, OS, Node.js major version, project shape (has TypeScript/CI/tests, framework, file change bucket).
109
+ Your instruction file contains a bootstrap rule (EG13) that fetches the full methodology from the PRISM network at cycle start. Rules, agents, and patterns are served fresh — always current, zero maintenance. Your LLM does all compute. Syntropic serves the methodology but runs zero inference.
105
110
 
106
- **What is NEVER collected:** file contents, file names, project names, code, diffs, commit messages, user identity, email, API keys.
111
+ The governance docs give your AI assistant project memory it checks priorities before coding and logs issues after. Over time, your docs become a structured record of every decision, bug, and iteration.
107
112
 
108
- **Pseudonymisation:** A random device ID is generated locally at install time. Before transmission, it is hashed client-side with a daily-rotating salt (`SHA-256(device_id + date)`), then hashed again server-side with a separate salt (`SHA-256(client_hash + server_salt)`). Neither the client hash nor the original device ID is stored server-side — only the double-hashed value, which cannot be reversed to identify a device or user. Inspired by [TelemetryDeck's MIT-licensed approach](https://telemetrydeck.com/docs/articles/anonymization-how-it-works/). GDPR-compliant by design.
113
+ ## Existing Projects
109
114
 
110
- Opt out anytime: `npx syntropic telemetry disable`
115
+ Running `syntropic init` in a project that already has a `CLAUDE.md` or `.cursorrules` **appends** the methodology — never overwrites. A `<!-- syntropic -->` marker prevents duplicates.
111
116
 
112
- ## Philosophy
117
+ ## Research
113
118
 
114
- - **Ship and iterate** momentum over perfection
115
- - **Hypothesis-driven** — test before you code
116
- - **Outcome-aligned** — if the user succeeds, do we succeed?
117
- - **No workarounds** — no bypasses, no "fix later", no shortcuts without approval
119
+ The methodology is grounded in published research: [zenodo.org/records/17894441](https://zenodo.org/records/17894441)
118
120
 
119
121
  ## Links
120
122
 
121
123
  - [Website](https://www.syntropicworks.com)
122
- - [GitHub](https://github.com/petercholford-ship-it/syntropic-cli)
123
- - [Research Paper](https://zenodo.org/records/17894441) — the underlying research behind the methodology
124
- - [Intelligent Analyser](https://www.syntropicworks.com/analyser) — deep-dive analysis through 8 philosophy lenses
124
+ - [Intelligent Analyser](https://www.syntropicworks.com/analyser) — deep-dive product analysis through 8 philosophy lenses
125
125
 
126
126
  ## License
127
127
 
package/bin/syntropic.js CHANGED
@@ -14,8 +14,10 @@ const args = process.argv.slice(2);
14
14
  const command = args[0];
15
15
 
16
16
  const COMMANDS = {
17
+ audit: () => require('../commands/audit'),
17
18
  init: () => require('../commands/init'),
18
19
  add: () => require('../commands/add'),
20
+ remove: () => require('../commands/remove'),
19
21
  health: () => require('../commands/health'),
20
22
  telemetry: () => require('../commands/telemetry'),
21
23
  report: () => require('../commands/report'),
@@ -39,8 +41,10 @@ if (!command || args.includes('--help') || args.includes('-h')) {
39
41
  syntropic — Philosophy-as-code development pipeline
40
42
 
41
43
  Usage:
44
+ syntropic audit Analyse your git history for process issues (no install needed)
42
45
  syntropic init [project-name] Scaffold a new project with the Syntropic pipeline
43
46
  syntropic add <tool> [tool...] Add support for another AI tool
47
+ syntropic remove Remove syntropic from this project (preserves your docs)
44
48
  syntropic analyse Analyse your product using 8 philosophy lenses
45
49
  syntropic login Sign in to Syntropic (required for analyse)
46
50
  syntropic logout Sign out
@@ -0,0 +1,293 @@
1
+ /**
2
+ * syntropic audit [--commits <n>]
3
+ *
4
+ * Analyse your git history for development process issues.
5
+ * Proves value on your own code before installing anything.
6
+ * Pure local analysis — sends nothing, requires nothing.
7
+ */
8
+
9
+ const { execSync } = require('child_process');
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ const DEFAULTS = { commits: 20 };
14
+
15
+ function parseFlags(args) {
16
+ const flags = {};
17
+ for (let i = 0; i < args.length; i++) {
18
+ if (args[i] === '--help' || args[i] === '-h') { flags.help = true; continue; }
19
+ if (args[i].startsWith('--')) {
20
+ const key = args[i].replace('--', '');
21
+ flags[key] = args[i + 1] && !args[i + 1].startsWith('--') ? args[++i] : true;
22
+ }
23
+ }
24
+ return flags;
25
+ }
26
+
27
+ function git(cmd) {
28
+ try {
29
+ return execSync(`git ${cmd}`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
30
+ } catch {
31
+ return '';
32
+ }
33
+ }
34
+
35
+ function colour(text, code) {
36
+ if (!process.stdout.isTTY) return text;
37
+ return `\x1b[${code}m${text}\x1b[0m`;
38
+ }
39
+
40
+ const green = (t) => colour(t, '32');
41
+ const yellow = (t) => colour(t, '33');
42
+ const red = (t) => colour(t, '31');
43
+ const dim = (t) => colour(t, '2');
44
+ const bold = (t) => colour(t, '1');
45
+
46
+ function checkLocalhost(n) {
47
+ // Find commits that introduced localhost/127.0.0.1 references
48
+ const log = git(`log --oneline -${n} --format=%H`);
49
+ if (!log) return { issues: 0, detail: '' };
50
+
51
+ const hashes = log.split('\n').filter(Boolean);
52
+ let hits = 0;
53
+ const examples = [];
54
+
55
+ for (const hash of hashes) {
56
+ const diff = git(`diff ${hash}~1 ${hash} -- . ":(exclude)*.lock" ":(exclude)node_modules" 2>/dev/null`);
57
+ if (!diff) continue;
58
+
59
+ const addedLines = diff.split('\n').filter(l => l.startsWith('+') && !l.startsWith('+++'));
60
+ for (const line of addedLines) {
61
+ if (/localhost|127\.0\.0\.1/.test(line) && !/\/\/.*localhost/.test(line.replace(/https?:\/\/localhost/, 'MATCH'))) {
62
+ hits++;
63
+ if (examples.length < 2) {
64
+ const shortHash = hash.slice(0, 7);
65
+ const subject = git(`log --format=%s -1 ${hash}`);
66
+ examples.push(`${shortHash} ${subject}`);
67
+ }
68
+ break; // Count once per commit
69
+ }
70
+ }
71
+ }
72
+
73
+ return {
74
+ issues: hits,
75
+ detail: examples.length ? examples.map(e => ` ${dim(e)}`).join('\n') : '',
76
+ };
77
+ }
78
+
79
+ function checkEnvFiles(n) {
80
+ // Check if .env files are tracked in git
81
+ const tracked = git('ls-files').split('\n');
82
+ const envFiles = tracked.filter(f => {
83
+ const base = path.basename(f);
84
+ // .env.example, .env.sample, .env.template are fine
85
+ return /^\.env($|\.)/.test(base) && !/\.(example|sample|template)$/.test(base);
86
+ });
87
+ return {
88
+ issues: envFiles.length,
89
+ detail: envFiles.length ? envFiles.map(f => ` ${dim(f)}`).join('\n') : '',
90
+ };
91
+ }
92
+
93
+ function checkCommitConventions(n) {
94
+ const log = git(`log --oneline -${n} --no-merges --format=%s`);
95
+ if (!log) return { conventional: 0, total: 0, pct: 0 };
96
+
97
+ const subjects = log.split('\n').filter(Boolean);
98
+ const conventional = subjects.filter(s => /^(feat|fix|refactor|chore|docs|style|perf|test|ci|build|revert|sync|content|debug|security|spec)(\(.+\))?:/.test(s));
99
+
100
+ return {
101
+ conventional: conventional.length,
102
+ total: subjects.length,
103
+ pct: subjects.length > 0 ? Math.round(conventional.length / subjects.length * 100) : 0,
104
+ };
105
+ }
106
+
107
+ function checkFixRatio(n) {
108
+ const log = git(`log --oneline -${n} --no-merges --format=%s`);
109
+ if (!log) return { feats: 0, fixes: 0, ratio: 0, total: 0 };
110
+
111
+ const subjects = log.split('\n').filter(Boolean);
112
+ const feats = subjects.filter(s => /^feat(\(.+\))?:/.test(s)).length;
113
+ const fixes = subjects.filter(s => /^fix(\(.+\))?:/.test(s)).length;
114
+ const total = subjects.length;
115
+
116
+ return { feats, fixes, ratio: total > 0 ? Math.round(fixes / total * 100) : 0, total };
117
+ }
118
+
119
+ function checkFilesPerCommit(n) {
120
+ const log = git(`log --oneline -${n} --no-merges --format=%H`);
121
+ if (!log) return { avg: 0, max: 0 };
122
+
123
+ const hashes = log.split('\n').filter(Boolean);
124
+ const counts = hashes.map(h => {
125
+ const files = git(`diff --name-only ${h}~1 ${h} 2>/dev/null`);
126
+ return files ? files.split('\n').filter(Boolean).length : 0;
127
+ }).filter(c => c > 0);
128
+
129
+ if (counts.length === 0) return { avg: 0, max: 0 };
130
+
131
+ return {
132
+ avg: Math.round(counts.reduce((a, b) => a + b, 0) / counts.length * 10) / 10,
133
+ max: Math.max(...counts),
134
+ };
135
+ }
136
+
137
+ function checkGovernanceDocs() {
138
+ const cwd = process.cwd();
139
+ const docs = {
140
+ north_star: fs.existsSync(path.join(cwd, '.claude', 'docs', 'NORTH_STAR.md')) || fs.existsSync(path.join(cwd, '.claude', 'NORTH_STAR.md')),
141
+ backlog: fs.existsSync(path.join(cwd, '.claude', 'docs', 'BACKLOG.md')),
142
+ issues: fs.existsSync(path.join(cwd, '.claude', 'docs', 'ISSUES.md')),
143
+ adr: fs.existsSync(path.join(cwd, '.claude', 'docs', 'adr')),
144
+ };
145
+ const count = Object.values(docs).filter(Boolean).length;
146
+ return { count, total: 4, docs };
147
+ }
148
+
149
+ function computeScore(results) {
150
+ let score = 5; // Start at 5/10
151
+
152
+ // Localhost issues: -1 per issue, max -2
153
+ score -= Math.min(results.localhost.issues, 2);
154
+
155
+ // Env files tracked: -2 if any
156
+ if (results.envFiles.issues > 0) score -= 2;
157
+
158
+ // Conventional commits: +1 if >70%, +0.5 if >40%
159
+ if (results.conventions.pct >= 70) score += 1;
160
+ else if (results.conventions.pct >= 40) score += 0.5;
161
+
162
+ // Fix ratio: neutral if 30-50%, -0.5 if >60%
163
+ if (results.fixRatio.ratio > 60) score -= 0.5;
164
+
165
+ // Governance docs: +0.5 per doc present
166
+ score += results.governance.count * 0.5;
167
+
168
+ // Avg files per commit: -0.5 if >15 (giant commits)
169
+ if (results.filesPerCommit.avg > 15) score -= 0.5;
170
+
171
+ return Math.max(0, Math.min(10, Math.round(score * 2) / 2));
172
+ }
173
+
174
+ function run(args) {
175
+ const flags = parseFlags(args);
176
+
177
+ if (flags.help) {
178
+ console.log(`
179
+ syntropic audit — Analyse your git history for process issues
180
+
181
+ Usage:
182
+ syntropic audit [options]
183
+ npx syntropic audit (no install needed)
184
+
185
+ Options:
186
+ --commits <n> Number of recent commits to analyse (default: 20)
187
+
188
+ What it checks:
189
+ - Localhost/127.0.0.1 references committed to repo
190
+ - .env files tracked in git
191
+ - Commit message conventions
192
+ - Fix:feature ratio (iteration indicator)
193
+ - Average files per commit (scope discipline)
194
+ - Governance docs (North Star, Backlog, Issues, ADRs)
195
+
196
+ This is a local-only analysis. Nothing is sent anywhere.
197
+ `);
198
+ return;
199
+ }
200
+
201
+ // Check we're in a git repo
202
+ const gitRoot = git('rev-parse --show-toplevel');
203
+ if (!gitRoot) {
204
+ console.error('\n Not a git repository. Run this from a project with git history.\n');
205
+ process.exit(1);
206
+ }
207
+
208
+ const n = parseInt(flags.commits, 10) || DEFAULTS.commits;
209
+ const commitCount = git('rev-list --count HEAD');
210
+ const actualN = Math.min(n, parseInt(commitCount, 10) || n);
211
+
212
+ console.log(`\n ${bold('syntropic audit')} — last ${actualN} commits\n`);
213
+
214
+ // Run all checks
215
+ const results = {
216
+ localhost: checkLocalhost(actualN),
217
+ envFiles: checkEnvFiles(actualN),
218
+ conventions: checkCommitConventions(actualN),
219
+ fixRatio: checkFixRatio(actualN),
220
+ filesPerCommit: checkFilesPerCommit(actualN),
221
+ governance: checkGovernanceDocs(),
222
+ };
223
+
224
+ const score = computeScore(results);
225
+
226
+ // Display results
227
+ const PAD = 24;
228
+
229
+ // EG1: Localhost
230
+ if (results.localhost.issues > 0) {
231
+ console.log(` ${yellow('⚠')} ${'EG1 Pre-flight'.padEnd(PAD)} ${yellow(`${results.localhost.issues} commit${results.localhost.issues > 1 ? 's' : ''} contain localhost references`)}`);
232
+ if (results.localhost.detail) console.log(results.localhost.detail);
233
+ } else {
234
+ console.log(` ${green('✓')} ${'EG1 Pre-flight'.padEnd(PAD)} ${green('No localhost references found')}`);
235
+ }
236
+
237
+ // EG10: Env files
238
+ if (results.envFiles.issues > 0) {
239
+ console.log(` ${red('✗')} ${'EG10 Env hygiene'.padEnd(PAD)} ${red(`${results.envFiles.issues} .env file${results.envFiles.issues > 1 ? 's' : ''} tracked in git`)}`);
240
+ if (results.envFiles.detail) console.log(results.envFiles.detail);
241
+ } else {
242
+ console.log(` ${green('✓')} ${'EG10 Env hygiene'.padEnd(PAD)} ${green('No .env files tracked')}`);
243
+ }
244
+
245
+ // Commit conventions
246
+ const convPct = results.conventions.pct;
247
+ const convIcon = convPct >= 70 ? green('✓') : convPct >= 40 ? yellow('⚠') : red('✗');
248
+ const convColour = convPct >= 70 ? green : convPct >= 40 ? yellow : red;
249
+ console.log(` ${convIcon} ${'Commit discipline'.padEnd(PAD)} ${convColour(`${convPct}% conventional commits`)} ${dim(`(${results.conventions.conventional}/${results.conventions.total})`)}`);
250
+
251
+ // Fix ratio
252
+ const fixPct = results.fixRatio.ratio;
253
+ const fixIcon = fixPct <= 50 ? green('✓') : yellow('⚠');
254
+ const fixColour = fixPct <= 50 ? green : yellow;
255
+ console.log(` ${fixIcon} ${'Fix ratio'.padEnd(PAD)} ${fixColour(`${fixPct}% of commits are fixes`)} ${dim(`(${results.fixRatio.fixes} fixes, ${results.fixRatio.feats} features)`)}`);
256
+
257
+ // Files per commit
258
+ const avgFiles = results.filesPerCommit.avg;
259
+ const filesIcon = avgFiles <= 10 ? green('✓') : avgFiles <= 15 ? yellow('⚠') : red('✗');
260
+ const filesColour = avgFiles <= 10 ? green : avgFiles <= 15 ? yellow : red;
261
+ console.log(` ${filesIcon} ${'Scope discipline'.padEnd(PAD)} ${filesColour(`${avgFiles} avg files/commit`)} ${dim(`(max: ${results.filesPerCommit.max})`)}`);
262
+
263
+ // Governance docs
264
+ const govCount = results.governance.count;
265
+ const govIcon = govCount >= 3 ? green('✓') : govCount >= 1 ? yellow('⚠') : dim('○');
266
+ const govColour = govCount >= 3 ? green : govCount >= 1 ? yellow : dim;
267
+ const govNames = [];
268
+ if (results.governance.docs.north_star) govNames.push('North Star');
269
+ if (results.governance.docs.backlog) govNames.push('Backlog');
270
+ if (results.governance.docs.issues) govNames.push('Issues');
271
+ if (results.governance.docs.adr) govNames.push('ADRs');
272
+ console.log(` ${govIcon} ${'Governance docs'.padEnd(PAD)} ${govColour(`${govCount}/4 present`)} ${dim(govNames.length ? `(${govNames.join(', ')})` : '(none)')}`);
273
+
274
+ // Score
275
+ console.log('');
276
+ const scoreColour = score >= 7 ? green : score >= 4 ? yellow : red;
277
+ console.log(` ${bold('Score:')} ${scoreColour(`${score}/10`)}`);
278
+
279
+ // Recommendation
280
+ console.log('');
281
+ if (score >= 8) {
282
+ console.log(` ${green('Strong development discipline.')} Syntropic can keep it that way.`);
283
+ } else if (score >= 5) {
284
+ console.log(` ${yellow('Room for improvement.')} Common issues that a structured pipeline prevents.`);
285
+ } else {
286
+ console.log(` ${red('Significant process gaps.')} A development methodology would catch these early.`);
287
+ }
288
+
289
+ console.log(`\n ${dim('Run `syntropic init` to install the methodology and prevent these automatically.')}`);
290
+ console.log(` ${dim('Learn more: https://www.syntropicworks.com')}\n`);
291
+ }
292
+
293
+ module.exports = run;
package/commands/init.js CHANGED
@@ -186,6 +186,51 @@ function detectTools(targetDir) {
186
186
  return detected;
187
187
  }
188
188
 
189
+ function scaffoldDocs(targetDir, projectName) {
190
+ const docsDir = path.join(targetDir, '.claude', 'docs');
191
+ const adrDir = path.join(docsDir, 'adr');
192
+ const docsTemplateDir = path.join(TEMPLATES_DIR, 'docs');
193
+
194
+ // Skip if docs dir already exists with content
195
+ if (fs.existsSync(docsDir)) {
196
+ const existing = fs.readdirSync(docsDir).filter(f => !f.startsWith('.'));
197
+ if (existing.length > 0) {
198
+ console.log(` skip .claude/docs/ (already exists with ${existing.length} items)`);
199
+ return;
200
+ }
201
+ }
202
+
203
+ if (!fs.existsSync(docsTemplateDir)) return;
204
+
205
+ fs.mkdirSync(adrDir, { recursive: true });
206
+
207
+ const today = new Date().toISOString().slice(0, 10);
208
+ const replacements = {
209
+ '\\{\\{PROJECT_NAME\\}\\}': projectName,
210
+ '\\{\\{CREATED_DATE\\}\\}': today,
211
+ };
212
+
213
+ // Copy doc templates, renaming .template to .md
214
+ const docFiles = [
215
+ { src: 'NORTH_STAR.template', dest: path.join(docsDir, 'NORTH_STAR.md') },
216
+ { src: 'BACKLOG.template', dest: path.join(docsDir, 'BACKLOG.md') },
217
+ { src: 'ISSUES.template', dest: path.join(docsDir, 'ISSUES.md') },
218
+ { src: path.join('adr', '000-TEMPLATE.template'), dest: path.join(adrDir, '000-TEMPLATE.md') },
219
+ ];
220
+
221
+ for (const { src, dest } of docFiles) {
222
+ const srcPath = path.join(docsTemplateDir, src);
223
+ if (!fs.existsSync(srcPath)) continue;
224
+
225
+ let content = fs.readFileSync(srcPath, 'utf8');
226
+ for (const [key, value] of Object.entries(replacements)) {
227
+ content = content.replace(new RegExp(key, 'g'), () => value);
228
+ }
229
+ fs.writeFileSync(dest, content, 'utf8');
230
+ console.log(` create ${path.relative(process.cwd(), dest)}`);
231
+ }
232
+ }
233
+
189
234
  async function run(args) {
190
235
  console.log('\n syntropic init — Philosophy-as-code development pipeline\n');
191
236
 
@@ -261,6 +306,9 @@ async function run(args) {
261
306
  actions[tool] = writeOrAppend(fullTpl, appendTpl, destPath, replacements);
262
307
  }
263
308
 
309
+ // Scaffold governance docs (.claude/docs/)
310
+ scaffoldDocs(targetDir, projectName);
311
+
264
312
  // Make health check executable
265
313
  const healthScript = path.join(targetDir, 'scripts', 'health-check.js');
266
314
  if (fs.existsSync(healthScript)) {
@@ -288,6 +336,7 @@ async function run(args) {
288
336
 
289
337
  What was created:
290
338
  ${toolFiles}
339
+ .claude/docs/ Project governance docs (North Star, Backlog, Issues, ADRs)
291
340
  .github/workflows/ Daily health check with auto-remediation
292
341
  scripts/health-check.js Local health check script${hookLine}
293
342
 
@@ -299,23 +348,26 @@ ${toolFiles}
299
348
  agents, and learning data are always up to date — zero local files to
300
349
  maintain. All compute runs on your machine.
301
350
 
302
- Next steps:
303
- 1. Review your instruction file and add project-specific context
304
- 2. Start building! Your AI will follow the EG7 pipeline automatically
351
+ Your governance docs:
352
+ .claude/docs/NORTH_STAR.md Define your vision, goals, and principles
353
+ .claude/docs/BACKLOG.md Prioritise and track your work
354
+ .claude/docs/ISSUES.md Log bugs and track iterations
355
+ .claude/docs/adr/ Record architectural decisions
305
356
 
306
- Telemetry:
307
- Syntropic collects pseudonymised usage patterns to improve the methodology
308
- for everyone. All identifiers are double-hashed before transmission — no
309
- device ID, code, file names, or personal data is ever stored server-side.
310
- Run \`syntropic telemetry disable\` to opt out at any time.
357
+ These are YOUR docs — they stay even if you remove syntropic.
358
+ Your AI reads them before every cycle and updates them after.
311
359
 
312
- The methodology is your superpower. Ship and iterate.
360
+ Next steps:
361
+ 1. Fill in your North Star — vision, mission, and goals
362
+ 2. Review your instruction file and add project-specific context
363
+ 3. Start building! Your AI follows the EG7 pipeline automatically
313
364
 
314
- Coming soon: \`syntropic analyse\` — assess market opportunity,
315
- validate assumptions, and get a strategic way forward, all from
316
- your CLI. Your LLM, your compute, powered by 8 philosophy lenses.
365
+ Trust & privacy:
366
+ Everything in .claude/ is local and yours. PRISM telemetry is
367
+ pseudonymised (double-hashed) and opt-out: \`syntropic telemetry disable\`.
368
+ Remove everything: \`syntropic remove\` (preserves your docs).
317
369
 
318
- Try the web version now: syntropicworks.com/analyser
370
+ Run \`syntropic audit\` to see what this methodology catches on your existing code.
319
371
 
320
372
  Learn more: https://www.syntropicworks.com
321
373
  `);