archondev 3.0.1 → 3.1.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 (40) hide show
  1. package/README.md +27 -32
  2. package/dist/auth-ZMBA5HYH.js +13 -0
  3. package/dist/{bug-TFICZ4OP.js → bug-MOMNYU5J.js} +2 -2
  4. package/dist/{chunk-43IIEFB2.js → chunk-7ELR6RW6.js} +1 -1
  5. package/dist/{chunk-IG3H7C7R.js → chunk-ARHCVLQW.js} +4 -4
  6. package/dist/chunk-AWHINKO2.js +244 -0
  7. package/dist/{chunk-7RXZTPXY.js → chunk-BSG5XY3C.js} +6 -6
  8. package/dist/{chunk-AJNKSFHL.js → chunk-CI5E4EX3.js} +80 -5
  9. package/dist/{chunk-4TZOCXAI.js → chunk-ECEWULAA.js} +1 -1
  10. package/dist/chunk-EF66S6ZQ.js +1189 -0
  11. package/dist/chunk-EV5QU5KG.js +18 -0
  12. package/dist/{chunk-45T2VB5R.js → chunk-IZFUFXDN.js} +98 -237
  13. package/dist/{chunk-YK5Z6U5A.js → chunk-LE5EJ6I4.js} +23 -20
  14. package/dist/{chunk-PQS3TQB6.js → chunk-LSLQIPLQ.js} +6 -6
  15. package/dist/chunk-NQBS7L2F.js +55 -0
  16. package/dist/chunk-RAM67KA6.js +57 -0
  17. package/dist/{chunk-Q3GIFHIQ.js → client-PPPOHAVY.js} +4 -3
  18. package/dist/constants-BES4STNW.js +11 -0
  19. package/dist/{execute-HWUL2M3B.js → execute-WSCLLLY6.js} +4 -4
  20. package/dist/geo-IRUGSLZS.js +50 -0
  21. package/dist/index.js +760 -1239
  22. package/dist/{interviewer-ZGKR7YQQ.js → interviewer-ZUYQ5ZFJ.js} +2 -2
  23. package/dist/{keys-3PRAVIRC.js → keys-SQUTA4L2.js} +2 -2
  24. package/dist/{list-7IBMJCCF.js → list-HZM7DNVS.js} +4 -4
  25. package/dist/{parallel-4PXJA2QD.js → parallel-MWPBKEEN.js} +5 -6
  26. package/dist/{plan-HBAUG3KD.js → plan-3Z6M4LE6.js} +3 -3
  27. package/dist/{preferences-VVFGRNPD.js → preferences-OXVXWARL.js} +2 -2
  28. package/dist/{ship-KHL6NVC2.js → ship-CTZU6RYR.js} +1 -1
  29. package/dist/{chunk-ONH6Y3CS.js → tier-selection-5KPN2RF2.js} +7 -28
  30. package/dist/truth-layer-7N32HKCE.js +19 -0
  31. package/package.json +2 -2
  32. package/dist/auth-T4C7OQWO.js +0 -14
  33. package/dist/chunk-57NSGWWD.js +0 -270
  34. package/dist/chunk-CFJECC3B.js +0 -495
  35. package/dist/chunk-GGRW4NTA.js +0 -118
  36. package/dist/chunk-M4LGRTLC.js +0 -10
  37. package/dist/client-PHW2C2HB.js +0 -11
  38. package/dist/constants-XDIWFFPN.js +0 -11
  39. package/dist/geo-BWH5PUBK.js +0 -20
  40. package/dist/tier-selection-O5AFLKD6.js +0 -18
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # ArchonDev
2
2
 
3
- **AI Development Governance Stop Babysitting Your AI Agent**
3
+ **Govern AI code with local-first quality gates.**
4
+
5
+ Development governance for code written by AI coding assistants. Reads your architecture file before any change, runs quality gates on every diff, tracks file dependencies so refactors don't silently break callers. Free, local-first, BYOK. Works as a CLI or as drop-in files for Cursor, Claude Code, Windsurf, VS Code + Copilot, Gemini, and the OpenAI Codex CLI.
4
6
 
5
7
  ## Two Ways to Use ArchonDev
6
8
 
@@ -23,7 +25,7 @@ npm install -g archondev; archon
23
25
  - Learning persistence — mistakes are remembered and avoided
24
26
  - **Dependency tracking** — prevent regressions with "what-breaks-what" map
25
27
  - Bug reporting with root cause analysis
26
- - AI-powered code review for any codebase
28
+ - Reviews any codebase against the architecture file you supply, with severity-graded findings
27
29
  - Multi-provider key support with adversarial features
28
30
  - **Risk scoring** — 0-100 risk assessment before every execution
29
31
  - **Ship pipeline** — `archon ship`: review → test → version → changelog → PR
@@ -50,12 +52,12 @@ Context-aware intelligence for your existing AI tools: **Cursor, Claude Code, Wi
50
52
 
51
53
  **Governance Foundation:**
52
54
  - .archon/active/architecture.md template with best practices
53
- - **Quality Level / Posture** — prototype/production/enterprise-grade behavior
55
+ - **Quality Level / Posture** — prototype, production, and enterprise postures each gate behavior differently
54
56
  - **DEPENDENCIES.md** — File-level dependency tracking to prevent regressions
55
57
  - IDE-specific rule files (.cursorrules, CLAUDE.md, GEMINI.md, etc.)
56
- - **24 on-demand AI skills** — Design review, debugging, ship readiness, scope review, accessibility, SEO/GEO, color scheme picker, expert review, features dashboard, and more — loaded only when triggered, keeping context lean
58
+ - **27 on-demand AI skills** — Design review, debugging, ship readiness, truth layer, human memory map, AI-washing audit, scope review, accessibility, SEO/GEO, color scheme picker, expert review, features dashboard, and more — loaded only when triggered, keeping context lean
57
59
  - **Skills-based architecture** — 80% smaller context footprint (8.6 KB core vs 42 KB monolithic). Skills load on-demand with progressive disclosure
58
- - **Claude Code: 16 native slash commands** — `/debug`, `/design-review`, `/ship-readiness`, `/code-review`, `/scope-check`, `/expert-review`, `/geo-optimize`, `/seo-check`, `/accessibility`, `/reflect`, `/handoff`, `/plan-tasks`, `/color-scheme`, `/rollback`, `/dashboard`, `/constitution`
60
+ - **Claude Code: 19 native slash commands** — `/debug`, `/design-review`, `/ship-readiness`, `/code-review`, `/scope-check`, `/expert-review`, `/geo-optimize`, `/seo-check`, `/accessibility`, `/reflect`, `/handoff`, `/plan-tasks`, `/color-scheme`, `/rollback`, `/dashboard`, `/constitution`, `/memory-map`, `/washing-audit`, `/truth-layer`
59
61
  - **GEO Optimization** — 7-phase protocol for AI search citation: identity phrases, atomic claims, JSON-LD schemas, and audit ([free tools](https://archondev.io/geo))
60
62
  - **Task Extraction** — AI confirms all items before starting, nothing gets forgotten
61
63
  - **Context Handoff** — Memory management for long sessions
@@ -80,14 +82,14 @@ pnpm exec tsx scripts/init-governance-db.ts
80
82
  | `archon init` | Initialize in your project |
81
83
  | `archon mode` | Choose local governance mode or BYOK AI mode |
82
84
  | `archon config ai` | Guided BYOK provider-key setup |
83
- | `archon status` | Show local mode, auth, and project status |
85
+ | `archon status` | Show local mode and any old local legacy-session tokens |
84
86
  | `archon plan <description>` | Create a work item with AI planning (extracts and confirms multi-item requests) |
85
87
  | `archon execute <atom-id>` | Execute with quality gates |
86
88
  | `archon list` | List all work items |
87
89
  | `archon show <atom-id>` | Show details |
88
90
  | `archon watch` | Live TUI dashboard with status |
89
91
  | `archon bug report <title>` | Bug report with root cause analysis |
90
- | `archon review init` | Initialize AI-powered code review |
92
+ | `archon review init` | Initialize the local code review database |
91
93
  | `archon review analyze` | Scan project and populate review tasks |
92
94
  | `archon review run` | Run AI review on pending tasks |
93
95
  | `archon usage` | Usage by period and model |
@@ -105,8 +107,15 @@ pnpm exec tsx scripts/init-governance-db.ts
105
107
  | `archon a11y pre-deploy` | Interactive pre-deployment check |
106
108
  | `archon seo check` | Run SEO meta tag audit |
107
109
  | `archon seo fix` | Apply recommended SEO fixes |
108
- | `archon geo identity` | Generate brand identity phrases for AI citation |
109
- | `archon geo schema` | Generate JSON-LD schemas |
110
+ | `archon geo identity` | Generate 7-word phrase + 50-word description + businessContext/audienceContext artifacts |
111
+ | `archon geo schema` | Generate Organization + Service + WebSite JSON-LD |
112
+ | `archon geo faq` | Generate FAQPage JSON-LD (sentence-budget validated) |
113
+ | `archon geo claims` | Generate atomic claims (≤18 tokens each) for agent citation |
114
+ | `archon geo audit` | Agent Clarity Audit — multi-surface walk (homepage, pricing, docs, comparison, etc.) |
115
+ | `archon geo washing-audit` | AI-Washing Risk Register — find unsupported claims, defensible rewrites |
116
+ | `archon truth-layer init` | Create `.archon/truth-layer.md` — the living claims-and-evidence artifact |
117
+ | `archon truth-layer audit` | Compare truth layer to public surfaces; flag gaps |
118
+ | `archon brand memory-map` | Human Memory Map — pressure-test what humans actually remember |
110
119
  | `archon governance status` | Show governance status (AGD) |
111
120
  | `archon governance architecture update` | Update architecture with change reason |
112
121
  | `archon governance task update` | Update governance tasks |
@@ -173,7 +182,7 @@ No Archon token markup. You pay your LLM provider directly at their published ra
173
182
  ```bash
174
183
  $ archon
175
184
 
176
- ArchonDev - AI-Powered Development Governance
185
+ ArchonDev Development Governance for AI-Assisted Code
177
186
  ────────────────────────────────────────────────
178
187
 
179
188
  AI mode: Local governance only
@@ -195,38 +204,24 @@ Type these anytime during interactive prompts:
195
204
  | Command | Description |
196
205
  |---------|-------------|
197
206
  | `config ai` | Open BYOK key setup |
198
- | `status` | Show local mode and optional auth info |
207
+ | `status` | Show local mode and old legacy-session token status |
199
208
  | `keys` | List configured API keys |
200
209
  | `help` | Show available commands |
201
210
  | `quit` | Exit ArchonDev |
202
211
 
203
- ## Cloud Execution (Legacy)
204
-
205
- These commands are preserved only for backward compatibility and are hidden from the normal CLI surface.
206
- They are not part of the current local-first product path.
212
+ ## Retired Remote Paths
207
213
 
208
- ```bash
209
- # 1. Authenticate
210
- archon login
214
+ Platform login, GitHub OAuth, cloud execution, cloud sessions, Supabase usage tracking, Stripe credits, and remote model-registry sync are retired for the current product. Hidden compatibility commands now print a retirement message instead of calling Supabase or Fly.
211
215
 
212
- # 2. Connect GitHub (one-time setup)
213
- archon github connect # Opens browser for authorization
214
- archon github status # Verify connection
216
+ Use local execution with BYOK keys:
215
217
 
216
- # 3. Plan locally, execute in cloud
218
+ ```bash
219
+ archon config ai
217
220
  archon plan "add user settings page"
218
- archon execute ATOM-001 --cloud
219
-
220
- # 3b. Queue multiple atoms in parallel (legacy command; disabled in free/BYOK mode)
221
- archon parallel cloud ATOM-001 ATOM-002
222
-
223
- # 4. Check progress
224
- archon cloud status # List all cloud executions
225
- archon cloud logs <id> # View execution logs
221
+ archon execute ATOM-001
222
+ archon usage
226
223
  ```
227
224
 
228
- Cloud execution is currently disabled in the free/BYOK model. Use local execution with BYOK keys.
229
-
230
225
  ## Working with Existing Projects
231
226
 
232
227
  Have a project created by another AI agent? ArchonDev can review it first, then govern future changes.
@@ -0,0 +1,13 @@
1
+ import {
2
+ login,
3
+ logout,
4
+ status
5
+ } from "./chunk-RAM67KA6.js";
6
+ import "./chunk-EV5QU5KG.js";
7
+ import "./chunk-NQBS7L2F.js";
8
+ import "./chunk-4VNS5WPM.js";
9
+ export {
10
+ login,
11
+ logout,
12
+ status
13
+ };
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  bugReport
3
- } from "./chunk-4TZOCXAI.js";
3
+ } from "./chunk-ECEWULAA.js";
4
4
  import "./chunk-IYZN6FPJ.js";
5
5
  import "./chunk-D3TVDCJA.js";
6
6
  import "./chunk-NIIFUBOE.js";
7
+ import "./chunk-NQBS7L2F.js";
7
8
  import "./chunk-7C6JELBL.js";
8
- import "./chunk-GGRW4NTA.js";
9
9
  import "./chunk-4VNS5WPM.js";
10
10
  export {
11
11
  bugReport
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  listLocalAtoms
3
- } from "./chunk-7RXZTPXY.js";
3
+ } from "./chunk-BSG5XY3C.js";
4
4
 
5
5
  // src/cli/list.ts
6
6
  import chalk from "chalk";
@@ -1,13 +1,13 @@
1
+ import {
2
+ loadConfig,
3
+ saveConfig
4
+ } from "./chunk-NQBS7L2F.js";
1
5
  import {
2
6
  KeyValidator
3
7
  } from "./chunk-TFSHS7EN.js";
4
8
  import {
5
9
  keyManager
6
10
  } from "./chunk-RDG5BUED.js";
7
- import {
8
- loadConfig,
9
- saveConfig
10
- } from "./chunk-GGRW4NTA.js";
11
11
 
12
12
  // src/cli/keys.ts
13
13
  import chalk from "chalk";
@@ -0,0 +1,244 @@
1
+ import {
2
+ BANNED_WORDS_AI_WASHING,
3
+ BANNED_WORDS_GENERIC,
4
+ detectSurfaces
5
+ } from "./chunk-EF66S6ZQ.js";
6
+ import {
7
+ ArchitectAgent
8
+ } from "./chunk-D3TVDCJA.js";
9
+
10
+ // src/cli/truth-layer.ts
11
+ import { Command } from "commander";
12
+ import chalk from "chalk";
13
+ import { readFile, writeFile, mkdir } from "fs/promises";
14
+ import { existsSync } from "fs";
15
+ import { join } from "path";
16
+ var TRUTH_LAYER_PATH = ".archon/truth-layer.md";
17
+ var TRUTH_LAYER_TEMPLATE = `# Truth Layer
18
+
19
+ Living infrastructure. Sales, product, marketing, and AI agents all read from this. Update it as reality changes.
20
+
21
+ > Edit freely. This file is the source of truth for every content-touching command. If a claim is not in here, do not publish it.
22
+
23
+ ## Identity
24
+
25
+ - **7-word phrase:** _(pulled from .archon/config.yaml after \`archon geo identity\`)_
26
+ - **50-word description:** _(same)_
27
+ - **businessContext:** _(see .archon/geo/context.md)_
28
+ - **audienceContext:** _(see .archon/geo/context.md)_
29
+
30
+ ## Claims and Evidence
31
+
32
+ Every claim made on a public surface must appear in this table with at least one piece of evidence. If you cannot fill the Evidence column, the claim is AI-washing and must be rewritten or removed.
33
+
34
+ | Claim | Where it appears | Evidence | Owner | Last verified |
35
+ |-------|------------------|----------|-------|---------------|
36
+ | _example: "Cuts onboarding time 60% for healthcare teams"_ | homepage hero, pricing | Customer case study X (link, date) | _name_ | YYYY-MM-DD |
37
+
38
+ ## Customer Language Library
39
+
40
+ Phrases that came from real customers \u2014 interviews, calls, reviews. Do not paraphrase.
41
+
42
+ - _example: "I stopped having to babysit the agent" \u2014 Sarah, healthcare ops, 2026-03-12_
43
+
44
+ ## Proof Library
45
+
46
+ Numbers, named outcomes, named integrations, named customers, named references.
47
+
48
+ - _example: 12,000 active developers as of 2026-04-01_
49
+ - _example: integrates with Stripe, Cursor, GitHub_
50
+
51
+ ## Competitive Positioning
52
+
53
+ Three direct comparisons. What we beat, what beats us, what is genuinely a tie.
54
+
55
+ | Competitor | We beat them on | They beat us on |
56
+ |------------|-----------------|-----------------|
57
+ | _example: CompetitorX_ | local-first, no-cloud, BYOK | enterprise SSO |
58
+
59
+ ## Constraints (What we do NOT do)
60
+
61
+ - _example: We do not host customer data._
62
+ - _example: We do not run AI without a user-supplied key._
63
+
64
+ Stating what the product does NOT do is high-leverage for agent legibility. Agents reading vague capability claims often invent capabilities; constraints anchor reality.
65
+
66
+ ## Pricing Logic
67
+
68
+ Why it costs what it costs. What each tier actually gates. If pricing is intentionally hidden, document why.
69
+
70
+ - _example: Free is the full product. The CLI is BYOK. We make money on Pro for teams >5._
71
+
72
+ ## Objection Bank
73
+
74
+ Top 10 objections + the honest response.
75
+
76
+ | Objection | Honest response |
77
+ |-----------|-----------------|
78
+ | _example: "Doesn't the AI just write whatever it wants?"_ | _example: No \u2014 quality gates block changes that violate architecture invariants. See \`archon governance\`._ |
79
+
80
+ ## Category Beliefs
81
+
82
+ The 2\u20133 things this company believes about its market that competitors do not. These are NOT taglines. These are the underlying convictions that produce the strategy.
83
+
84
+ - _example: "AI quality cannot be a layer you add. It has to be where the code-writing happens."_
85
+
86
+ ## Memorability Test
87
+
88
+ What is the ONE thing you want a human to carry into an agent prompt six months from now? Pass the competitor test \u2014 could any competitor honestly write the same line?
89
+
90
+ - _intended memory:_ _(fill in)_
91
+ - _competitor test:_ _(could any direct competitor say this? if yes, sharpen.)_
92
+
93
+ ---
94
+
95
+ _Generated by \`archon truth-layer init\`. Re-generate with \`archon truth-layer audit\`._
96
+ `;
97
+ async function truthLayerInit() {
98
+ const cwd = process.cwd();
99
+ const fullPath = join(cwd, TRUTH_LAYER_PATH);
100
+ if (existsSync(fullPath)) {
101
+ console.log(chalk.yellow(`Truth Layer already exists at ${TRUTH_LAYER_PATH}.`));
102
+ console.log(chalk.dim(`Edit it directly, or run 'archon truth-layer audit' to scan it for gaps.`));
103
+ return;
104
+ }
105
+ const archonDir = join(cwd, ".archon");
106
+ if (!existsSync(archonDir)) await mkdir(archonDir, { recursive: true });
107
+ await writeFile(fullPath, TRUTH_LAYER_TEMPLATE, "utf-8");
108
+ console.log(chalk.green(`\u2705 Truth Layer initialized at ${TRUTH_LAYER_PATH}`));
109
+ console.log();
110
+ console.log(chalk.bold("Next steps:"));
111
+ console.log(chalk.dim(` 1. Open ${TRUTH_LAYER_PATH} and fill in the sections marked _example_.`));
112
+ console.log(chalk.dim(` 2. Run 'archon geo identity' to populate the Identity section.`));
113
+ console.log(chalk.dim(` 3. Run 'archon truth-layer audit' to find unsupported claims in your copy.`));
114
+ }
115
+ var TRUTH_LAYER_AUDIT_PROMPT = `You audit a company's truth layer against its public surfaces. Your job is to find:
116
+ 1. Claims that appear publicly but are NOT in the truth layer's claims-and-evidence table.
117
+ 2. Constraints implied by the product but not declared in the constraints section.
118
+ 3. Customer language used publicly that was synthesized rather than sourced.
119
+ 4. Inconsistencies between the truth layer and what surfaces actually say.
120
+
121
+ Be direct. Do not soften findings.
122
+
123
+ Output strict JSON.`;
124
+ async function truthLayerAudit() {
125
+ const cwd = process.cwd();
126
+ const truthPath = join(cwd, TRUTH_LAYER_PATH);
127
+ console.log(chalk.blue("\n\u{1F4D0} Truth Layer Audit\n"));
128
+ if (!existsSync(truthPath)) {
129
+ console.log(chalk.yellow(`No truth-layer.md found.`));
130
+ console.log(chalk.dim(`Run 'archon truth-layer init' first.
131
+ `));
132
+ return [];
133
+ }
134
+ const truthLayer = await readFile(truthPath, "utf-8");
135
+ const surfaces = await detectSurfaces(cwd);
136
+ if (surfaces.length === 0) {
137
+ console.log(chalk.yellow("No public surfaces detected to audit against."));
138
+ return [];
139
+ }
140
+ const corpus = surfaces.map((s) => `--- ${s.label} ---
141
+ ${s.content.slice(0, 4e3)}`).join("\n\n");
142
+ console.log(chalk.dim(`Comparing truth layer against ${surfaces.length} surface(s)...
143
+ `));
144
+ const agent = new ArchitectAgent({ temperature: 0.3 });
145
+ const prompt = `Truth Layer:
146
+
147
+ ${truthLayer}
148
+
149
+ Public surfaces:
150
+
151
+ ${corpus}
152
+
153
+ Audit. Output JSON:
154
+ {
155
+ "gaps": [
156
+ {
157
+ "type": "unbacked-claim|missing-constraint|synthetic-language|inconsistency",
158
+ "description": "what is the problem",
159
+ "surface": "which surface this came from",
160
+ "recommendation": "what to do \u2014 add to truth layer OR remove from copy"
161
+ }
162
+ ]
163
+ }`;
164
+ const response = await agent.client.chat(
165
+ TRUTH_LAYER_AUDIT_PROMPT,
166
+ prompt,
167
+ { temperature: 0.3, maxTokens: 3e3 }
168
+ );
169
+ const jsonMatch = response.content.match(/\{[\s\S]*\}/);
170
+ if (!jsonMatch) {
171
+ console.log(chalk.red("Failed to parse audit response."));
172
+ return [];
173
+ }
174
+ const parsed = JSON.parse(jsonMatch[0]);
175
+ const gaps = parsed.gaps ?? [];
176
+ const lower = truthLayer.toLowerCase();
177
+ for (const banned of [...BANNED_WORDS_GENERIC, ...BANNED_WORDS_AI_WASHING]) {
178
+ if (lower.includes(banned.toLowerCase())) {
179
+ gaps.push({
180
+ type: "synthetic-language",
181
+ description: `Banned filler word "${banned}" appears in the truth layer itself.`,
182
+ surface: "truth-layer.md",
183
+ recommendation: "Replace with specific, defensible language."
184
+ });
185
+ }
186
+ }
187
+ if (gaps.length === 0) {
188
+ console.log(chalk.green("\u2705 No gaps found between truth layer and public surfaces."));
189
+ return [];
190
+ }
191
+ console.log(chalk.bold(`Found ${gaps.length} gap(s):
192
+ `));
193
+ const byType = {
194
+ "unbacked-claim": [],
195
+ "missing-constraint": [],
196
+ "synthetic-language": [],
197
+ inconsistency: []
198
+ };
199
+ for (const g of gaps) byType[g.type]?.push(g);
200
+ for (const t of ["unbacked-claim", "inconsistency", "missing-constraint", "synthetic-language"]) {
201
+ const list = byType[t] ?? [];
202
+ if (list.length === 0) continue;
203
+ console.log(chalk.yellow.bold(` ${t.toUpperCase()} (${list.length})`));
204
+ list.forEach((g, i) => {
205
+ console.log(chalk.yellow(` ${i + 1}. ${g.description}`));
206
+ console.log(chalk.dim(` Surface: ${g.surface}`));
207
+ console.log(chalk.dim(` Recommendation: ${g.recommendation}`));
208
+ });
209
+ console.log();
210
+ }
211
+ return gaps;
212
+ }
213
+ function createTruthLayerCommand() {
214
+ const cmd = new Command("truth-layer").description("Truth Layer \u2014 living infrastructure for claims, evidence, customer language, proof").addHelpText(
215
+ "after",
216
+ `
217
+ Examples:
218
+ archon truth-layer init Create .archon/truth-layer.md from template
219
+ archon truth-layer audit Audit truth layer against detected public surfaces
220
+ `
221
+ );
222
+ cmd.command("init").description("Create .archon/truth-layer.md from template").action(async () => {
223
+ await truthLayerInit();
224
+ });
225
+ cmd.command("audit").description("Find gaps between truth layer and public surfaces").action(async () => {
226
+ await truthLayerAudit();
227
+ });
228
+ cmd.action(async () => {
229
+ const cwd = process.cwd();
230
+ if (!existsSync(join(cwd, TRUTH_LAYER_PATH))) {
231
+ await truthLayerInit();
232
+ } else {
233
+ await truthLayerAudit();
234
+ }
235
+ });
236
+ return cmd;
237
+ }
238
+
239
+ export {
240
+ TRUTH_LAYER_TEMPLATE,
241
+ truthLayerInit,
242
+ truthLayerAudit,
243
+ createTruthLayerCommand
244
+ };
@@ -2,9 +2,6 @@ import {
2
2
  appendLocalUsageEntry,
3
3
  debugLog
4
4
  } from "./chunk-I3BBA7MB.js";
5
- import {
6
- ArchitectureParser
7
- } from "./chunk-5EVHUDQX.js";
8
5
  import {
9
6
  createAtom,
10
7
  validateAtom
@@ -15,15 +12,18 @@ import {
15
12
  import {
16
13
  createAIClient
17
14
  } from "./chunk-NIIFUBOE.js";
15
+ import {
16
+ isAuthenticated
17
+ } from "./chunk-NQBS7L2F.js";
18
+ import {
19
+ ArchitectureParser
20
+ } from "./chunk-5EVHUDQX.js";
18
21
  import {
19
22
  getModelProvider
20
23
  } from "./chunk-7C6JELBL.js";
21
24
  import {
22
25
  KeyManager
23
26
  } from "./chunk-RDG5BUED.js";
24
- import {
25
- isAuthenticated
26
- } from "./chunk-GGRW4NTA.js";
27
27
 
28
28
  // src/cli/plan.ts
29
29
  import chalk from "chalk";
@@ -1,5 +1,7 @@
1
1
  // src/cli/ship.ts
2
2
  import chalk from "chalk";
3
+ import { existsSync as existsSync2 } from "fs";
4
+ import { join as join3 } from "path";
3
5
 
4
6
  // src/core/ship/pipeline.ts
5
7
  import { execSync } from "child_process";
@@ -54,17 +56,21 @@ function parseCommitMessages(commitLines) {
54
56
  return commitLines.map((line) => {
55
57
  const trimmed = line.trim();
56
58
  const match = trimmed.match(/^([a-z]+)(?:\([^)]*\))?[!]?:\s*(.+)/);
57
- if (match) {
58
- const type = match[1];
59
+ const commitType = match?.[1];
60
+ const message = match?.[2];
61
+ if (commitType && message) {
62
+ const type = commitType;
59
63
  const validTypes = ["feat", "fix", "refactor", "docs", "chore"];
60
64
  return {
61
65
  type: validTypes.includes(type) ? type : "other",
62
- message: match[2]
66
+ message
63
67
  };
64
68
  }
65
69
  const hashMatch = trimmed.match(/^([0-9a-f]{7,40})\s+(.+)/);
66
- if (hashMatch) {
67
- return { type: "other", message: hashMatch[2], hash: hashMatch[1] };
70
+ const hash = hashMatch?.[1];
71
+ const hashMessage = hashMatch?.[2];
72
+ if (hash && hashMessage) {
73
+ return { type: "other", message: hashMessage, hash };
68
74
  }
69
75
  return { type: "other", message: trimmed };
70
76
  }).filter((e) => e.message.length > 0);
@@ -400,6 +406,61 @@ async function runPostShipDocCheck(cwd, changedFiles) {
400
406
  // src/cli/ship.ts
401
407
  import { createInterface } from "readline";
402
408
  import { execSync as execSync2 } from "child_process";
409
+ var PUBLIC_COPY_PATTERNS = [
410
+ /^README\.md$/i,
411
+ /(^|\/)CHANGELOG\.md$/i,
412
+ /(^|\/)pricing\./i,
413
+ /(^|\/)index\.(html|astro|tsx|jsx|svelte|vue)$/i,
414
+ /(^|\/)src\/pages\//i,
415
+ /(^|\/)docs\.(html|astro|tsx|jsx|md|mdx)$/i,
416
+ /(^|\/)compare\./i,
417
+ /(^|\/)integrations\./i,
418
+ /(^|\/)customers\./i,
419
+ /(^|\/)case-studies\//i
420
+ ];
421
+ function changeTouchesPublicCopy(files) {
422
+ return files.some((f) => PUBLIC_COPY_PATTERNS.some((p) => p.test(f)));
423
+ }
424
+ async function runCoherenceGate(cwd, options) {
425
+ const truthPath = join3(cwd, ".archon", "truth-layer.md");
426
+ if (!existsSync2(truthPath)) {
427
+ return { blocking: false, message: "No truth-layer.md found \u2014 skipping coherence gate. Consider `archon truth-layer init`." };
428
+ }
429
+ let changedFiles = [];
430
+ try {
431
+ const baseRef = options.baseBranch ?? "main";
432
+ const out = execSync2(`git diff --name-only ${baseRef}...HEAD`, { cwd, encoding: "utf-8" });
433
+ changedFiles = out.split("\n").map((s) => s.trim()).filter(Boolean);
434
+ } catch {
435
+ return { blocking: false, message: "Could not compute changeset \u2014 coherence gate skipped." };
436
+ }
437
+ if (!changeTouchesPublicCopy(changedFiles)) {
438
+ return { blocking: false, message: "No public-facing copy in changeset \u2014 coherence gate not required." };
439
+ }
440
+ console.log(chalk.bold("\nTruth-Layer Coherence Gate"));
441
+ console.log(chalk.dim(` Public-facing copy changed in ${changedFiles.filter((f) => PUBLIC_COPY_PATTERNS.some((p) => p.test(f))).length} file(s).`));
442
+ console.log(chalk.dim(" Running truth-layer audit against detected public surfaces..."));
443
+ try {
444
+ const { truthLayerAudit } = await import("./truth-layer-7N32HKCE.js");
445
+ const gaps = await truthLayerAudit();
446
+ const critical = gaps.filter((g) => g.type === "unbacked-claim" || g.type === "inconsistency");
447
+ if (critical.length > 0) {
448
+ return {
449
+ blocking: true,
450
+ message: `Coherence gate BLOCKED: ${critical.length} unbacked claim(s) or inconsistency(ies) between truth layer and public surfaces.`
451
+ };
452
+ }
453
+ if (gaps.length > 0) {
454
+ return {
455
+ blocking: false,
456
+ message: `Coherence gate: ${gaps.length} non-critical gap(s) (constraints / synthetic language). Review .archon/truth-layer.md after ship.`
457
+ };
458
+ }
459
+ return { blocking: false, message: "Coherence gate: PASSED." };
460
+ } catch (err) {
461
+ return { blocking: false, message: `Coherence gate could not run: ${err.message}` };
462
+ }
463
+ }
403
464
  function createPrompt() {
404
465
  const rl = createInterface({
405
466
  input: process.stdin,
@@ -440,11 +501,25 @@ async function ship(options = {}) {
440
501
  console.log(chalk.dim(" (dry run \u2014 no changes will be made)"));
441
502
  }
442
503
  console.log();
504
+ const gate = await runCoherenceGate(cwd, options);
505
+ if (gate.blocking) {
506
+ console.log(chalk.red(gate.message));
507
+ console.log(chalk.dim("Fix the truth layer or rewrite the offending public copy before shipping."));
508
+ console.log(chalk.dim("Override (not recommended): set ARCHON_SKIP_COHERENCE_GATE=1"));
509
+ if (process.env.ARCHON_SKIP_COHERENCE_GATE !== "1") {
510
+ return;
511
+ }
512
+ console.log(chalk.yellow(" Override applied \u2014 continuing despite coherence gate failure."));
513
+ } else if (gate.message) {
514
+ console.log(chalk.dim(gate.message));
515
+ }
516
+ console.log();
443
517
  const pipeline = new ShipPipeline(cwd, options);
444
518
  const result = await pipeline.run();
445
519
  const totalSteps = result.steps.length;
446
520
  for (let i = 0; i < result.steps.length; i++) {
447
521
  const step = result.steps[i];
522
+ if (!step) continue;
448
523
  const stepNum = `[${i + 1}/${totalSteps}]`;
449
524
  const detail = step.detail ? chalk.dim(` ${step.detail}`) : "";
450
525
  const error = step.error ? chalk.red(` \u2014 ${step.error}`) : "";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-D3TVDCJA.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-GGRW4NTA.js";
9
+ } from "./chunk-NQBS7L2F.js";
10
10
 
11
11
  // src/cli/bug.ts
12
12
  import chalk from "chalk";