@agentskit/doc-bridge 1.0.2 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/CONTRIBUTING.md +8 -0
  3. package/README.md +114 -17
  4. package/SECURITY.md +1 -1
  5. package/action.yml +23 -26
  6. package/dist/cli/program.js +1241 -309
  7. package/dist/cli/program.js.map +1 -1
  8. package/dist/config/index.d.ts +1 -1
  9. package/dist/config/index.js +338 -13
  10. package/dist/config/index.js.map +1 -1
  11. package/dist/{index-CPUJbTbg.d.ts → index-DGI9TBLE.d.ts} +906 -11
  12. package/dist/index.d.ts +65 -11
  13. package/dist/index.js +1084 -171
  14. package/dist/index.js.map +1 -1
  15. package/docs/DOGFOOD-ROUND2.md +5 -0
  16. package/docs/DOGFOOD-ROUND3.md +5 -0
  17. package/docs/DOGFOOD-V1.md +5 -0
  18. package/docs/DOGFOOD.md +5 -0
  19. package/docs/MARKETPLACE-ECOSYSTEM-PLAN.md +16 -0
  20. package/docs/MARKETPLACE.md +39 -0
  21. package/docs/POSITIONING.md +5 -0
  22. package/docs/RELEASE.md +26 -19
  23. package/docs/agent-corpus/INDEX.md +10 -0
  24. package/docs/agent-corpus/OVERVIEW.md +9 -0
  25. package/docs/agent-corpus/chat.md +10 -0
  26. package/docs/agent-corpus/cli.md +10 -0
  27. package/docs/agent-corpus/conformance.md +10 -0
  28. package/docs/agent-corpus/doc-bridge.md +10 -0
  29. package/docs/agent-corpus/doctor.md +10 -0
  30. package/docs/agent-corpus/gates.md +10 -0
  31. package/docs/agent-corpus/mcp.md +10 -0
  32. package/docs/agent-corpus/memory.md +10 -0
  33. package/docs/agent-corpus/query.md +10 -0
  34. package/docs/chat-and-rag.md +34 -0
  35. package/docs/examples.md +5 -0
  36. package/docs/for-agents.md +31 -0
  37. package/docs/getting-started.md +32 -2
  38. package/docs/index.md +23 -0
  39. package/docs/landing/assets/doc-bridge-hero.webp +0 -0
  40. package/docs/landing/assets/doc-bridge-surfaces.webp +0 -0
  41. package/docs/landing/assets/doc-bridge-two-way.webp +0 -0
  42. package/docs/landing/index.html +70 -10
  43. package/docs/mcp.md +5 -0
  44. package/docs/meta.json +20 -0
  45. package/docs/ollama-demo.md +6 -1
  46. package/docs/playbook/doc-bridge-pattern.md +4 -2
  47. package/docs/query.md +34 -0
  48. package/docs/recipes/index-pipeline.md +7 -2
  49. package/docs/schemas/agent-handoff-v1.md +5 -0
  50. package/docs/schemas/doc-bridge-index-v1.md +5 -0
  51. package/docs/schemas/memory-candidate-v1.md +15 -1
  52. package/docs/skills/doc-bridge.md +6 -1
  53. package/docs/spec/cli.md +6 -0
  54. package/docs/spec/config-v1.md +56 -6
  55. package/docs/spec/documentation-standard-v1.md +136 -0
  56. package/docs/spec/playbook-feedback.md +5 -0
  57. package/docs/spec/registry-agents.md +5 -0
  58. package/ecosystem-claims.json +187 -0
  59. package/ecosystem-upstream.json +9 -0
  60. package/ecosystem.json +235 -0
  61. package/examples/verify-handoff.mjs +5 -0
  62. package/package.json +46 -4
  63. package/scripts/check-ecosystem-upstream.mjs +50 -0
  64. package/src/cli/program.ts +36 -3
  65. package/src/config/index.ts +7 -1
  66. package/src/config/load-config.ts +4 -14
  67. package/src/config/schema.ts +91 -0
  68. package/src/conformance/documentation-standard-v1.ts +502 -0
  69. package/src/conformance/ecosystem-contract.ts +175 -0
  70. package/src/gates/run-gates.ts +33 -4
  71. package/src/index-builder/human-adapters/core.ts +12 -5
  72. package/src/index-builder/human-adapters/docusaurus.ts +29 -44
  73. package/src/index-builder/human-adapters/index.ts +15 -3
  74. package/src/index-builder/scan-corpus.ts +6 -6
  75. package/src/index.ts +17 -0
  76. package/src/lib/bounded-text.ts +25 -0
  77. package/src/lib/paths.ts +20 -2
  78. package/src/lib/static-js-literal.ts +261 -0
  79. package/src/lib/walk.ts +23 -4
  80. package/src/version.ts +1 -1
package/ecosystem.json ADDED
@@ -0,0 +1,235 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "$comment": "Canonical registry of AgentsKit ecosystem products. Stable identity lives here; numeric values live in the generated ecosystem-claims ledger. The deprecated properties array temporarily preserves v1 sibling consumers.",
4
+ "parentBrand": {
5
+ "id": "agentskit",
6
+ "name": "AgentsKit"
7
+ },
8
+ "products": [
9
+ {
10
+ "id": "agentskit",
11
+ "name": "AgentsKit",
12
+ "shortName": "AgentsKit",
13
+ "kind": "library",
14
+ "role": "foundation",
15
+ "promise": "Build agents without gluing many libraries together.",
16
+ "maturity": "beta",
17
+ "repo": "AgentsKit-io/agentskit",
18
+ "accent": "#2EA043",
19
+ "surfaces": {
20
+ "home": "https://www.agentskit.io",
21
+ "docs": "https://www.agentskit.io/docs",
22
+ "llms": "https://www.agentskit.io/llms.txt",
23
+ "stats": "https://www.agentskit.io/api/stats.json",
24
+ "documentation": "fumadocs",
25
+ "chat": "agentschat"
26
+ },
27
+ "navigation": {
28
+ "showInBar": true,
29
+ "order": 0,
30
+ "next": ["registry", "agentskit-chat", "playbook", "doc-bridge", "code-review", "akos"]
31
+ }
32
+ },
33
+ {
34
+ "id": "registry",
35
+ "name": "AgentsKit Registry",
36
+ "shortName": "Registry",
37
+ "kind": "registry",
38
+ "role": "starting-point",
39
+ "promise": "Copy ready-made agents and own the source.",
40
+ "maturity": "beta",
41
+ "repo": "AgentsKit-io/agentskit-registry",
42
+ "accent": "#58A6FF",
43
+ "surfaces": {
44
+ "home": "https://registry.agentskit.io",
45
+ "docs": "https://registry.agentskit.io/docs",
46
+ "llms": "https://registry.agentskit.io/llms.txt",
47
+ "stats": "https://registry.agentskit.io/r/index.json",
48
+ "documentation": "fumadocs",
49
+ "chat": "agentschat"
50
+ },
51
+ "navigation": {
52
+ "showInBar": true,
53
+ "order": 1,
54
+ "next": ["agentskit", "agentskit-chat", "playbook", "doc-bridge", "code-review", "akos"]
55
+ }
56
+ },
57
+ {
58
+ "id": "agentskit-chat",
59
+ "name": "AgentsKit Chat",
60
+ "shortName": "Chat",
61
+ "kind": "framework",
62
+ "role": "experience",
63
+ "promise": "Define one agent experience and deliver it across interfaces.",
64
+ "maturity": "alpha",
65
+ "repo": "AgentsKit-io/agentskit-chat",
66
+ "accent": "#F59E0B",
67
+ "surfaces": {
68
+ "home": "https://chat.agentskit.io",
69
+ "docs": "https://chat.agentskit.io/docs",
70
+ "llms": "https://chat.agentskit.io/llms.txt",
71
+ "documentation": "fumadocs",
72
+ "chat": "agentschat"
73
+ },
74
+ "navigation": {
75
+ "showInBar": true,
76
+ "order": 2,
77
+ "next": ["agentskit", "registry", "playbook", "doc-bridge", "code-review", "akos"]
78
+ }
79
+ },
80
+ {
81
+ "id": "playbook",
82
+ "name": "Agents Playbook",
83
+ "shortName": "Playbook",
84
+ "kind": "methodology",
85
+ "role": "discipline",
86
+ "promise": "Make agents ship code a human would actually merge.",
87
+ "maturity": "stable",
88
+ "repo": "AgentsKit-io/agents-playbook",
89
+ "accent": "#8B5CF6",
90
+ "surfaces": {
91
+ "home": "https://playbook.agentskit.io",
92
+ "docs": "https://playbook.agentskit.io/docs",
93
+ "llms": "https://playbook.agentskit.io/llms.txt",
94
+ "stats": "https://playbook.agentskit.io/api/stats.json",
95
+ "documentation": "fumadocs",
96
+ "chat": "custom"
97
+ },
98
+ "navigation": {
99
+ "showInBar": true,
100
+ "order": 3,
101
+ "next": ["agentskit", "registry", "agentskit-chat", "doc-bridge", "code-review", "akos"]
102
+ }
103
+ },
104
+ {
105
+ "id": "doc-bridge",
106
+ "name": "Doc Bridge",
107
+ "shortName": "Doc Bridge",
108
+ "kind": "developer-tool",
109
+ "role": "understanding",
110
+ "promise": "Turn repository documentation into executable agent handoffs.",
111
+ "maturity": "stable",
112
+ "repo": "AgentsKit-io/doc-bridge",
113
+ "accent": "#06B6D4",
114
+ "surfaces": {
115
+ "home": "https://agentskit-io.github.io/doc-bridge/",
116
+ "docs": "https://agentskit-io.github.io/doc-bridge/",
117
+ "llms": "https://agentskit-io.github.io/doc-bridge/llms.txt",
118
+ "documentation": "fumadocs",
119
+ "chat": "none"
120
+ },
121
+ "navigation": {
122
+ "showInBar": true,
123
+ "order": 4,
124
+ "next": ["agentskit", "registry", "agentskit-chat", "playbook", "code-review", "akos"]
125
+ }
126
+ },
127
+ {
128
+ "id": "code-review",
129
+ "name": "AgentsKit Code Review",
130
+ "shortName": "Code Review",
131
+ "kind": "developer-tool",
132
+ "role": "verification",
133
+ "promise": "Run deep, low-noise review with the model already in use.",
134
+ "maturity": "alpha",
135
+ "repo": "AgentsKit-io/code-review-cli",
136
+ "accent": "#F97316",
137
+ "surfaces": {
138
+ "home": "https://github.com/AgentsKit-io/code-review-cli",
139
+ "docs": "https://github.com/AgentsKit-io/code-review-cli#readme",
140
+ "llms": "https://raw.githubusercontent.com/AgentsKit-io/code-review-cli/main/llms.txt",
141
+ "documentation": "repository",
142
+ "chat": "none"
143
+ },
144
+ "navigation": {
145
+ "showInBar": true,
146
+ "order": 5,
147
+ "next": ["agentskit", "registry", "agentskit-chat", "playbook", "doc-bridge", "akos"]
148
+ }
149
+ },
150
+ {
151
+ "id": "akos",
152
+ "name": "AgentsKit OS",
153
+ "shortName": "AKOS",
154
+ "kind": "product",
155
+ "role": "operation",
156
+ "promise": "Run and govern agents in production.",
157
+ "maturity": "stable",
158
+ "repo": "AgentsKit-io/agentskit-os",
159
+ "accent": "#34D399",
160
+ "surfaces": {
161
+ "home": "https://akos.agentskit.io",
162
+ "docs": "https://akos.agentskit.io/docs",
163
+ "llms": "https://akos.agentskit.io/llms.txt",
164
+ "stats": "https://akos.agentskit.io/api/stats.json",
165
+ "documentation": "fumadocs",
166
+ "chat": "none"
167
+ },
168
+ "navigation": {
169
+ "showInBar": true,
170
+ "order": 6,
171
+ "next": []
172
+ }
173
+ }
174
+ ],
175
+ "properties": [
176
+ {
177
+ "id": "agentskit",
178
+ "name": "AgentsKit",
179
+ "barLabel": "AgentsKit",
180
+ "domain": "www.agentskit.io",
181
+ "url": "https://www.agentskit.io",
182
+ "repo": "AgentsKit-io/agentskit",
183
+ "tagline": "Build agents without gluing many libraries together.",
184
+ "kind": "library",
185
+ "accent": "#2EA043",
186
+ "llms": "https://www.agentskit.io/llms.txt",
187
+ "stats": "https://www.agentskit.io/api/stats.json"
188
+ },
189
+ {
190
+ "id": "akos",
191
+ "name": "AgentsKit OS",
192
+ "barLabel": "AKOS",
193
+ "domain": "akos.agentskit.io",
194
+ "url": "https://akos.agentskit.io",
195
+ "repo": "AgentsKit-io/agentskit-os",
196
+ "tagline": "Run and govern agents in production.",
197
+ "kind": "product",
198
+ "accent": "#34D399",
199
+ "llms": "https://akos.agentskit.io/llms.txt",
200
+ "stats": "https://akos.agentskit.io/api/stats.json"
201
+ },
202
+ {
203
+ "id": "playbook",
204
+ "name": "Agents Playbook",
205
+ "barLabel": "Playbook",
206
+ "domain": "playbook.agentskit.io",
207
+ "url": "https://playbook.agentskit.io",
208
+ "repo": "AgentsKit-io/agents-playbook",
209
+ "tagline": "Make agents ship code a human would actually merge.",
210
+ "kind": "methodology",
211
+ "accent": "#8B5CF6",
212
+ "llms": "https://playbook.agentskit.io/llms.txt",
213
+ "stats": "https://playbook.agentskit.io/api/stats.json"
214
+ },
215
+ {
216
+ "id": "registry",
217
+ "name": "AgentsKit Registry",
218
+ "barLabel": "Registry",
219
+ "domain": "registry.agentskit.io",
220
+ "url": "https://registry.agentskit.io",
221
+ "repo": "AgentsKit-io/agentskit-registry",
222
+ "tagline": "Copy ready-made agents and own the source.",
223
+ "kind": "registry",
224
+ "accent": "#58A6FF",
225
+ "llms": "https://registry.agentskit.io/llms.txt",
226
+ "stats": "https://registry.agentskit.io/r/index.json"
227
+ }
228
+ ],
229
+ "builder": {
230
+ "id": "emersonbraun",
231
+ "name": "Emerson Braun",
232
+ "url": "https://emersonbraun.dev",
233
+ "$comment": "Link-source only. The builder is not a peer product and is not shown in shared product navigation."
234
+ }
235
+ }
@@ -0,0 +1,5 @@
1
+ import { execFileSync } from 'node:child_process'
2
+
3
+ execFileSync(process.execPath, ['bin/ak-docs.js', 'demo', '--text'], {
4
+ stdio: 'inherit',
5
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentskit/doc-bridge",
3
- "version": "1.0.2",
3
+ "version": "1.2.1",
4
4
  "description": "Human↔agent documentation bridge — deterministic handoffs, doc-site links, memory→docs, optional AgentsKit RAG/chat.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,6 +23,10 @@
23
23
  "bin",
24
24
  "action.yml",
25
25
  "scripts/prepare.mjs",
26
+ "scripts/check-ecosystem-upstream.mjs",
27
+ "ecosystem.json",
28
+ "ecosystem-claims.json",
29
+ "ecosystem-upstream.json",
26
30
  "docs",
27
31
  "examples",
28
32
  "README.md",
@@ -41,6 +45,8 @@
41
45
  "test": "vitest run",
42
46
  "test:watch": "vitest",
43
47
  "coverage": "vitest run --coverage",
48
+ "check:ecosystem-upstream": "node scripts/check-ecosystem-upstream.mjs",
49
+ "check:no-legacy-chat-imports": "node scripts/check-no-legacy-chat-imports.mjs",
44
50
  "typecheck": "tsc --noEmit",
45
51
  "smoke:packaged": "node scripts/smoke-packaged.mjs",
46
52
  "smoke:docsites": "node scripts/smoke-docsites.mjs",
@@ -48,12 +54,24 @@
48
54
  "smoke:ollama": "node scripts/smoke-ollama.mjs",
49
55
  "coverage:badge": "node scripts/update-coverage-badge.mjs",
50
56
  "changeset": "changeset",
51
- "version-packages": "changeset version",
57
+ "version-packages": "changeset version && node scripts/sync-version.mjs",
52
58
  "release": "npm run build && npm test && changeset publish",
53
- "version": "node scripts/sync-version.mjs && git add package.json src/version.ts",
59
+ "version": "node scripts/sync-version.mjs && git add package.json src/version.ts action.yml",
54
60
  "prepublishOnly": "npm run build && npm test",
55
61
  "prepare": "node scripts/prepare.mjs",
56
- "prepack": "npm run build"
62
+ "prepack": "npm run build",
63
+ "docs:dev": "cd apps/docs && next dev",
64
+ "docs:artifacts": "node scripts/build-docs-artifacts.mjs",
65
+ "docs:build": "pnpm build && node bin/ak-docs.js index && pnpm docs:artifacts && cd apps/docs && next build",
66
+ "docs:typecheck": "cd apps/docs && fumadocs-mdx && tsc --noEmit",
67
+ "docs:e2e": "playwright test",
68
+ "docs:lighthouse": "lhci autorun",
69
+ "test:readme-standard": "node --test scripts/readme-standard.test.mjs",
70
+ "test:marketplace": "node --test scripts/marketplace-contract.test.mjs",
71
+ "check:marketplace": "node scripts/check-marketplace-contract.mjs",
72
+ "test:docs-artifacts": "node --test scripts/docs-artifacts-contract.test.mjs",
73
+ "check:readme-standard": "node scripts/check-readme-standard.mjs",
74
+ "check:docs": "pnpm check:readme-standard && node bin/ak-docs.js gate run && node bin/ak-docs.js conformance run documentation-standard-v1 --text && pnpm docs:typecheck && pnpm docs:build && pnpm test:docs-artifacts"
57
75
  },
58
76
  "keywords": [
59
77
  "agentskit",
@@ -108,13 +126,37 @@
108
126
  }
109
127
  },
110
128
  "devDependencies": {
129
+ "@agentskit/chat": "0.3.0",
130
+ "@agentskit/core": "1.12.3",
131
+ "@agentskit/react": "0.7.4",
111
132
  "@changesets/cli": "^2.31.0",
133
+ "@lhci/cli": "^0.15.1",
134
+ "@playwright/test": "1.61.1",
135
+ "@tailwindcss/postcss": "4.3.2",
112
136
  "@types/node": "^22.15.3",
137
+ "@types/react": "19.0.0",
138
+ "@types/react-dom": "19.0.0",
113
139
  "@vitest/coverage-v8": "4.1.10",
140
+ "fumadocs-core": "15.6.5",
141
+ "fumadocs-mdx": "11.6.4",
142
+ "fumadocs-ui": "15.6.5",
143
+ "lucide-react": "0.460.0",
144
+ "next": "15.5.19",
145
+ "react": "19.2.0",
146
+ "react-dom": "19.2.0",
147
+ "tailwindcss": "4.3.2",
114
148
  "tsup": "^8.5.0",
115
149
  "typescript": "^6.0.3",
116
150
  "vitest": "^4.1.9"
117
151
  },
152
+ "pnpm": {
153
+ "overrides": {
154
+ "esbuild": "^0.28.1",
155
+ "postcss": "8.5.19",
156
+ "tmp": "0.2.7",
157
+ "uuid": "11.1.1"
158
+ }
159
+ },
118
160
  "directories": {
119
161
  "doc": "docs",
120
162
  "example": "examples",
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import { createHash } from 'node:crypto'
3
+ import { readFileSync } from 'node:fs'
4
+ import { dirname, join, resolve } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+
7
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), '..')
8
+ const metadata = JSON.parse(readFileSync(join(root, 'ecosystem-upstream.json'), 'utf8'))
9
+ if (metadata.schemaVersion !== 1 || typeof metadata.repository !== 'string' || typeof metadata.ref !== 'string') {
10
+ throw new Error('Invalid ecosystem-upstream.json metadata.')
11
+ }
12
+
13
+ const sha256 = (value) => createHash('sha256').update(value).digest('hex')
14
+ const requiredFiles = ['ecosystem.json', 'ecosystem-claims.json']
15
+ if (
16
+ !metadata.files ||
17
+ Object.keys(metadata.files).length !== requiredFiles.length ||
18
+ requiredFiles.some((file) => !/^[a-f0-9]{64}$/.test(metadata.files[file] ?? ''))
19
+ ) {
20
+ throw new Error('Upstream metadata must contain SHA-256 digests for both canonical files.')
21
+ }
22
+
23
+ const fetchText = async (url) => {
24
+ let lastError
25
+ for (let attempt = 1; attempt <= 2; attempt += 1) {
26
+ try {
27
+ const response = await fetch(url, { signal: AbortSignal.timeout(10_000) })
28
+ if (!response.ok) throw new Error(`HTTP ${response.status}`)
29
+ return await response.text()
30
+ } catch (error) {
31
+ lastError = error
32
+ }
33
+ }
34
+ throw new Error(`Unable to verify ${url}: ${lastError instanceof Error ? lastError.message : String(lastError)}`)
35
+ }
36
+
37
+ for (const file of requiredFiles) {
38
+ const expectedDigest = metadata.files[file]
39
+ const local = readFileSync(join(root, file), 'utf8')
40
+ const localDigest = sha256(local)
41
+ if (localDigest !== expectedDigest) {
42
+ throw new Error(`${file} differs from its recorded upstream SHA-256 digest.`)
43
+ }
44
+ const url = `https://raw.githubusercontent.com/${metadata.repository}/${metadata.ref}/${file}`
45
+ const upstream = await fetchText(url)
46
+ if (sha256(upstream) !== expectedDigest || upstream !== local) {
47
+ throw new Error(`${file} is stale against ${metadata.repository}@${metadata.ref}. Sync the canonical snapshot and digest.`)
48
+ }
49
+ process.stdout.write(`ecosystem upstream parity: ${file}\n`)
50
+ }
@@ -4,6 +4,11 @@ import { createInterface } from 'node:readline/promises'
4
4
 
5
5
  import { loadConfig, projectRootFromConfigPath } from '../config/load-config.js'
6
6
  import type { DocBridgeConfigV1 } from '../config/schema.js'
7
+ import {
8
+ DOCUMENTATION_STANDARD_V1_ID,
9
+ formatDocumentationStandardText,
10
+ runDocumentationStandardV1,
11
+ } from '../conformance/documentation-standard-v1.js'
7
12
  import { buildDocBridgeIndex } from '../index-builder/build-index.js'
8
13
  import { discoverPnpmPackages } from '../index-builder/plugins/pnpm-monorepo.js'
9
14
  import { scanHumanDocRecords } from '../index-builder/human-adapters/index.js'
@@ -55,6 +60,7 @@ type Command =
55
60
  | 'chat'
56
61
  | 'rag'
57
62
  | 'list'
63
+ | 'conformance'
58
64
 
59
65
  const usage = `ak-docs — human↔agent documentation bridge (@agentskit/doc-bridge)
60
66
 
@@ -68,6 +74,7 @@ Core (no API key):
68
74
  ak-docs list <packages|intents|changes|knowledge> [--text]
69
75
  ak-docs ask [question] local consult (no LLM)
70
76
  ak-docs gate run [gate-id]
77
+ ak-docs conformance run documentation-standard-v1 [--text|--json]
71
78
  ak-docs mcp
72
79
  ak-docs mcp install --cursor | --claude
73
80
  ak-docs memory ingest|classify|promote [--pr] [--dry-run]
@@ -92,7 +99,13 @@ Global flags:
92
99
 
93
100
  const QUERY_KINDS = new Set<QueryKind>(['package', 'ownership', 'intent', 'change', 'search'])
94
101
  const LIST_KINDS = new Set(['packages', 'intents', 'changes', 'knowledge'])
95
- const GATE_IDS = new Set<GateId>(['index-freshness', 'human-guide-links', 'okf-type', 'docs-style'])
102
+ const GATE_IDS = new Set<GateId>([
103
+ 'index-freshness',
104
+ 'human-guide-links',
105
+ 'okf-type',
106
+ 'docs-style',
107
+ 'documentation-standard-v1',
108
+ ])
96
109
 
97
110
  const parseArgs = (argv: readonly string[]) => {
98
111
  const flags = new Set<string>()
@@ -136,6 +149,7 @@ const parseArgs = (argv: readonly string[]) => {
136
149
  else if (positional[0] === 'chat') command = 'chat'
137
150
  else if (positional[0] === 'rag') command = 'rag'
138
151
  else if (positional[0] === 'list') command = 'list'
152
+ else if (positional[0] === 'conformance') command = 'conformance'
139
153
 
140
154
  return { command, flags, configPath, positional }
141
155
  }
@@ -782,12 +796,12 @@ export const runCli = (argv: readonly string[]): number | undefined | Promise<nu
782
796
  const action = positional[1]
783
797
  const gateId = positional[2] as GateId | undefined
784
798
  if (action !== 'run') {
785
- process.stderr.write('Usage: ak-docs gate run [index-freshness]\n')
799
+ process.stderr.write('Usage: ak-docs gate run [gate-id]\n')
786
800
  return 1
787
801
  }
788
802
  if (gateId && !GATE_IDS.has(gateId)) {
789
803
  process.stderr.write(
790
- `Unsupported gate "${gateId}". Supported gates: index-freshness, human-guide-links, okf-type, docs-style\n`,
804
+ `Unsupported gate "${gateId}". Supported gates: ${[...GATE_IDS].join(', ')}\n`,
791
805
  )
792
806
  return 1
793
807
  }
@@ -802,6 +816,25 @@ export const runCli = (argv: readonly string[]): number | undefined | Promise<nu
802
816
  }
803
817
  }
804
818
 
819
+ if (command === 'conformance') {
820
+ const action = positional[1]
821
+ const profile = positional[2]
822
+ if (action !== 'run' || profile !== DOCUMENTATION_STANDARD_V1_ID) {
823
+ process.stderr.write(`Usage: ak-docs conformance run ${DOCUMENTATION_STANDARD_V1_ID} [--text|--json]\n`)
824
+ return 1
825
+ }
826
+ try {
827
+ const { config, root } = loadProject(configPath)
828
+ const report = runDocumentationStandardV1(root, config)
829
+ if (wantsTextOutput(flags, config)) writeLines(formatDocumentationStandardText(report))
830
+ else writeJson(report)
831
+ return report.ok ? 0 : 1
832
+ } catch (error) {
833
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`)
834
+ return 1
835
+ }
836
+ }
837
+
805
838
  if (command === 'mcp') {
806
839
  if (positional[1] === 'install') {
807
840
  const target = flags.has('--claude') ? 'claude' : flags.has('--cursor') ? 'cursor' : undefined
@@ -10,6 +10,12 @@ export {
10
10
  DocBridgeConfigV1Schema,
11
11
  AgentCorpusConfigSchema,
12
12
  HumanCorpusConfigSchema,
13
+ DocumentationStandardRuleIdSchema,
14
+ DocumentationStandardV1ConfigSchema,
15
+ EcosystemContractEvidenceSchema,
16
+ ConformanceConfigSchema,
13
17
  type DocBridgeConfigV1,
14
18
  type AgentCorpusConfig,
15
- } from './schema.js'
19
+ type DocumentationStandardRuleId,
20
+ type DocumentationStandardV1Config,
21
+ } from './schema.js'
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from 'node:fs'
2
2
  import { basename, dirname, join, resolve } from 'node:path'
3
- import vm from 'node:vm'
4
3
 
4
+ import { parseStaticJsObject } from '../lib/static-js-literal.js'
5
5
  import { applyConfigDefaults } from './defaults.js'
6
6
  import { DocBridgeConfigV1Schema, type DocBridgeConfigV1 } from './schema.js'
7
7
 
@@ -60,28 +60,18 @@ const parseJsonConfig = (raw: string, path: string): unknown => {
60
60
  }
61
61
 
62
62
  const parseCodeConfig = (raw: string, path: string): unknown => {
63
- const code = raw
63
+ const unsupportedImports = raw
64
64
  .replace(/import\s+type\s+[\s\S]*?;?\n/g, '')
65
65
  .replace(/import\s+\{\s*defineConfig\s*\}\s+from\s+['"]@agentskit\/doc-bridge(?:\/config)?['"];?\n?/g, '')
66
- .replace(/\s+satisfies\s+[A-Za-z0-9_.$<>{}\[\],\s]+(?=\s*(?:;|\)|$))/g, '')
67
- .replace(/export\s+default/, 'module.exports.default =')
68
-
69
- if (/\bimport\b/.test(code)) {
66
+ if (/\bimport\b/.test(unsupportedImports)) {
70
67
  throw new Error(`Unsupported import in ${path}. Static config only supports defineConfig imports.`)
71
68
  }
72
-
73
- const sandbox = {
74
- module: { exports: {} as { default?: unknown } },
75
- exports: {},
76
- defineConfig: (config: unknown) => config,
77
- }
78
69
  try {
79
- vm.runInNewContext(code, sandbox, { timeout: 250, filename: path })
70
+ return parseStaticJsObject(raw)
80
71
  } catch (error) {
81
72
  const message = error instanceof Error ? error.message : String(error)
82
73
  throw new Error(`Failed to load config at ${path}: ${message}`)
83
74
  }
84
- return sandbox.module.exports.default
85
75
  }
86
76
 
87
77
  const parseConfig = (input: unknown): DocBridgeConfigV1 => {
@@ -124,6 +124,7 @@ export const GatesConfigSchema = z
124
124
  'docs-style',
125
125
  'routing-currency',
126
126
  'bootstrap-size',
127
+ 'documentation-standard-v1',
127
128
  ]),
128
129
  )
129
130
  .max(16)
@@ -138,6 +139,7 @@ export const GatesConfigSchema = z
138
139
  'docs-style',
139
140
  'routing-currency',
140
141
  'bootstrap-size',
142
+ 'documentation-standard-v1',
141
143
  ]),
142
144
  )
143
145
  .max(16)
@@ -264,6 +266,92 @@ export const FederationConfigSchema = z
264
266
  })
265
267
  .strict()
266
268
 
269
+ export const DocumentationEvidenceFileSchema = z
270
+ .object({
271
+ path: z.string().min(1).max(512),
272
+ contains: z.array(z.string().min(1).max(512)).min(1).max(32),
273
+ })
274
+ .strict()
275
+
276
+ export const DocumentationLinkEvidenceSchema = z
277
+ .object({
278
+ url: z.string().url().max(512),
279
+ paths: z.array(z.string().min(1).max(512)).min(1).max(32),
280
+ })
281
+ .strict()
282
+
283
+ export const DocumentationQuickstartEvidenceSchema = z
284
+ .object({
285
+ id: z.string().regex(/^[a-z][a-z0-9-]*$/).max(128),
286
+ doc: z.string().min(1).max(512),
287
+ test: z.string().min(1).max(512),
288
+ command: z.string().min(1).max(512),
289
+ testContains: z.array(z.string().min(1).max(256)).min(1).max(16),
290
+ })
291
+ .strict()
292
+
293
+ export const EcosystemContractEvidenceSchema = z
294
+ .object({
295
+ manifest: z.string().min(1).max(512),
296
+ claims: z.string().min(1).max(512),
297
+ productId: z.string().regex(/^[a-z][a-z0-9-]*$/).max(128),
298
+ })
299
+ .strict()
300
+
301
+ export const DocumentationStandardRuleIdSchema = z.enum([
302
+ 'human-docs',
303
+ 'llms-and-raw-source',
304
+ 'agent-handoffs',
305
+ 'contribution',
306
+ 'metadata',
307
+ 'cross-links',
308
+ 'tested-quickstarts',
309
+ 'visual-explanations',
310
+ 'structured-diagrams',
311
+ ])
312
+
313
+ export const DocumentationStandardExceptionSchema = z
314
+ .object({
315
+ ruleId: DocumentationStandardRuleIdSchema,
316
+ reason: z.string().min(10).max(1_024),
317
+ approvedBy: z.string().min(1).max(256),
318
+ trackingUrl: z.string().url().max(512),
319
+ })
320
+ .strict()
321
+
322
+ export const DocumentationStandardV1ConfigSchema = z
323
+ .object({
324
+ rawSources: z.array(z.string().min(1).max(512)).max(64).optional(),
325
+ contributionPaths: z.array(z.string().min(1).max(512)).max(16).optional(),
326
+ metadata: z.array(DocumentationEvidenceFileSchema).max(32).optional(),
327
+ links: z.array(DocumentationLinkEvidenceSchema).max(64).optional(),
328
+ quickstarts: z.array(DocumentationQuickstartEvidenceSchema).max(32).optional(),
329
+ visuals: z.array(z.string().min(1).max(512)).max(64).optional(),
330
+ diagrams: z.array(DocumentationEvidenceFileSchema).max(32).optional(),
331
+ ecosystemContract: EcosystemContractEvidenceSchema.optional(),
332
+ exceptions: z.array(DocumentationStandardExceptionSchema).max(32).optional(),
333
+ })
334
+ .strict()
335
+ .superRefine((value, context) => {
336
+ const seen = new Set<string>()
337
+ for (const [index, exception] of (value.exceptions ?? []).entries()) {
338
+ if (seen.has(exception.ruleId)) {
339
+ context.addIssue({
340
+ code: 'custom',
341
+ path: ['exceptions', index, 'ruleId'],
342
+ message: `Duplicate exception for rule ${exception.ruleId}`,
343
+ })
344
+ }
345
+ seen.add(exception.ruleId)
346
+ }
347
+ })
348
+
349
+ export const ConformanceConfigSchema = z
350
+ .object({
351
+ documentationStandardV1: DocumentationStandardV1ConfigSchema.optional(),
352
+ })
353
+ .strict()
354
+
267
355
  export const DocBridgeConfigV1Schema = z
268
356
  .object({
269
357
  schemaVersion: z.literal(CONFIG_SCHEMA_VERSION),
@@ -286,9 +374,12 @@ export const DocBridgeConfigV1Schema = z
286
374
  surfaces: SurfacesConfigSchema.optional(),
287
375
  intelligence: IntelligenceConfigSchema.optional(),
288
376
  federation: FederationConfigSchema.optional(),
377
+ conformance: ConformanceConfigSchema.optional(),
289
378
  })
290
379
  .strict()
291
380
 
292
381
  export type DocBridgeConfigV1 = z.infer<typeof DocBridgeConfigV1Schema>
293
382
  export type AgentCorpusConfig = z.infer<typeof AgentCorpusConfigSchema>
294
383
  export type HumanCorpusConfig = z.infer<typeof HumanCorpusConfigSchema>
384
+ export type DocumentationStandardV1Config = z.infer<typeof DocumentationStandardV1ConfigSchema>
385
+ export type DocumentationStandardRuleId = z.infer<typeof DocumentationStandardRuleIdSchema>