@aperant/framework 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/agents/apt-verifier.md +6 -3
  3. package/dist/cli/commands/init.d.mts.map +1 -1
  4. package/dist/cli/commands/init.mjs +17 -1
  5. package/dist/cli/commands/init.mjs.map +1 -1
  6. package/dist/cli/consistency/parse-review.mjs +5 -3
  7. package/dist/cli/consistency/parse-review.mjs.map +1 -1
  8. package/dist/cli/consistency/rules/r5-verdict-consistency.d.mts.map +1 -1
  9. package/dist/cli/consistency/rules/r5-verdict-consistency.mjs +10 -8
  10. package/dist/cli/consistency/rules/r5-verdict-consistency.mjs.map +1 -1
  11. package/dist/cli/gate/gates/review-clean.d.mts.map +1 -1
  12. package/dist/cli/gate/gates/review-clean.mjs +4 -2
  13. package/dist/cli/gate/gates/review-clean.mjs.map +1 -1
  14. package/dist/cli/install/mcp-provision.d.mts +26 -0
  15. package/dist/cli/install/mcp-provision.d.mts.map +1 -0
  16. package/dist/cli/install/mcp-provision.mjs +281 -0
  17. package/dist/cli/install/mcp-provision.mjs.map +1 -0
  18. package/dist/cli/install/mcp-server-specs.d.mts +80 -0
  19. package/dist/cli/install/mcp-server-specs.d.mts.map +1 -0
  20. package/dist/cli/install/mcp-server-specs.mjs +102 -0
  21. package/dist/cli/install/mcp-server-specs.mjs.map +1 -0
  22. package/dist/cli/install/runtime-detect.d.mts +1 -0
  23. package/dist/cli/install/runtime-detect.d.mts.map +1 -1
  24. package/dist/cli/install/runtime-detect.mjs +5 -0
  25. package/dist/cli/install/runtime-detect.mjs.map +1 -1
  26. package/dist/cli/install/toml-merge.d.mts +40 -0
  27. package/dist/cli/install/toml-merge.d.mts.map +1 -0
  28. package/dist/cli/install/toml-merge.mjs +134 -0
  29. package/dist/cli/install/toml-merge.mjs.map +1 -0
  30. package/dist/cli/util/events-path.d.mts +8 -0
  31. package/dist/cli/util/events-path.d.mts.map +1 -0
  32. package/dist/cli/util/events-path.mjs +23 -0
  33. package/dist/cli/util/events-path.mjs.map +1 -0
  34. package/dist/cli/util/runtime-capabilities.d.mts +30 -0
  35. package/dist/cli/util/runtime-capabilities.d.mts.map +1 -0
  36. package/dist/cli/util/runtime-capabilities.mjs +214 -0
  37. package/dist/cli/util/runtime-capabilities.mjs.map +1 -0
  38. package/dist/cli/verify-proof/audit.d.mts +2 -7
  39. package/dist/cli/verify-proof/audit.d.mts.map +1 -1
  40. package/dist/cli/verify-proof/audit.mjs +11 -17
  41. package/dist/cli/verify-proof/audit.mjs.map +1 -1
  42. package/dist/cli/verify-proof/runtime-detect.d.mts +2 -29
  43. package/dist/cli/verify-proof/runtime-detect.d.mts.map +1 -1
  44. package/dist/cli/verify-proof/runtime-detect.mjs +8 -203
  45. package/dist/cli/verify-proof/runtime-detect.mjs.map +1 -1
  46. package/dist/plugin/.claude-plugin/plugin.json +1 -1
  47. package/dist/plugin/agents/apt-verifier.md +6 -3
  48. package/dist/plugin/skills/apt-pr-review/SKILL.md +54 -0
  49. package/dist/plugin/skills/apt-verify/SKILL.md +1 -1
  50. package/dist/plugin/skills/apt-verify-proof/SKILL.md +25 -1
  51. package/drivers/browser/skill/agent-browser/SKILL.md +51 -0
  52. package/drivers/tauri/README.md +107 -0
  53. package/drivers/tauri/driver.mjs +88 -0
  54. package/drivers/tauri/manifest.json +37 -0
  55. package/drivers/tauri/scripts/tauri-mcp.sh +41 -0
  56. package/package.json +1 -1
  57. package/skills/apt-pr-review/SKILL.md +54 -0
  58. package/skills/apt-verify/SKILL.md +1 -1
  59. package/skills/apt-verify-proof/SKILL.md +25 -1
  60. package/src/cli/commands/init.mjs +19 -0
  61. package/src/cli/consistency/parse-review.mjs +5 -3
  62. package/src/cli/consistency/rules/r5-verdict-consistency.mjs +14 -9
  63. package/src/cli/gate/gates/review-clean.mjs +4 -2
  64. package/src/cli/install/mcp-provision.mjs +293 -0
  65. package/src/cli/install/mcp-server-specs.mjs +101 -0
  66. package/src/cli/install/runtime-detect.mjs +9 -0
  67. package/src/cli/install/toml-merge.mjs +139 -0
  68. package/src/cli/util/events-path.mjs +24 -0
  69. package/src/cli/util/runtime-capabilities.mjs +216 -0
  70. package/src/cli/verify-proof/audit.mjs +11 -17
  71. package/src/cli/verify-proof/runtime-detect.mjs +11 -204
  72. package/templates/config.json +2 -1
@@ -1,211 +1,18 @@
1
1
  /**
2
- * runtime-detect.mjs — pure project-shape capability detection.
2
+ * verify-proof/runtime-detect.mjs — pure project-shape capability detection.
3
3
  *
4
- * Extracted from packages/core/src/prompts/prompt-loader.ts:572-595 so the
5
- * framework CLI is self-contained (no @aperant/core dep). Same heuristics:
6
- * read package.json's dependencies + devDependencies, return a capability
7
- * record the resolver can score against.
8
- *
9
- * Pattern: pure data in → pure data out. No filesystem walking, no exec.
10
- * Use loadRuntimeCapabilities(projectDir) for the cwd-rooted variant.
11
- *
12
- * v0.8.6 — `loadRuntimeCapabilities` now ALSO walks `apps/*` by default
13
- * (configurable via the second arg `{monorepo_globs}`) and OR-merges
14
- * each match's `package.json` capabilities with the root. The default
15
- * `['apps/*']` matches the canonical Aperant monorepo layout; adopters
16
- * whose monorepo lives elsewhere (e.g. `packages/apps/*`) pass a
17
- * custom `monorepo_globs`. Setting `monorepo_globs: []` disables the
18
- * walk entirely (root-only escape hatch).
4
+ * The implementation now lives in util/runtime-capabilities.mjs so the install
5
+ * layer can share it WITHOUT install/ importing from verify-proof/ (the
6
+ * layer-boundary rule). Re-exported here byte-for-byte so every existing
7
+ * `import { } from '../verify-proof/runtime-detect.mjs'` call site (and the
8
+ * `RuntimeCapabilities` typedef references) keep working unchanged.
19
9
  */
20
10
 
21
- import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'
22
- import { join, resolve } from 'node:path'
11
+ export {
12
+ detectFromPackageJson,
13
+ loadRuntimeCapabilities,
14
+ } from '../util/runtime-capabilities.mjs'
23
15
 
24
16
  /**
25
- * @typedef {Object} RuntimeCapabilities
26
- * @property {boolean} is_electron
27
- * @property {boolean} is_tauri
28
- * @property {boolean} is_nextjs
29
- * @property {boolean} is_nuxt
30
- * @property {boolean} is_web_frontend
31
- * @property {boolean} is_expo
32
- * @property {boolean} is_react_native
33
- * @property {boolean} has_node
34
- */
35
-
36
- /** A capability record with every flag defaulted to false. */
37
- function emptyCapabilities() {
38
- return {
39
- is_electron: false,
40
- is_tauri: false,
41
- is_nextjs: false,
42
- is_nuxt: false,
43
- is_web_frontend: false,
44
- is_expo: false,
45
- is_react_native: false,
46
- has_node: false,
47
- }
48
- }
49
-
50
- /**
51
- * Detect runtime capabilities from a parsed package.json object.
52
- *
53
- * @param {Record<string, unknown> | null} packageJson
54
- * @returns {RuntimeCapabilities}
55
- */
56
- export function detectFromPackageJson(packageJson) {
57
- const capabilities = emptyCapabilities()
58
- if (packageJson === null || typeof packageJson !== 'object') return capabilities
59
-
60
- const allDeps = {
61
- ...(packageJson.dependencies ?? {}) /** @type {Record<string,string>} */,
62
- ...(packageJson.devDependencies ?? {}) /** @type {Record<string,string>} */,
63
- }
64
- const deps = new Set(Object.keys(allDeps).map((k) => k.toLowerCase()))
65
-
66
- if (deps.has('electron') || [...deps].some((d) => d.startsWith('@electron'))) {
67
- capabilities.is_electron = true
68
- }
69
- if (deps.has('@tauri-apps/api') || deps.has('tauri')) {
70
- capabilities.is_tauri = true
71
- }
72
- if (deps.has('expo')) capabilities.is_expo = true
73
- if (deps.has('react-native')) capabilities.is_react_native = true
74
-
75
- // Web frontends — react/vue/svelte/angular/solid → frontend. BUT: an
76
- // Electron app commonly bundles React as its renderer; in that case the
77
- // runtime is "electron", not "web_frontend". Electron + react-native +
78
- // expo + tauri all win over the web flag.
79
- const isNativeContainer =
80
- capabilities.is_electron ||
81
- capabilities.is_tauri ||
82
- capabilities.is_react_native ||
83
- capabilities.is_expo
84
- const webFrameworks = ['react', 'vue', 'svelte', 'angular', 'solid']
85
- if (!isNativeContainer && webFrameworks.some((f) => deps.has(f))) {
86
- capabilities.is_web_frontend = true
87
- }
88
-
89
- if (deps.has('next')) {
90
- capabilities.is_nextjs = true
91
- capabilities.is_web_frontend = true
92
- }
93
- if (deps.has('nuxt')) {
94
- capabilities.is_nuxt = true
95
- capabilities.is_web_frontend = true
96
- }
97
- if (deps.has('vite') && !isNativeContainer) {
98
- capabilities.is_web_frontend = true
99
- }
100
-
101
- // Node-ish? Anything with a package.json + an entry point counts.
102
- if (typeof packageJson.main === 'string' || typeof packageJson.module === 'string') {
103
- capabilities.has_node = true
104
- }
105
- if (!capabilities.has_node && packageJson.scripts && typeof packageJson.scripts === 'object') {
106
- capabilities.has_node = true
107
- }
108
-
109
- return capabilities
110
- }
111
-
112
- /**
113
- * Load and detect capabilities from a project directory's package.json.
114
- * v0.8.6 — also walks `monorepo_globs` (default `['apps/*']`) and
115
- * OR-merges each match's capabilities with the root.
116
- *
117
- * @param {string} projectDir
118
- * @param {{monorepo_globs?: string[]}} [opts]
119
- * @returns {RuntimeCapabilities}
120
- */
121
- export function loadRuntimeCapabilities(projectDir, opts) {
122
- const root = resolve(projectDir)
123
- const rootPkgPath = join(root, 'package.json')
124
- let rootCaps = emptyCapabilities()
125
- if (existsSync(rootPkgPath)) {
126
- try {
127
- rootCaps = detectFromPackageJson(JSON.parse(readFileSync(rootPkgPath, 'utf-8')))
128
- } catch {
129
- /* fall through with empty caps */
130
- }
131
- }
132
-
133
- // Default to the canonical Aperant monorepo layout. Passing `[]`
134
- // disables the walk entirely (root-only escape hatch per spec ID-05).
135
- const globs = opts && Array.isArray(opts.monorepo_globs) ? opts.monorepo_globs : ['apps/*']
136
- if (globs.length === 0) return rootCaps
137
-
138
- let merged = rootCaps
139
- for (const glob of globs) {
140
- const matches = expandSimpleGlob(root, glob)
141
- for (const dir of matches) {
142
- const childPkgPath = join(dir, 'package.json')
143
- if (!existsSync(childPkgPath)) continue
144
- try {
145
- const childCaps = detectFromPackageJson(JSON.parse(readFileSync(childPkgPath, 'utf-8')))
146
- merged = orMergeCapabilities(merged, childCaps)
147
- } catch {
148
- /* skip malformed package.json */
149
- }
150
- }
151
- }
152
- return merged
153
- }
154
-
155
- /**
156
- * Expand a simple `prefix/*` glob against the root. Supports ONLY the
157
- * `<dir>/*` shape (matches each direct subdirectory of `<dir>`). Other
158
- * glob syntax is intentionally rejected — v1 keeps the dep surface
159
- * small. Fails closed on malformed patterns (returns []).
160
- *
161
- * @param {string} root
162
- * @param {string} glob
163
- * @returns {string[]}
164
- */
165
- function expandSimpleGlob(root, glob) {
166
- if (typeof glob !== 'string' || !glob.endsWith('/*')) return []
167
- const prefix = glob.slice(0, -2)
168
- if (prefix.length === 0 || prefix.includes('*')) return []
169
- const dir = join(root, prefix)
170
- if (!existsSync(dir)) return []
171
- let entries
172
- try {
173
- entries = readdirSync(dir)
174
- } catch {
175
- return []
176
- }
177
- const matches = []
178
- for (const name of entries) {
179
- const sub = join(dir, name)
180
- try {
181
- if (statSync(sub).isDirectory()) matches.push(sub)
182
- } catch {
183
- /* skip unreadable entries */
184
- }
185
- }
186
- return matches
187
- }
188
-
189
- /**
190
- * Boolean OR-merge of two capability records. Any flag true in either
191
- * input is true in the output. The "Electron wins over web" rule from
192
- * `detectFromPackageJson` is preserved when this is called repeatedly —
193
- * each child's flags are honest about that child's own shape, and the
194
- * OR-merge just unions them.
195
- *
196
- * @param {RuntimeCapabilities} a
197
- * @param {RuntimeCapabilities} b
198
- * @returns {RuntimeCapabilities}
17
+ * @typedef {import('../util/runtime-capabilities.mjs').RuntimeCapabilities} RuntimeCapabilities
199
18
  */
200
- function orMergeCapabilities(a, b) {
201
- return {
202
- is_electron: a.is_electron || b.is_electron,
203
- is_tauri: a.is_tauri || b.is_tauri,
204
- is_nextjs: a.is_nextjs || b.is_nextjs,
205
- is_nuxt: a.is_nuxt || b.is_nuxt,
206
- is_web_frontend: a.is_web_frontend || b.is_web_frontend,
207
- is_expo: a.is_expo || b.is_expo,
208
- is_react_native: a.is_react_native || b.is_react_native,
209
- has_node: a.has_node || b.has_node,
210
- }
211
- }
@@ -42,7 +42,8 @@
42
42
  "report_formats": ["html", "md"],
43
43
  "evidence_capture": true,
44
44
  "max_iterations": 3,
45
- "strict": false
45
+ "strict": false,
46
+ "provision_mcp": true
46
47
  },
47
48
  "multi_model": {
48
49
  "cross_verification": {