@softspark/ai-toolkit 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +16 -3
- package/action.yml +2 -1
- package/app/.claude-plugin/plugin.json +1 -1
- package/app/ARCHITECTURE.md +3 -1
- package/app/agents/documenter.md +2 -2
- package/app/plugins/memory-pack/scripts/strip_private.py +1 -1
- package/app/skills/docs/SKILL.md +1 -1
- package/app/skills/documentation-standards/SKILL.md +1 -1
- package/app/skills/write-a-prd/scripts/frame-template.html +1 -25
- package/app/skills/write-a-prd/scripts/poll.js +23 -0
- package/app/skills/write-a-prd/scripts/visual-server.cjs +11 -1
- package/kb/planning/cloud-security-pack-plan.md +1166 -0
- package/kb/planning/enterprise-config-inheritance-plan.md +917 -0
- package/kb/planning/local-dashboard-plan.md +773 -0
- package/kb/planning/offline-slm-profile-plan.md +742 -0
- package/kb/procedures/maintenance-sop.md +10 -4
- package/llms-full.txt +3915 -4
- package/llms.txt +5 -0
- package/manifest.json +1 -1
- package/package.json +1 -1
- package/scripts/dir_rules_shared.py +96 -0
- package/scripts/generate_antigravity.py +16 -5
- package/scripts/generate_augment_rules.py +41 -7
- package/scripts/generate_cline_rules.py +13 -3
- package/scripts/generate_cursor_mdc.py +37 -8
- package/scripts/generate_roo_rules.py +13 -3
- package/scripts/generate_windsurf_rules.py +13 -3
- package/scripts/install_steps/ai_tools.py +16 -8
- package/scripts/validate.py +1 -0
|
@@ -0,0 +1,917 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Plan: Enterprise Config Inheritance — Multi-Repo Governance with extends"
|
|
3
|
+
category: planning
|
|
4
|
+
service: ai-toolkit
|
|
5
|
+
tags:
|
|
6
|
+
- enterprise
|
|
7
|
+
- multi-repo
|
|
8
|
+
- config-inheritance
|
|
9
|
+
- extends
|
|
10
|
+
- governance
|
|
11
|
+
- team-management
|
|
12
|
+
- monorepo
|
|
13
|
+
doc_type: plan
|
|
14
|
+
status: proposed
|
|
15
|
+
created: "2026-04-10"
|
|
16
|
+
last_updated: "2026-04-10"
|
|
17
|
+
completion: "0%"
|
|
18
|
+
description: "Configuration inheritance system for ai-toolkit. Enables organizations to define a shared base config (agents, rules, hooks, profiles, constitution overrides) published as an npm package or local path, which individual projects extend via an `extends` field. Changes to the base config propagate automatically on `ai-toolkit update`. Targets enterprises managing 10-100+ repositories with uniform AI governance."
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Plan: Enterprise Config Inheritance — Multi-Repo Governance with `extends`
|
|
22
|
+
|
|
23
|
+
**Status:** Proposed
|
|
24
|
+
**Completion:** 0%
|
|
25
|
+
**Created:** 2026-04-10
|
|
26
|
+
**Origin:** Organizations adopting ai-toolkit across 10-100+ repositories face a config synchronization problem — updating a rule or policy requires touching every repository individually. The `extends` pattern (popularized by ESLint, TypeScript, Prettier) solves this by establishing a single source of truth that projects inherit from.
|
|
27
|
+
**Estimated Effort:** 5-7 weeks (1 person) — MVP (core engine + install integration) shippable in ~3.5 weeks
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 1. Objective
|
|
32
|
+
|
|
33
|
+
Create a configuration inheritance system where projects can extend a shared base config published as an npm package, a Git URL, or a local path. The base config defines organizational defaults (which agents to enable, which rules to enforce, which hooks to require, persona presets, and constitution amendments). Individual projects can override or supplement the base, creating a layered governance model.
|
|
34
|
+
|
|
35
|
+
**Key design principles:**
|
|
36
|
+
- **Familiar pattern** — mirrors ESLint's `extends`, TypeScript's `extends`, and Prettier's shared configs
|
|
37
|
+
- **npm-first distribution** — base configs are regular npm packages (e.g., `@mycompany/ai-toolkit-config`). Resolver shells out to `npm pack` CLI (respects `.npmrc` auth) — no hand-rolled npm client, preserves stdlib-only constraint
|
|
38
|
+
- **Single extends in v1** — `"extends": "string"` only. Multi-base merge (`"extends": [...]`) deferred to v2 to avoid merge-ordering complexity (ESLint's multi-extends is a known source of confusion)
|
|
39
|
+
- **Layered merge** — base → project, with explicit override semantics (`override: true` required for safety-critical overrides)
|
|
40
|
+
- **Constitution immutable** — base constitution articles cannot be modified by projects, period. Projects can only ADD new articles (article 6+). No weakening detection heuristics — absolute immutability is simpler and safer
|
|
41
|
+
- **Offline-capable** — resolved at `install`/`update` time, not at runtime
|
|
42
|
+
- **Backward-compatible** — projects without `extends` work exactly as today (no breaking changes)
|
|
43
|
+
- **Audit trail** — `state.json` records which base config was resolved and what was overridden
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 1a. Functional Requirements
|
|
48
|
+
|
|
49
|
+
| ID | Requirement | Priority | Success Metric |
|
|
50
|
+
|----|-------------|----------|----------------|
|
|
51
|
+
| FR1 | Resolve `extends` from npm package, git URL, local path | Must | 4 source types work |
|
|
52
|
+
| FR2 | Deep merge base → project config with layered semantics | Must | Merge engine handles dict, list, scalar types |
|
|
53
|
+
| FR3 | Constitution immutability — Articles I-V cannot be modified | Must | 100% block rate on modification attempts |
|
|
54
|
+
| FR4 | Override validation with `override: true` + `justification` | Must | Missing justification → error |
|
|
55
|
+
| FR5 | `enforce` block constraints (minHookProfile, requiredPlugins, forbidOverride, requiredAgents) | Must | All 4 constraint types enforced |
|
|
56
|
+
| FR6 | Install/update integration — resolve extends during install | Must | `install --local` detects `.ai-toolkit.json` |
|
|
57
|
+
| FR7 | `config diff` command — show project vs base differences | Must | All merge layers visible |
|
|
58
|
+
| FR8 | `config validate` command — schema + enforcement validation | Must | Exit 0/1 for pass/fail |
|
|
59
|
+
| FR9 | `config init` — interactive project config setup | Should | Guided flow produces valid `.ai-toolkit.json` |
|
|
60
|
+
| FR10 | `config create-base` — scaffold npm base config package | Should | Ready-to-publish package with `package.json` |
|
|
61
|
+
| FR11 | Lock file for reproducible installs | Should | Identical resolved config across team members |
|
|
62
|
+
| FR12 | Audit trail in `state.json` | Should | Resolved version + overrides recorded |
|
|
63
|
+
| FR13 | CI enforcement command (`config check`) | Could | Exit 0/1 for governance compliance |
|
|
64
|
+
| FR14 | Multi-base extends (`"extends": [...]`) | Won't (v2) | Deferred — merge ordering complexity |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 2. Architecture Overview
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
Organization Level (published once, consumed by all repos):
|
|
72
|
+
═══════════════════════════════════════════════════════════
|
|
73
|
+
|
|
74
|
+
@mycompany/ai-toolkit-config (npm package)
|
|
75
|
+
├── ai-toolkit.config.json ← base configuration
|
|
76
|
+
├── rules/
|
|
77
|
+
│ ├── code-review-policy.md ← company-specific rules
|
|
78
|
+
│ └── deployment-checklist.md
|
|
79
|
+
├── agents/
|
|
80
|
+
│ └── compliance-auditor.md ← company-specific agent
|
|
81
|
+
└── package.json
|
|
82
|
+
|
|
83
|
+
Project Level (per-repository):
|
|
84
|
+
══════════════════════════════
|
|
85
|
+
|
|
86
|
+
my-service/
|
|
87
|
+
├── .ai-toolkit.json ← project config with "extends"
|
|
88
|
+
├── .claude/
|
|
89
|
+
│ ├── CLAUDE.md ← generated (base + project merged)
|
|
90
|
+
│ └── settings.json ← generated (base hooks + project hooks merged)
|
|
91
|
+
└── ...
|
|
92
|
+
|
|
93
|
+
Merge Pipeline:
|
|
94
|
+
══════════════
|
|
95
|
+
|
|
96
|
+
@mycompany/ai-toolkit-config ← Layer 0: organizational defaults
|
|
97
|
+
│
|
|
98
|
+
▼
|
|
99
|
+
ai-toolkit defaults (manifest.json) ← Layer 1: toolkit defaults
|
|
100
|
+
│
|
|
101
|
+
▼
|
|
102
|
+
.ai-toolkit.json ← Layer 2: project overrides
|
|
103
|
+
│
|
|
104
|
+
▼
|
|
105
|
+
Resolved Configuration ← Final: CLAUDE.md, settings.json, etc.
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Config Resolution Order
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
1. Load base config from "extends" (npm package, git URL, or local path)
|
|
112
|
+
2. Merge with ai-toolkit defaults (manifest.json profiles)
|
|
113
|
+
3. Apply project-level overrides from .ai-toolkit.json
|
|
114
|
+
4. Validate merged config (constitution immutability, schema validation)
|
|
115
|
+
5. Generate output files (CLAUDE.md, settings.json, agent symlinks, etc.)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 3. Progress Tracking
|
|
121
|
+
|
|
122
|
+
| # | Feature | Priority | Status | Est. Time | Notes |
|
|
123
|
+
|---|---------|----------|--------|-----------|-------|
|
|
124
|
+
| 1.1 | `.ai-toolkit.json` schema definition | P0 | Proposed | 1d | JSON Schema with `extends` field |
|
|
125
|
+
| 1.2 | Config resolver (npm, git, local path) | P0 | Proposed | 3d | Fetch + cache + validate base configs |
|
|
126
|
+
| 1.3 | Merge engine (layered merge with override semantics) | P0 | Proposed | 3d | Deep merge with `override: true` gates |
|
|
127
|
+
| 1.4 | Constitution immutability guard | P0 | Proposed | 1d | Block weakening of safety articles |
|
|
128
|
+
| 2.1 | Install/update integration | P0 | Proposed | 2d | Resolve extends during install/update |
|
|
129
|
+
| 2.2 | `ai-toolkit config diff` command | P0 | Proposed | 1.5d | Show project vs base differences — primary debugging tool |
|
|
130
|
+
| 2.3 | `ai-toolkit config validate` command | P0 | Proposed | 1d | Validate .ai-toolkit.json schema + extends resolution |
|
|
131
|
+
| 2.4 | `ai-toolkit config init` command | P1 | Proposed | 1.5d | Interactive project config setup |
|
|
132
|
+
| 2.5 | `ai-toolkit config create-base` command | P1 | Proposed | 2d | Scaffold base config package |
|
|
133
|
+
| 3.1 | Audit trail in state.json | P1 | Proposed | 1d | Record resolved config provenance |
|
|
134
|
+
| 3.2 | Lock file (`.ai-toolkit.lock.json`) | P1 | Proposed | 1.5d | Pin resolved versions for reproducibility |
|
|
135
|
+
| 3.3 | Base config scaffolder (npm package template) | P1 | Proposed | 1.5d | Ready-to-publish template |
|
|
136
|
+
| 3.4 | CI enforcement (`ai-toolkit config check`) | P2 | Proposed | 1d | Verify project adheres to base + no unapproved overrides |
|
|
137
|
+
| 4.1 | Tests | P1 | Proposed | 3d | Unit: resolution, merge, immutability, override, CLI commands. Integration: `install --local` with `.ai-toolkit.json` containing `extends`, verify resolved `CLAUDE.md` has base + project rules merged end-to-end |
|
|
138
|
+
| 4.2 | Documentation | P1 | Proposed | 3d | Enterprise setup guide + all 9 docs per CLAUDE.md: README, CLAUDE.md, ARCHITECTURE.md, package.json, llms.txt, llms-full.txt, AGENTS.md, skills-catalog.md, architecture-overview.md |
|
|
139
|
+
|
|
140
|
+
**Phasing (MVP-first):**
|
|
141
|
+
- **MVP Phase 1 (week 1-2):** Core engine — schema (1.1), resolver (1.2), merge engine (1.3), constitution guard (1.4)
|
|
142
|
+
- **MVP Phase 2 (week 2-3):** Integration + diff — install integration (2.1), `config diff` (2.2), `config validate` (2.3), tests for above (~3.5 weeks = shippable MVP)
|
|
143
|
+
- **Phase 3 (week 4-5):** CLI polish — `config init` (2.4), `config create-base` (2.5), scaffolder (3.3)
|
|
144
|
+
- **Phase 4 (week 5-6):** Enterprise — audit trail (3.1), lock file (3.2), CI enforcement (3.4) (**gate behind real enterprise feedback**)
|
|
145
|
+
- **Phase 5 (week 6-7):** Tests + documentation (4.1, 4.2) (3d docs — all 9 docs per CLAUDE.md rules)
|
|
146
|
+
|
|
147
|
+
> **Demand validation gate:** Ship MVP (Phases 1-2), announce, measure adoption. Only build Phase 4 (lock file, CI enforcement, audit trail) in response to confirmed enterprise demand.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 4. Dependency Graph
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
MVP Phase 1: Core Engine (week 1-2)
|
|
155
|
+
====================================
|
|
156
|
+
Schema definition (1.1) ──────┐
|
|
157
|
+
├──► Merge engine (1.3)
|
|
158
|
+
Config resolver (1.2) ────────┤
|
|
159
|
+
└──► Constitution guard (1.4)
|
|
160
|
+
|
|
161
|
+
MVP Phase 2: Integration + Diff (week 2-3)
|
|
162
|
+
============================================
|
|
163
|
+
Install integration (2.1) ──┐
|
|
164
|
+
├──► config diff (2.2)
|
|
165
|
+
└──► config validate (2.3)
|
|
166
|
+
└──► MVP tests → SHIP
|
|
167
|
+
|
|
168
|
+
═══ DEMAND VALIDATION GATE ═══
|
|
169
|
+
|
|
170
|
+
Phase 3: CLI Polish (week 4-5)
|
|
171
|
+
===============================
|
|
172
|
+
├──► config init (2.4)
|
|
173
|
+
└──► create-base (2.5) + scaffolder (3.3)
|
|
174
|
+
|
|
175
|
+
Phase 4: Enterprise (week 5-6)
|
|
176
|
+
================================
|
|
177
|
+
Audit trail (3.1) ──┐
|
|
178
|
+
├──► Lock file (3.2)
|
|
179
|
+
└──► CI enforcement (3.4)
|
|
180
|
+
|
|
181
|
+
Phase 5: Polish (week 6-7)
|
|
182
|
+
===========================
|
|
183
|
+
└──► Full tests + docs (4.1, 4.2)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 5. Detailed Implementation
|
|
189
|
+
|
|
190
|
+
### Phase 1: Core Engine (week 1-2)
|
|
191
|
+
|
|
192
|
+
#### 1.1 Configuration Schema (`.ai-toolkit.json`)
|
|
193
|
+
|
|
194
|
+
> **v1 scope:** The full schema below shows the target state. v1 implements only: `extends`, `profile`, `agents`, `rules`, `constitution`, and `enforce`. See section 6a for the v1/v2 field breakdown.
|
|
195
|
+
|
|
196
|
+
**Project-level config file:**
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"$schema": "https://softspark.github.io/ai-toolkit/schemas/ai-toolkit-config.json",
|
|
201
|
+
|
|
202
|
+
"extends": "@mycompany/ai-toolkit-config",
|
|
203
|
+
|
|
204
|
+
"profile": "standard",
|
|
205
|
+
"persona": "backend-lead",
|
|
206
|
+
"hookProfile": "strict",
|
|
207
|
+
|
|
208
|
+
"agents": {
|
|
209
|
+
"enabled": ["backend-specialist", "test-engineer", "debugger"],
|
|
210
|
+
"disabled": ["game-developer", "mobile-developer"],
|
|
211
|
+
"custom": ["./agents/compliance-auditor.md"]
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
"skills": {
|
|
215
|
+
"disabled": ["/deploy", "/rollback"],
|
|
216
|
+
"custom": ["./skills/internal-deploy/"]
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
"rules": {
|
|
220
|
+
"inject": ["./rules/code-review-policy.md"],
|
|
221
|
+
"remove": []
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
"plugins": {
|
|
225
|
+
"required": ["security-pack", "memory-pack"],
|
|
226
|
+
"forbidden": []
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
"languages": ["typescript", "python"],
|
|
230
|
+
|
|
231
|
+
"editors": ["cursor", "windsurf", "copilot"],
|
|
232
|
+
|
|
233
|
+
"constitution": {
|
|
234
|
+
"amendments": [
|
|
235
|
+
{
|
|
236
|
+
"article": 6,
|
|
237
|
+
"title": "Data Sovereignty",
|
|
238
|
+
"text": "All code generation must comply with GDPR. No personal data in prompts. No PII in generated code comments."
|
|
239
|
+
}
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
"overrides": {
|
|
244
|
+
"hooks": {
|
|
245
|
+
"quality-check": {
|
|
246
|
+
"override": true,
|
|
247
|
+
"justification": "Company uses custom lint pipeline via Jenkins",
|
|
248
|
+
"replacement": "skip"
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Base config (`ai-toolkit.config.json` in npm package):**
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
{
|
|
259
|
+
"$schema": "https://softspark.github.io/ai-toolkit/schemas/ai-toolkit-base-config.json",
|
|
260
|
+
"name": "@mycompany/ai-toolkit-config",
|
|
261
|
+
"version": "2.1.0",
|
|
262
|
+
"description": "MyCompany standard AI coding config",
|
|
263
|
+
|
|
264
|
+
"extends": null,
|
|
265
|
+
|
|
266
|
+
"profile": "strict",
|
|
267
|
+
"persona": "backend-lead",
|
|
268
|
+
"hookProfile": "strict",
|
|
269
|
+
|
|
270
|
+
"agents": {
|
|
271
|
+
"enabled": ["backend-specialist", "test-engineer", "code-reviewer", "security-auditor", "debugger", "documenter"],
|
|
272
|
+
"disabled": ["game-developer"],
|
|
273
|
+
"custom": ["./agents/compliance-auditor.md"]
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
"rules": {
|
|
277
|
+
"inject": [
|
|
278
|
+
"./rules/code-review-policy.md",
|
|
279
|
+
"./rules/deployment-checklist.md",
|
|
280
|
+
"./rules/data-handling-policy.md"
|
|
281
|
+
]
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
"plugins": {
|
|
285
|
+
"required": ["security-pack"]
|
|
286
|
+
},
|
|
287
|
+
|
|
288
|
+
"languages": ["typescript"],
|
|
289
|
+
|
|
290
|
+
"constitution": {
|
|
291
|
+
"amendments": [
|
|
292
|
+
{
|
|
293
|
+
"article": 6,
|
|
294
|
+
"title": "Data Sovereignty",
|
|
295
|
+
"text": "All code generation must comply with GDPR. No personal data in prompts."
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"article": 7,
|
|
299
|
+
"title": "Audit Compliance",
|
|
300
|
+
"text": "All AI-generated code changes must be logged to the company audit system. The governance-capture hook must remain enabled."
|
|
301
|
+
}
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
|
|
305
|
+
"enforce": {
|
|
306
|
+
"minHookProfile": "standard",
|
|
307
|
+
"requiredPlugins": ["security-pack"],
|
|
308
|
+
"forbidOverride": ["constitution", "guard-destructive", "guard-path"],
|
|
309
|
+
"requiredAgents": ["security-auditor"]
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**`enforce` section:** Base configs can define non-overridable constraints:
|
|
315
|
+
- `minHookProfile` — projects cannot go below this profile
|
|
316
|
+
- `requiredPlugins` — must be installed in all projects
|
|
317
|
+
- `forbidOverride` — these components cannot be overridden
|
|
318
|
+
- `requiredAgents` — must be enabled in all projects
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
#### 1.2 Config Resolver
|
|
323
|
+
|
|
324
|
+
**Resolution sources:**
|
|
325
|
+
|
|
326
|
+
| Source | Syntax | Resolution |
|
|
327
|
+
|--------|--------|------------|
|
|
328
|
+
| npm package | `"extends": "@mycompany/ai-toolkit-config"` | `npm pack --pack-destination /tmp` + extract |
|
|
329
|
+
| npm with version | `"extends": "@mycompany/ai-toolkit-config@^2.0.0"` | Version resolution via npm |
|
|
330
|
+
| Git URL | `"extends": "git+https://github.com/myco/ai-config.git"` | `git clone --depth 1` to cache |
|
|
331
|
+
| Local path | `"extends": "../shared-config"` | Resolve relative to project root |
|
|
332
|
+
| ~~Multiple bases~~ | ~~`"extends": ["@mycompany/base", "@mycompany/typescript-extra"]`~~ | Deferred to v2 — multi-base merge ordering is a complexity trap |
|
|
333
|
+
|
|
334
|
+
**Cache directory:** `~/.ai-toolkit/config-cache/`
|
|
335
|
+
```
|
|
336
|
+
~/.ai-toolkit/config-cache/
|
|
337
|
+
@mycompany/
|
|
338
|
+
ai-toolkit-config/
|
|
339
|
+
2.1.0/
|
|
340
|
+
ai-toolkit.config.json
|
|
341
|
+
rules/
|
|
342
|
+
agents/
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**Resolution algorithm:**
|
|
346
|
+
```python
|
|
347
|
+
def resolve_extends(extends_value: str, project_root: str) -> list[BaseConfig]:
|
|
348
|
+
"""Resolve extends chain into ordered list of base configs.
|
|
349
|
+
|
|
350
|
+
v1: single string only. Multi-base (list) deferred to v2.
|
|
351
|
+
"""
|
|
352
|
+
configs = []
|
|
353
|
+
for source in [extends_value]: # v2: support list[str]
|
|
354
|
+
if source.startswith('@') or source.startswith('npm:'):
|
|
355
|
+
config = resolve_npm(source)
|
|
356
|
+
elif source.startswith('git+'):
|
|
357
|
+
config = resolve_git(source)
|
|
358
|
+
elif source.startswith('.') or source.startswith('/'):
|
|
359
|
+
config = resolve_local(source, project_root)
|
|
360
|
+
else:
|
|
361
|
+
raise ConfigError(f"Unknown extends source: {source}")
|
|
362
|
+
|
|
363
|
+
# Recursive: base config may also have "extends"
|
|
364
|
+
if config.extends:
|
|
365
|
+
parent_configs = resolve_extends(config.extends, config.root)
|
|
366
|
+
configs.extend(parent_configs)
|
|
367
|
+
|
|
368
|
+
configs.append(config)
|
|
369
|
+
|
|
370
|
+
return configs
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def resolve_extends(extends_value: str, project_root: str,
|
|
374
|
+
_visited: set[str] | None = None) -> list[BaseConfig]:
|
|
375
|
+
"""Full signature with cycle detection via visited set."""
|
|
376
|
+
if _visited is None:
|
|
377
|
+
_visited = set()
|
|
378
|
+
if extends_value in _visited:
|
|
379
|
+
raise ConfigError(
|
|
380
|
+
f"Circular extends detected: {extends_value} already in chain "
|
|
381
|
+
f"{' → '.join(_visited)}. Check your base config's 'extends' field."
|
|
382
|
+
)
|
|
383
|
+
if len(_visited) >= 5:
|
|
384
|
+
raise ConfigError(
|
|
385
|
+
f"Extends chain too deep (max 5 levels). Chain: {' → '.join(_visited)}"
|
|
386
|
+
)
|
|
387
|
+
_visited.add(extends_value)
|
|
388
|
+
# ... resolution logic as above, passing _visited to recursive calls
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Max recursion depth:** 5 levels (prevent circular extends). Circular detection via visited set.
|
|
392
|
+
|
|
393
|
+
**Offline handling:** If the npm/git source is unavailable:
|
|
394
|
+
1. Check cache (`~/.ai-toolkit/config-cache/`)
|
|
395
|
+
2. If cached version found → use with warning: "Using cached config v2.1.0 (offline)"
|
|
396
|
+
3. If not cached → error with instructions: "Run `ai-toolkit config update` when online"
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
#### 1.3 Merge Engine
|
|
401
|
+
|
|
402
|
+
**Layered deep merge with explicit override semantics:**
|
|
403
|
+
|
|
404
|
+
```python
|
|
405
|
+
def merge_configs(base: dict, project: dict) -> dict:
|
|
406
|
+
"""Merge project config over base config with rules."""
|
|
407
|
+
merged = {}
|
|
408
|
+
|
|
409
|
+
for key in set(base.keys()) | set(project.keys()):
|
|
410
|
+
base_val = base.get(key)
|
|
411
|
+
proj_val = project.get(key)
|
|
412
|
+
|
|
413
|
+
if proj_val is None:
|
|
414
|
+
merged[key] = base_val
|
|
415
|
+
elif base_val is None:
|
|
416
|
+
merged[key] = proj_val
|
|
417
|
+
elif key == 'constitution':
|
|
418
|
+
merged[key] = merge_constitution(base_val, proj_val)
|
|
419
|
+
elif key == 'agents':
|
|
420
|
+
merged[key] = merge_agents(base_val, proj_val)
|
|
421
|
+
elif key == 'rules':
|
|
422
|
+
merged[key] = merge_rules(base_val, proj_val)
|
|
423
|
+
elif key == 'overrides':
|
|
424
|
+
merged[key] = validate_overrides(base, proj_val)
|
|
425
|
+
elif isinstance(base_val, dict) and isinstance(proj_val, dict):
|
|
426
|
+
merged[key] = merge_configs(base_val, proj_val)
|
|
427
|
+
elif isinstance(base_val, list) and isinstance(proj_val, list):
|
|
428
|
+
merged[key] = list(set(base_val + proj_val)) # union
|
|
429
|
+
else:
|
|
430
|
+
merged[key] = proj_val # project wins for scalars
|
|
431
|
+
|
|
432
|
+
return merged
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**Agent merge rules:**
|
|
436
|
+
```python
|
|
437
|
+
def merge_agents(base: dict, project: dict) -> dict:
|
|
438
|
+
"""Merge agent configs — project can enable/disable but not remove base-required."""
|
|
439
|
+
merged_enabled = set(base.get('enabled', []))
|
|
440
|
+
|
|
441
|
+
# Project can add agents
|
|
442
|
+
merged_enabled.update(project.get('enabled', []))
|
|
443
|
+
|
|
444
|
+
# Project can disable agents (unless base enforces them)
|
|
445
|
+
for agent in project.get('disabled', []):
|
|
446
|
+
if agent in base.get('enforce', {}).get('requiredAgents', []):
|
|
447
|
+
raise ConfigError(
|
|
448
|
+
f"Cannot disable '{agent}' — required by base config '{base['name']}'. "
|
|
449
|
+
f"Contact your team lead to request an exemption."
|
|
450
|
+
)
|
|
451
|
+
merged_enabled.discard(agent)
|
|
452
|
+
|
|
453
|
+
return {
|
|
454
|
+
'enabled': sorted(merged_enabled),
|
|
455
|
+
'custom': base.get('custom', []) + project.get('custom', [])
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
**Override validation:**
|
|
460
|
+
```python
|
|
461
|
+
def validate_overrides(base: dict, overrides: dict) -> dict:
|
|
462
|
+
"""Validate project overrides against base enforcement rules."""
|
|
463
|
+
forbidden = set(base.get('enforce', {}).get('forbidOverride', []))
|
|
464
|
+
|
|
465
|
+
for key, override in overrides.items():
|
|
466
|
+
if key in forbidden:
|
|
467
|
+
raise ConfigError(
|
|
468
|
+
f"Cannot override '{key}' — forbidden by base config '{base['name']}'.\n"
|
|
469
|
+
f"Forbidden overrides: {', '.join(sorted(forbidden))}\n"
|
|
470
|
+
f"Contact your team lead to request an exemption."
|
|
471
|
+
)
|
|
472
|
+
if not override.get('override'):
|
|
473
|
+
raise ConfigError(
|
|
474
|
+
f"Override for '{key}' requires explicit 'override: true' + 'justification' field.\n"
|
|
475
|
+
f"This ensures intentional deviation from organizational defaults."
|
|
476
|
+
)
|
|
477
|
+
if not override.get('justification'):
|
|
478
|
+
raise ConfigError(
|
|
479
|
+
f"Override for '{key}' requires a 'justification' field explaining why.\n"
|
|
480
|
+
f"Example: \"Company uses custom lint pipeline via Jenkins\""
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
return overrides
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
#### 1.4 Constitution Immutability Guard
|
|
489
|
+
|
|
490
|
+
**Core rule:** Base constitution articles are absolutely immutable. Projects can only ADD new articles.
|
|
491
|
+
|
|
492
|
+
No weakening-detection heuristic (character count, semantic analysis) — these produce false positives and are gameable. Instead, the rule is simple and absolute: if an article number exists in the base, it cannot be modified by the project.
|
|
493
|
+
|
|
494
|
+
```python
|
|
495
|
+
def merge_constitution(base: dict, project: dict) -> dict:
|
|
496
|
+
"""Merge constitution — additions only, no modifications."""
|
|
497
|
+
base_amendments = {a['article']: a for a in base.get('amendments', [])}
|
|
498
|
+
proj_amendments = {a['article']: a for a in project.get('amendments', [])}
|
|
499
|
+
|
|
500
|
+
# Toolkit articles I-V are always immutable
|
|
501
|
+
IMMUTABLE_ARTICLES = {1, 2, 3, 4, 5}
|
|
502
|
+
|
|
503
|
+
merged = dict(base_amendments)
|
|
504
|
+
|
|
505
|
+
for article_num, amendment in proj_amendments.items():
|
|
506
|
+
if article_num in IMMUTABLE_ARTICLES:
|
|
507
|
+
raise ConfigError(
|
|
508
|
+
f"Cannot modify Constitution Article {article_num} — immutable.\n"
|
|
509
|
+
f"Articles I-V are defined by ai-toolkit and cannot be overridden.\n"
|
|
510
|
+
f"You can ADD new articles (article 6+)."
|
|
511
|
+
)
|
|
512
|
+
if article_num in base_amendments:
|
|
513
|
+
# Base articles are immutable — projects cannot modify them
|
|
514
|
+
raise ConfigError(
|
|
515
|
+
f"Cannot modify Constitution Article {article_num} — "
|
|
516
|
+
f"defined by base config '{base.get('name', 'unknown')}'.\n"
|
|
517
|
+
f"Base articles are immutable. You can ADD new articles "
|
|
518
|
+
f"with a higher article number."
|
|
519
|
+
)
|
|
520
|
+
merged[article_num] = amendment
|
|
521
|
+
|
|
522
|
+
return {'amendments': list(merged.values())}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
### MVP Phase 2: Integration + Diff (week 2-3)
|
|
528
|
+
|
|
529
|
+
#### 2.1 Install/Update Integration
|
|
530
|
+
|
|
531
|
+
**Modified `install.py` flow:**
|
|
532
|
+
|
|
533
|
+
```python
|
|
534
|
+
# During install --local:
|
|
535
|
+
# 1. Check for .ai-toolkit.json in project root
|
|
536
|
+
# 2. If found and has "extends":
|
|
537
|
+
# a. Resolve base config(s)
|
|
538
|
+
# b. Merge base → project
|
|
539
|
+
# c. Validate merged config
|
|
540
|
+
# d. Generate files from merged config
|
|
541
|
+
# 3. If not found: proceed with current behavior (backwards compatible)
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
**CLI flags:**
|
|
545
|
+
```bash
|
|
546
|
+
ai-toolkit install --local # auto-detect .ai-toolkit.json
|
|
547
|
+
ai-toolkit install --local --config ./custom.json # explicit config file
|
|
548
|
+
ai-toolkit update --local # re-resolve extends + update
|
|
549
|
+
ai-toolkit update --local --refresh-base # force re-fetch base config
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
#### 2.2 `ai-toolkit config diff`
|
|
555
|
+
|
|
556
|
+
**Show differences between project config and base:**
|
|
557
|
+
|
|
558
|
+
```bash
|
|
559
|
+
ai-toolkit config diff
|
|
560
|
+
|
|
561
|
+
# Output:
|
|
562
|
+
# Base: @mycompany/ai-toolkit-config@2.1.0
|
|
563
|
+
#
|
|
564
|
+
# Profile: strict (base) → standard (project) ⚠ OVERRIDE
|
|
565
|
+
# Persona: backend-lead (base) → frontend-lead (project)
|
|
566
|
+
# Hook Profile: strict (base) → strict (inherited)
|
|
567
|
+
#
|
|
568
|
+
# Agents:
|
|
569
|
+
# + frontend-specialist (project adds)
|
|
570
|
+
# - game-developer (base disables)
|
|
571
|
+
# = security-auditor (base requires, cannot disable)
|
|
572
|
+
#
|
|
573
|
+
# Rules:
|
|
574
|
+
# + ./rules/api-standards.md (project adds)
|
|
575
|
+
# = code-review-policy.md (inherited from base)
|
|
576
|
+
#
|
|
577
|
+
# Constitution:
|
|
578
|
+
# = Articles I-V (immutable)
|
|
579
|
+
# = Article 6: Data Sovereignty (inherited from base)
|
|
580
|
+
# + Article 8: API Standards (project adds)
|
|
581
|
+
#
|
|
582
|
+
# Overrides:
|
|
583
|
+
# quality-check: SKIP (justification: "Custom Jenkins pipeline")
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
#### 2.3 `ai-toolkit config validate`
|
|
589
|
+
|
|
590
|
+
```bash
|
|
591
|
+
ai-toolkit config validate
|
|
592
|
+
|
|
593
|
+
# Checks:
|
|
594
|
+
# ✓ .ai-toolkit.json schema valid
|
|
595
|
+
# ✓ extends: @mycompany/ai-toolkit-config@2.1.0 resolved
|
|
596
|
+
# ✓ No forbidden overrides
|
|
597
|
+
# ✓ Required plugins installed: security-pack
|
|
598
|
+
# ✓ Required agents enabled: security-auditor
|
|
599
|
+
# ✓ Constitution articles I-V intact
|
|
600
|
+
# ✓ Hook profile meets minimum: standard ≥ standard
|
|
601
|
+
# ✓ All custom rule files exist
|
|
602
|
+
# ✓ All custom agent files exist
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
607
|
+
### Phase 3: CLI Polish (week 4-5)
|
|
608
|
+
|
|
609
|
+
#### 2.4 `ai-toolkit config init`
|
|
610
|
+
|
|
611
|
+
**Interactive project config setup:**
|
|
612
|
+
|
|
613
|
+
```bash
|
|
614
|
+
ai-toolkit config init
|
|
615
|
+
|
|
616
|
+
# Flow:
|
|
617
|
+
# 1. "Does your organization have a shared ai-toolkit config? [y/n]"
|
|
618
|
+
# → y: "npm package name or git URL:" → resolves + validates
|
|
619
|
+
# → n: creates minimal .ai-toolkit.json without extends
|
|
620
|
+
# 2. "Which profile? [minimal/standard/strict]" → default from base or standard
|
|
621
|
+
# 3. "Which persona? [none/backend-lead/frontend-lead/devops-eng/junior-dev]"
|
|
622
|
+
# 4. Auto-detect languages from project
|
|
623
|
+
# 5. Auto-detect editors from project files
|
|
624
|
+
# 6. Write .ai-toolkit.json
|
|
625
|
+
# 7. Run ai-toolkit install --local
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
#### 2.5 `ai-toolkit config create-base`
|
|
631
|
+
|
|
632
|
+
**Scaffold a base config package:**
|
|
633
|
+
|
|
634
|
+
```bash
|
|
635
|
+
ai-toolkit config create-base @mycompany/ai-toolkit-config
|
|
636
|
+
|
|
637
|
+
# Creates:
|
|
638
|
+
# @mycompany-ai-toolkit-config/
|
|
639
|
+
# ├── package.json (name, version, files, peerDependencies)
|
|
640
|
+
# ├── ai-toolkit.config.json (base config with sane defaults)
|
|
641
|
+
# ├── rules/ (empty, ready for company rules)
|
|
642
|
+
# ├── agents/ (empty, ready for company agents)
|
|
643
|
+
# └── README.md (setup instructions)
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
**Generated `package.json`:**
|
|
647
|
+
```json
|
|
648
|
+
{
|
|
649
|
+
"name": "@mycompany/ai-toolkit-config",
|
|
650
|
+
"version": "1.0.0",
|
|
651
|
+
"description": "Shared ai-toolkit configuration for MyCompany",
|
|
652
|
+
"main": "ai-toolkit.config.json",
|
|
653
|
+
"files": ["ai-toolkit.config.json", "rules/", "agents/"],
|
|
654
|
+
"peerDependencies": {
|
|
655
|
+
"@softspark/ai-toolkit": ">=1.5.0"
|
|
656
|
+
},
|
|
657
|
+
"keywords": ["ai-toolkit", "config", "shared"]
|
|
658
|
+
}
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
---
|
|
662
|
+
|
|
663
|
+
### Phase 4: Enterprise Features (week 5-6)
|
|
664
|
+
|
|
665
|
+
#### 3.1 Audit Trail
|
|
666
|
+
|
|
667
|
+
**`state.json` additions:**
|
|
668
|
+
```json
|
|
669
|
+
{
|
|
670
|
+
"extends": {
|
|
671
|
+
"source": "@mycompany/ai-toolkit-config",
|
|
672
|
+
"version": "2.1.0",
|
|
673
|
+
"resolved_at": "2026-04-10T10:30:00Z",
|
|
674
|
+
"hash": "sha256:abc123...",
|
|
675
|
+
"overrides_applied": [
|
|
676
|
+
{
|
|
677
|
+
"key": "hooks.quality-check",
|
|
678
|
+
"action": "skip",
|
|
679
|
+
"justification": "Custom Jenkins pipeline"
|
|
680
|
+
}
|
|
681
|
+
]
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
---
|
|
687
|
+
|
|
688
|
+
#### 3.2 Lock File (`.ai-toolkit.lock.json`)
|
|
689
|
+
|
|
690
|
+
**Purpose:** Pin the exact resolved version of base configs for reproducible installs across team members and CI.
|
|
691
|
+
|
|
692
|
+
```json
|
|
693
|
+
{
|
|
694
|
+
"lockfileVersion": 1,
|
|
695
|
+
"resolved": {
|
|
696
|
+
"@mycompany/ai-toolkit-config": {
|
|
697
|
+
"version": "2.1.0",
|
|
698
|
+
"resolved": "https://registry.npmjs.org/@mycompany/ai-toolkit-config/-/ai-toolkit-config-2.1.0.tgz",
|
|
699
|
+
"integrity": "sha512-abc123...",
|
|
700
|
+
"cached": "~/.ai-toolkit/config-cache/@mycompany/ai-toolkit-config/2.1.0/"
|
|
701
|
+
}
|
|
702
|
+
},
|
|
703
|
+
"generated_at": "2026-04-10T10:30:00Z",
|
|
704
|
+
"ai_toolkit_version": "1.5.1"
|
|
705
|
+
}
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
**Behavior:**
|
|
709
|
+
- `ai-toolkit install --local` → uses lock file if present (like `npm ci`)
|
|
710
|
+
- `ai-toolkit update --local` → re-resolves and updates lock file (like `npm install`)
|
|
711
|
+
- `ai-toolkit update --local --refresh-base` → force re-fetch ignoring cache
|
|
712
|
+
- `.ai-toolkit.lock.json` should be committed to git (team synchronization)
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
716
|
+
#### 3.4 CI Enforcement
|
|
717
|
+
|
|
718
|
+
**`ai-toolkit config check` — for CI pipelines:**
|
|
719
|
+
|
|
720
|
+
```bash
|
|
721
|
+
ai-toolkit config check
|
|
722
|
+
|
|
723
|
+
# Exit codes:
|
|
724
|
+
# 0 — project complies with base config
|
|
725
|
+
# 1 — violations found (missing required plugins, forbidden overrides, etc.)
|
|
726
|
+
# 2 — .ai-toolkit.json not found
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
**GitHub Actions example:**
|
|
730
|
+
```yaml
|
|
731
|
+
- name: AI Toolkit Governance Check
|
|
732
|
+
run: |
|
|
733
|
+
npx @softspark/ai-toolkit config check
|
|
734
|
+
npx @softspark/ai-toolkit config validate --strict
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
**What it checks:**
|
|
738
|
+
1. Required plugins are installed
|
|
739
|
+
2. Required agents are enabled
|
|
740
|
+
3. No forbidden overrides applied without exemption
|
|
741
|
+
4. Hook profile meets minimum
|
|
742
|
+
5. Constitution articles intact
|
|
743
|
+
6. Lock file up-to-date (warn if stale)
|
|
744
|
+
|
|
745
|
+
---
|
|
746
|
+
|
|
747
|
+
## 6. File Summary
|
|
748
|
+
|
|
749
|
+
| File | Action | LOC (est.) | Description |
|
|
750
|
+
|------|--------|------------|-------------|
|
|
751
|
+
| `scripts/config_resolver.py` | CREATE | ~400 | Resolve extends (npm, git, local path) |
|
|
752
|
+
| `scripts/config_merger.py` | CREATE | ~350 | Layered merge engine |
|
|
753
|
+
| `scripts/config_validator.py` | CREATE | ~200 | Schema + enforcement validation |
|
|
754
|
+
| `scripts/config_scaffold.py` | CREATE | ~250 | create-base scaffolder |
|
|
755
|
+
| `scripts/config_diff.py` | CREATE | ~200 | Diff viewer |
|
|
756
|
+
| `scripts/config_check.py` | CREATE | ~150 | CI enforcement checker |
|
|
757
|
+
| `scripts/install.py` | EDIT | +80 | Integrate extends resolution |
|
|
758
|
+
| `bin/ai-toolkit.js` | EDIT | +40 | Register config subcommands |
|
|
759
|
+
| `manifest.json` | EDIT | +10 | Schema references |
|
|
760
|
+
| `kb/reference/enterprise-config-guide.md` | CREATE | ~300 | Enterprise setup guide |
|
|
761
|
+
| `kb/reference/base-config-template/` | CREATE | ~200 | Scaffolded base config files |
|
|
762
|
+
| `tests/test_config_resolver.bats` | CREATE | ~150 | Resolution tests |
|
|
763
|
+
| `tests/test_config_merger.bats` | CREATE | ~200 | Merge + override tests |
|
|
764
|
+
| `tests/test_config_immutability.bats` | CREATE | ~100 | Constitution guard tests |
|
|
765
|
+
| `tests/test_config_cli.bats` | CREATE | ~150 | CLI command tests |
|
|
766
|
+
| **Total** | | **~2780** | |
|
|
767
|
+
|
|
768
|
+
---
|
|
769
|
+
|
|
770
|
+
## 6a. Schema Scope (v1 vs v2)
|
|
771
|
+
|
|
772
|
+
v1 ships with a minimal schema. Each additional field adds merge logic, validation, diff output, and test surface. Expand based on real usage, not speculation.
|
|
773
|
+
|
|
774
|
+
| Field | v1 | v2 | Rationale |
|
|
775
|
+
|-------|----|----|-----------|
|
|
776
|
+
| `extends` | single string | array (multi-base) | Multi-base merge ordering is complex |
|
|
777
|
+
| `profile` | yes | — | Core governance knob |
|
|
778
|
+
| `agents` | yes | — | Most common customization |
|
|
779
|
+
| `rules` | yes | — | Rule injection is existing feature |
|
|
780
|
+
| `constitution` | yes | — | Key differentiator |
|
|
781
|
+
| `enforce` | yes | — | Non-overridable constraints |
|
|
782
|
+
| `skills` | — | yes | Less commonly customized at org level |
|
|
783
|
+
| `plugins` | — | yes | Depends on plugin maturity |
|
|
784
|
+
| `languages` | — | yes | Auto-detected, rarely org-level |
|
|
785
|
+
| `editors` | — | yes | Auto-detected, rarely org-level |
|
|
786
|
+
| `overrides` | — | yes | Complex, needs real-world feedback |
|
|
787
|
+
| `hookProfile` / `persona` | — | yes | Low demand signal |
|
|
788
|
+
|
|
789
|
+
---
|
|
790
|
+
|
|
791
|
+
## 6b. Non-Functional Requirements
|
|
792
|
+
|
|
793
|
+
| Category | Requirement |
|
|
794
|
+
|----------|-------------|
|
|
795
|
+
| **Performance** | `install --local` with extends resolution < 5s (cached), < 15s (first fetch). Config merge < 100ms. |
|
|
796
|
+
| **Offline** | Cached configs used when registry unavailable, with clear warning. |
|
|
797
|
+
| **Security** | No secret exposure in config files or audit trail. npm auth via `.npmrc` (user-managed). `execFile` for npm CLI (no shell injection). |
|
|
798
|
+
| **Error messages** | Every validation error includes: what failed, which config layer caused it, and what to do (e.g., "Contact your team lead to request an exemption"). |
|
|
799
|
+
| **Backward compatibility** | 100% — projects without `.ai-toolkit.json` work exactly as today. Zero behavioral changes for existing users. |
|
|
800
|
+
| **Maintainability** | Each new schema field requires: merge logic, validation, diff output, test. Budget 0.5d per new field. |
|
|
801
|
+
| **Quality gates** | `ruff check scripts/config_*.py` (0 errors), `mypy --strict scripts/config_*.py` (0 errors). Run before every commit. |
|
|
802
|
+
| **Type safety** | 100% public API type hints (all function signatures). >60% internal. Use `TypedDict` for config schemas, `dataclass` for resolved configs. |
|
|
803
|
+
|
|
804
|
+
---
|
|
805
|
+
|
|
806
|
+
## 7. Success Criteria (Overall)
|
|
807
|
+
|
|
808
|
+
| Metric | Target |
|
|
809
|
+
|--------|--------|
|
|
810
|
+
| Extends sources (v1) | 4 (npm, npm+version, git URL, local path) — single string only |
|
|
811
|
+
| Merge depth | 5 levels max (recursive extends) |
|
|
812
|
+
| Config schema | JSON Schema validated |
|
|
813
|
+
| Constitution protection | 100% (Articles I-V immutable) |
|
|
814
|
+
| Override justification | Required for all overrides |
|
|
815
|
+
| Enforce constraints | 4 types (minHookProfile, requiredPlugins, forbidOverride, requiredAgents) |
|
|
816
|
+
| Backward compatibility | 100% (projects without .ai-toolkit.json work as today) |
|
|
817
|
+
| CI enforcement | Exit code 0/1 for governance compliance |
|
|
818
|
+
| Lock file | Reproducible installs across team members |
|
|
819
|
+
| Scaffold command | Ready-to-publish npm package template |
|
|
820
|
+
| Tests | 30+ |
|
|
821
|
+
| Offline resolution | Cached configs with warning |
|
|
822
|
+
|
|
823
|
+
---
|
|
824
|
+
|
|
825
|
+
## 8. Risks and Mitigation
|
|
826
|
+
|
|
827
|
+
| Risk | Probability | Impact | Mitigation |
|
|
828
|
+
|------|-------------|--------|------------|
|
|
829
|
+
| npm registry unavailable during install | Low | Medium | Cache + offline fallback with warning |
|
|
830
|
+
| Circular extends chain | Low | High | Max depth 5 + visited set for cycle detection |
|
|
831
|
+
| Base config breaks project | Medium | High | Lock file pins exact version; `ai-toolkit config diff` shows changes before update |
|
|
832
|
+
| Override abuse (teams bypass governance) | Medium | Medium | `enforce.forbidOverride` + CI check + justification requirement |
|
|
833
|
+
| Config schema too restrictive | Medium | Medium | Start with minimal enforcement, expand based on enterprise feedback |
|
|
834
|
+
| Multiple base configs conflict | — | — | Deferred to v2 (single extends only in v1) |
|
|
835
|
+
| Private npm registry authentication | Medium | Low | Use existing npm auth (`.npmrc`), document setup |
|
|
836
|
+
| Git URL resolution slow | Low | Low | `--depth 1` clone, cache aggressively |
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
840
|
+
## 9. Pre-Mortem
|
|
841
|
+
|
|
842
|
+
1. **"Config file fatigue"** — developers already have `.eslintrc`, `tsconfig.json`, `.prettierrc`. Another `.ai-toolkit.json` may feel like bloat. Mitigation: file is optional, all features work without it. The DX gain (organizational governance without per-repo updates) justifies the file.
|
|
843
|
+
2. **"Base config never gets updated"** — team lead creates base config, nobody maintains it. Mitigation: `ai-toolkit config check` in CI catches drift; lock file staleness warnings.
|
|
844
|
+
3. **"Override justification is annoying"** — developers will write "needed" as justification. Mitigation: CI check can enforce minimum justification length (>20 chars); code review culture catches low-effort justifications.
|
|
845
|
+
4. **"Merge semantics are confusing"** — "does project override or extend the base agent list?" Mitigation: explicit semantics documented in schema; `ai-toolkit config diff` shows exactly what happened.
|
|
846
|
+
5. **"Enterprise teams want RBAC on overrides"** — who can approve overrides? Mitigation: v1 uses justification text + code review; v2 could integrate with GitHub CODEOWNERS for override approval.
|
|
847
|
+
|
|
848
|
+
---
|
|
849
|
+
|
|
850
|
+
## 10. Market Positioning
|
|
851
|
+
|
|
852
|
+
**Target users:**
|
|
853
|
+
1. **Engineering managers** — enforce AI coding standards across 20+ repos without touching each one
|
|
854
|
+
2. **Security teams** — ensure constitution + security-auditor agent is always enabled
|
|
855
|
+
3. **Platform teams** — distribute company-specific agents, rules, and plugins via npm
|
|
856
|
+
4. **Compliance officers** — audit trail of what AI governance rules are active in each project
|
|
857
|
+
|
|
858
|
+
**Competitive advantage:** No existing AI coding toolkit supports configuration inheritance. This is a unique enterprise feature that transforms ai-toolkit from a developer tool into an organizational governance platform.
|
|
859
|
+
|
|
860
|
+
**Revenue potential:** Enterprise teams are the primary audience for paid support/consulting around ai-toolkit. Config inheritance is the feature that makes enterprise adoption manageable.
|
|
861
|
+
|
|
862
|
+
---
|
|
863
|
+
|
|
864
|
+
## 11. Next Actions
|
|
865
|
+
|
|
866
|
+
**MVP (ship first, ~3.5 weeks):**
|
|
867
|
+
1. [ ] Approve plan
|
|
868
|
+
2. [ ] Define `.ai-toolkit.json` JSON Schema — v1 scope only (1.1)
|
|
869
|
+
3. [ ] Implement config resolver (npm, git, local) with caching (1.2)
|
|
870
|
+
4. [ ] Implement merge engine with override validation (1.3)
|
|
871
|
+
5. [ ] Implement constitution immutability guard (1.4)
|
|
872
|
+
6. [ ] Integrate into install.py flow (2.1)
|
|
873
|
+
7. [ ] Create `config diff` viewer (2.2) — primary debugging tool
|
|
874
|
+
8. [ ] Create `config validate` checker (2.3)
|
|
875
|
+
9. [ ] Tests for above (4.1 partial)
|
|
876
|
+
10. [ ] **Ship MVP → announce → measure adoption**
|
|
877
|
+
|
|
878
|
+
**Post-MVP (if demand validated):**
|
|
879
|
+
11. [ ] Create `config init` interactive command (2.4)
|
|
880
|
+
12. [ ] Create `config create-base` scaffolder (2.5)
|
|
881
|
+
13. [ ] Add audit trail to state.json (3.1)
|
|
882
|
+
14. [ ] Implement lock file generation + resolution (3.2)
|
|
883
|
+
15. [ ] Create base config npm package template (3.3)
|
|
884
|
+
16. [ ] Create CI enforcement command `config check` (3.4)
|
|
885
|
+
17. [ ] Full tests + documentation — all 9 docs per CLAUDE.md (4.1, 4.2)
|
|
886
|
+
|
|
887
|
+
---
|
|
888
|
+
|
|
889
|
+
## 12. Future (v2)
|
|
890
|
+
|
|
891
|
+
| Feature | Rationale |
|
|
892
|
+
|---------|-----------|
|
|
893
|
+
| Multi-base extends (`"extends": [...]`) | Needs real-world feedback on merge ordering UX |
|
|
894
|
+
| v1 deferred schema fields (skills, plugins, languages, editors, overrides, hookProfile, persona) | Expand based on actual enterprise requests |
|
|
895
|
+
| RBAC on overrides (GitHub CODEOWNERS integration) | v1 uses justification + code review |
|
|
896
|
+
| Semantic constitution analysis | Character-count heuristics removed in v1; revisit only if absolute immutability proves too restrictive |
|
|
897
|
+
| `ai-toolkit config audit` (full governance report) | Depends on audit trail maturity |
|
|
898
|
+
|
|
899
|
+
---
|
|
900
|
+
|
|
901
|
+
## 13. Cross-Plan Dependencies
|
|
902
|
+
|
|
903
|
+
This plan shares modification targets with two other proposed plans:
|
|
904
|
+
|
|
905
|
+
| Shared File | This Plan | Local Dashboard Plan | Offline SLM Plan |
|
|
906
|
+
|-------------|-----------|---------------------|-----------------|
|
|
907
|
+
| `scripts/install.py` | +80 LOC (extends resolution) | — | +30 LOC (offline-slm profile) |
|
|
908
|
+
| `manifest.json` | +10 LOC (schema refs) | — | +5 LOC (offline-slm profile) |
|
|
909
|
+
| `bin/ai-toolkit.js` | +40 LOC (config subcommands) | +15 LOC (ui command) | +10 LOC (compile-slm command) |
|
|
910
|
+
|
|
911
|
+
**If implementing in parallel:** coordinate merge order for shared files. Recommended sequence: Offline SLM (smallest changes) → Enterprise Config → Dashboard (no install.py changes).
|
|
912
|
+
|
|
913
|
+
**Dashboard integration note:** If this plan ships before the Dashboard plan, the Dashboard's Config page (2.6) should display `.ai-toolkit.json` / `extends` status and the `config diff` output.
|
|
914
|
+
|
|
915
|
+
---
|
|
916
|
+
|
|
917
|
+
**Last Updated:** 2026-04-10
|