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.
- package/README.md +27 -32
- package/dist/auth-ZMBA5HYH.js +13 -0
- package/dist/{bug-TFICZ4OP.js → bug-MOMNYU5J.js} +2 -2
- package/dist/{chunk-43IIEFB2.js → chunk-7ELR6RW6.js} +1 -1
- package/dist/{chunk-IG3H7C7R.js → chunk-ARHCVLQW.js} +4 -4
- package/dist/chunk-AWHINKO2.js +244 -0
- package/dist/{chunk-7RXZTPXY.js → chunk-BSG5XY3C.js} +6 -6
- package/dist/{chunk-AJNKSFHL.js → chunk-CI5E4EX3.js} +80 -5
- package/dist/{chunk-4TZOCXAI.js → chunk-ECEWULAA.js} +1 -1
- package/dist/chunk-EF66S6ZQ.js +1189 -0
- package/dist/chunk-EV5QU5KG.js +18 -0
- package/dist/{chunk-45T2VB5R.js → chunk-IZFUFXDN.js} +98 -237
- package/dist/{chunk-YK5Z6U5A.js → chunk-LE5EJ6I4.js} +23 -20
- package/dist/{chunk-PQS3TQB6.js → chunk-LSLQIPLQ.js} +6 -6
- package/dist/chunk-NQBS7L2F.js +55 -0
- package/dist/chunk-RAM67KA6.js +57 -0
- package/dist/{chunk-Q3GIFHIQ.js → client-PPPOHAVY.js} +4 -3
- package/dist/constants-BES4STNW.js +11 -0
- package/dist/{execute-HWUL2M3B.js → execute-WSCLLLY6.js} +4 -4
- package/dist/geo-IRUGSLZS.js +50 -0
- package/dist/index.js +760 -1239
- package/dist/{interviewer-ZGKR7YQQ.js → interviewer-ZUYQ5ZFJ.js} +2 -2
- package/dist/{keys-3PRAVIRC.js → keys-SQUTA4L2.js} +2 -2
- package/dist/{list-7IBMJCCF.js → list-HZM7DNVS.js} +4 -4
- package/dist/{parallel-4PXJA2QD.js → parallel-MWPBKEEN.js} +5 -6
- package/dist/{plan-HBAUG3KD.js → plan-3Z6M4LE6.js} +3 -3
- package/dist/{preferences-VVFGRNPD.js → preferences-OXVXWARL.js} +2 -2
- package/dist/{ship-KHL6NVC2.js → ship-CTZU6RYR.js} +1 -1
- package/dist/{chunk-ONH6Y3CS.js → tier-selection-5KPN2RF2.js} +7 -28
- package/dist/truth-layer-7N32HKCE.js +19 -0
- package/package.json +2 -2
- package/dist/auth-T4C7OQWO.js +0 -14
- package/dist/chunk-57NSGWWD.js +0 -270
- package/dist/chunk-CFJECC3B.js +0 -495
- package/dist/chunk-GGRW4NTA.js +0 -118
- package/dist/chunk-M4LGRTLC.js +0 -10
- package/dist/client-PHW2C2HB.js +0 -11
- package/dist/constants-XDIWFFPN.js +0 -11
- package/dist/geo-BWH5PUBK.js +0 -20
- package/dist/tier-selection-O5AFLKD6.js +0 -18
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# ArchonDev
|
|
2
2
|
|
|
3
|
-
**AI
|
|
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
|
-
-
|
|
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
|
|
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
|
-
- **
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
109
|
-
| `archon geo schema` | Generate JSON-LD
|
|
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
|
|
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
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
213
|
-
archon github connect # Opens browser for authorization
|
|
214
|
-
archon github status # Verify connection
|
|
216
|
+
Use local execution with BYOK keys:
|
|
215
217
|
|
|
216
|
-
|
|
218
|
+
```bash
|
|
219
|
+
archon config ai
|
|
217
220
|
archon plan "add user settings page"
|
|
218
|
-
archon execute ATOM-001
|
|
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.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
bugReport
|
|
3
|
-
} from "./chunk-
|
|
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,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
|
-
|
|
58
|
-
|
|
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
|
|
66
|
+
message
|
|
63
67
|
};
|
|
64
68
|
}
|
|
65
69
|
const hashMatch = trimmed.match(/^([0-9a-f]{7,40})\s+(.+)/);
|
|
66
|
-
|
|
67
|
-
|
|
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}`) : "";
|