@aperant/framework 0.9.0 → 0.11.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 +120 -0
- package/agents/apt-verifier.md +6 -3
- package/dist/cli/commands/catch-up.d.mts +9 -0
- package/dist/cli/commands/catch-up.d.mts.map +1 -0
- package/dist/cli/commands/catch-up.mjs +64 -0
- package/dist/cli/commands/catch-up.mjs.map +1 -0
- package/dist/cli/commands/init.d.mts.map +1 -1
- package/dist/cli/commands/init.mjs +17 -1
- package/dist/cli/commands/init.mjs.map +1 -1
- package/dist/cli/commands/pr-review.d.mts +16 -4
- package/dist/cli/commands/pr-review.d.mts.map +1 -1
- package/dist/cli/commands/pr-review.mjs +30 -11
- package/dist/cli/commands/pr-review.mjs.map +1 -1
- package/dist/cli/commands/route.d.mts.map +1 -1
- package/dist/cli/commands/route.mjs +92 -2
- package/dist/cli/commands/route.mjs.map +1 -1
- package/dist/cli/commands/validate-evidence.d.mts +1 -1
- package/dist/cli/config/share-policy.d.mts.map +1 -1
- package/dist/cli/config/share-policy.mjs +1 -0
- package/dist/cli/config/share-policy.mjs.map +1 -1
- package/dist/cli/config/upgrade-gitignore.d.mts.map +1 -1
- package/dist/cli/config/upgrade-gitignore.mjs +1 -0
- package/dist/cli/config/upgrade-gitignore.mjs.map +1 -1
- package/dist/cli/consistency/parse-review.mjs +5 -3
- package/dist/cli/consistency/parse-review.mjs.map +1 -1
- package/dist/cli/consistency/rules/r5-verdict-consistency.d.mts.map +1 -1
- package/dist/cli/consistency/rules/r5-verdict-consistency.mjs +10 -8
- package/dist/cli/consistency/rules/r5-verdict-consistency.mjs.map +1 -1
- package/dist/cli/coordination/catch-up.d.mts +26 -0
- package/dist/cli/coordination/catch-up.d.mts.map +1 -0
- package/dist/cli/coordination/catch-up.mjs +239 -0
- package/dist/cli/coordination/catch-up.mjs.map +1 -0
- package/dist/cli/coordination/last-seen.d.mts +45 -0
- package/dist/cli/coordination/last-seen.d.mts.map +1 -0
- package/dist/cli/coordination/last-seen.mjs +128 -0
- package/dist/cli/coordination/last-seen.mjs.map +1 -0
- package/dist/cli/coordination/store.d.mts +15 -0
- package/dist/cli/coordination/store.d.mts.map +1 -1
- package/dist/cli/coordination/store.mjs +16 -0
- package/dist/cli/coordination/store.mjs.map +1 -1
- package/dist/cli/design/frontmatter-schema.d.mts +8 -8
- package/dist/cli/dispatch.d.mts.map +1 -1
- package/dist/cli/dispatch.mjs +2 -0
- package/dist/cli/dispatch.mjs.map +1 -1
- package/dist/cli/gate/gates/review-clean.d.mts.map +1 -1
- package/dist/cli/gate/gates/review-clean.mjs +4 -2
- package/dist/cli/gate/gates/review-clean.mjs.map +1 -1
- package/dist/cli/git/default-branch.d.mts +51 -0
- package/dist/cli/git/default-branch.d.mts.map +1 -0
- package/dist/cli/git/default-branch.mjs +234 -0
- package/dist/cli/git/default-branch.mjs.map +1 -0
- package/dist/cli/git/identity.d.mts +3 -5
- package/dist/cli/git/identity.d.mts.map +1 -1
- package/dist/cli/git/identity.mjs +10 -4
- package/dist/cli/git/identity.mjs.map +1 -1
- package/dist/cli/install/legacy-paths.d.mts.map +1 -1
- package/dist/cli/install/legacy-paths.mjs +2 -0
- package/dist/cli/install/legacy-paths.mjs.map +1 -1
- package/dist/cli/install/mcp-provision.d.mts +26 -0
- package/dist/cli/install/mcp-provision.d.mts.map +1 -0
- package/dist/cli/install/mcp-provision.mjs +281 -0
- package/dist/cli/install/mcp-provision.mjs.map +1 -0
- package/dist/cli/install/mcp-server-specs.d.mts +80 -0
- package/dist/cli/install/mcp-server-specs.d.mts.map +1 -0
- package/dist/cli/install/mcp-server-specs.mjs +102 -0
- package/dist/cli/install/mcp-server-specs.mjs.map +1 -0
- package/dist/cli/install/runtime-detect.d.mts +1 -0
- package/dist/cli/install/runtime-detect.d.mts.map +1 -1
- package/dist/cli/install/runtime-detect.mjs +5 -0
- package/dist/cli/install/runtime-detect.mjs.map +1 -1
- package/dist/cli/install/toml-merge.d.mts +40 -0
- package/dist/cli/install/toml-merge.d.mts.map +1 -0
- package/dist/cli/install/toml-merge.mjs +134 -0
- package/dist/cli/install/toml-merge.mjs.map +1 -0
- package/dist/cli/personas/sidecar.d.mts +1 -1
- package/dist/cli/roadmap/lifecycle.d.mts +1 -1
- package/dist/cli/roadmap/rollup.d.mts +2 -2
- package/dist/cli/util/events-path.d.mts +8 -0
- package/dist/cli/util/events-path.d.mts.map +1 -0
- package/dist/cli/util/events-path.mjs +23 -0
- package/dist/cli/util/events-path.mjs.map +1 -0
- package/dist/cli/util/runtime-capabilities.d.mts +30 -0
- package/dist/cli/util/runtime-capabilities.d.mts.map +1 -0
- package/dist/cli/util/runtime-capabilities.mjs +214 -0
- package/dist/cli/util/runtime-capabilities.mjs.map +1 -0
- package/dist/cli/verify-proof/audit.d.mts +2 -7
- package/dist/cli/verify-proof/audit.d.mts.map +1 -1
- package/dist/cli/verify-proof/audit.mjs +11 -17
- package/dist/cli/verify-proof/audit.mjs.map +1 -1
- package/dist/cli/verify-proof/runtime-detect.d.mts +2 -29
- package/dist/cli/verify-proof/runtime-detect.d.mts.map +1 -1
- package/dist/cli/verify-proof/runtime-detect.mjs +8 -203
- package/dist/cli/verify-proof/runtime-detect.mjs.map +1 -1
- package/dist/plugin/.claude-plugin/plugin.json +2 -1
- package/dist/plugin/agents/apt-verifier.md +6 -3
- package/dist/plugin/skills/apt/SKILL.md +29 -0
- package/dist/plugin/skills/apt-catch-up/SKILL.md +79 -0
- package/dist/plugin/skills/apt-pr-review/SKILL.md +59 -4
- package/dist/plugin/skills/apt-setup/SKILL.md +76 -0
- package/dist/plugin/skills/apt-verify/SKILL.md +1 -1
- package/dist/plugin/skills/apt-verify-proof/SKILL.md +25 -1
- package/drivers/browser/skill/agent-browser/SKILL.md +51 -0
- package/drivers/tauri/README.md +107 -0
- package/drivers/tauri/driver.mjs +88 -0
- package/drivers/tauri/manifest.json +37 -0
- package/drivers/tauri/scripts/tauri-mcp.sh +41 -0
- package/package.json +138 -138
- package/skills/apt/SKILL.md +29 -0
- package/skills/apt-catch-up/SKILL.md +79 -0
- package/skills/apt-pr-review/SKILL.md +59 -4
- package/skills/apt-setup/SKILL.md +76 -0
- package/skills/apt-verify/SKILL.md +1 -1
- package/skills/apt-verify-proof/SKILL.md +25 -1
- package/src/cli/commands/catch-up.mjs +67 -0
- package/src/cli/commands/init.mjs +19 -0
- package/src/cli/commands/pr-review.mjs +32 -11
- package/src/cli/commands/route.mjs +92 -1
- package/src/cli/config/share-policy.mjs +1 -0
- package/src/cli/config/upgrade-gitignore.mjs +1 -0
- package/src/cli/consistency/parse-review.mjs +5 -3
- package/src/cli/consistency/rules/r5-verdict-consistency.mjs +14 -9
- package/src/cli/coordination/catch-up.mjs +231 -0
- package/src/cli/coordination/last-seen.mjs +131 -0
- package/src/cli/coordination/store.mjs +18 -0
- package/src/cli/dispatch.mjs +2 -0
- package/src/cli/gate/gates/review-clean.mjs +4 -2
- package/src/cli/git/default-branch.mjs +250 -0
- package/src/cli/git/identity.mjs +9 -3
- package/src/cli/install/legacy-paths.mjs +2 -0
- package/src/cli/install/mcp-provision.mjs +293 -0
- package/src/cli/install/mcp-server-specs.mjs +101 -0
- package/src/cli/install/runtime-detect.mjs +9 -0
- package/src/cli/install/toml-merge.mjs +139 -0
- package/src/cli/util/events-path.mjs +24 -0
- package/src/cli/util/runtime-capabilities.mjs +216 -0
- package/src/cli/verify-proof/audit.mjs +11 -17
- package/src/cli/verify-proof/runtime-detect.mjs +11 -204
- package/templates/config.json +13 -1
|
@@ -1,209 +1,14 @@
|
|
|
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
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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).
|
|
19
|
-
*/
|
|
20
|
-
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
21
|
-
import { join, resolve } from 'node:path';
|
|
22
|
-
/**
|
|
23
|
-
* @typedef {Object} RuntimeCapabilities
|
|
24
|
-
* @property {boolean} is_electron
|
|
25
|
-
* @property {boolean} is_tauri
|
|
26
|
-
* @property {boolean} is_nextjs
|
|
27
|
-
* @property {boolean} is_nuxt
|
|
28
|
-
* @property {boolean} is_web_frontend
|
|
29
|
-
* @property {boolean} is_expo
|
|
30
|
-
* @property {boolean} is_react_native
|
|
31
|
-
* @property {boolean} has_node
|
|
32
|
-
*/
|
|
33
|
-
/** A capability record with every flag defaulted to false. */
|
|
34
|
-
function emptyCapabilities() {
|
|
35
|
-
return {
|
|
36
|
-
is_electron: false,
|
|
37
|
-
is_tauri: false,
|
|
38
|
-
is_nextjs: false,
|
|
39
|
-
is_nuxt: false,
|
|
40
|
-
is_web_frontend: false,
|
|
41
|
-
is_expo: false,
|
|
42
|
-
is_react_native: false,
|
|
43
|
-
has_node: false,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Detect runtime capabilities from a parsed package.json object.
|
|
48
|
-
*
|
|
49
|
-
* @param {Record<string, unknown> | null} packageJson
|
|
50
|
-
* @returns {RuntimeCapabilities}
|
|
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.
|
|
51
9
|
*/
|
|
52
|
-
export
|
|
53
|
-
const capabilities = emptyCapabilities();
|
|
54
|
-
if (packageJson === null || typeof packageJson !== 'object')
|
|
55
|
-
return capabilities;
|
|
56
|
-
const allDeps = {
|
|
57
|
-
...(packageJson.dependencies ?? {}) /** @type {Record<string,string>} */,
|
|
58
|
-
...(packageJson.devDependencies ?? {}) /** @type {Record<string,string>} */,
|
|
59
|
-
};
|
|
60
|
-
const deps = new Set(Object.keys(allDeps).map((k) => k.toLowerCase()));
|
|
61
|
-
if (deps.has('electron') || [...deps].some((d) => d.startsWith('@electron'))) {
|
|
62
|
-
capabilities.is_electron = true;
|
|
63
|
-
}
|
|
64
|
-
if (deps.has('@tauri-apps/api') || deps.has('tauri')) {
|
|
65
|
-
capabilities.is_tauri = true;
|
|
66
|
-
}
|
|
67
|
-
if (deps.has('expo'))
|
|
68
|
-
capabilities.is_expo = true;
|
|
69
|
-
if (deps.has('react-native'))
|
|
70
|
-
capabilities.is_react_native = true;
|
|
71
|
-
// Web frontends — react/vue/svelte/angular/solid → frontend. BUT: an
|
|
72
|
-
// Electron app commonly bundles React as its renderer; in that case the
|
|
73
|
-
// runtime is "electron", not "web_frontend". Electron + react-native +
|
|
74
|
-
// expo + tauri all win over the web flag.
|
|
75
|
-
const isNativeContainer = capabilities.is_electron ||
|
|
76
|
-
capabilities.is_tauri ||
|
|
77
|
-
capabilities.is_react_native ||
|
|
78
|
-
capabilities.is_expo;
|
|
79
|
-
const webFrameworks = ['react', 'vue', 'svelte', 'angular', 'solid'];
|
|
80
|
-
if (!isNativeContainer && webFrameworks.some((f) => deps.has(f))) {
|
|
81
|
-
capabilities.is_web_frontend = true;
|
|
82
|
-
}
|
|
83
|
-
if (deps.has('next')) {
|
|
84
|
-
capabilities.is_nextjs = true;
|
|
85
|
-
capabilities.is_web_frontend = true;
|
|
86
|
-
}
|
|
87
|
-
if (deps.has('nuxt')) {
|
|
88
|
-
capabilities.is_nuxt = true;
|
|
89
|
-
capabilities.is_web_frontend = true;
|
|
90
|
-
}
|
|
91
|
-
if (deps.has('vite') && !isNativeContainer) {
|
|
92
|
-
capabilities.is_web_frontend = true;
|
|
93
|
-
}
|
|
94
|
-
// Node-ish? Anything with a package.json + an entry point counts.
|
|
95
|
-
if (typeof packageJson.main === 'string' || typeof packageJson.module === 'string') {
|
|
96
|
-
capabilities.has_node = true;
|
|
97
|
-
}
|
|
98
|
-
if (!capabilities.has_node && packageJson.scripts && typeof packageJson.scripts === 'object') {
|
|
99
|
-
capabilities.has_node = true;
|
|
100
|
-
}
|
|
101
|
-
return capabilities;
|
|
102
|
-
}
|
|
10
|
+
export { detectFromPackageJson, loadRuntimeCapabilities, } from '../util/runtime-capabilities.mjs';
|
|
103
11
|
/**
|
|
104
|
-
*
|
|
105
|
-
* v0.8.6 — also walks `monorepo_globs` (default `['apps/*']`) and
|
|
106
|
-
* OR-merges each match's capabilities with the root.
|
|
107
|
-
*
|
|
108
|
-
* @param {string} projectDir
|
|
109
|
-
* @param {{monorepo_globs?: string[]}} [opts]
|
|
110
|
-
* @returns {RuntimeCapabilities}
|
|
111
|
-
*/
|
|
112
|
-
export function loadRuntimeCapabilities(projectDir, opts) {
|
|
113
|
-
const root = resolve(projectDir);
|
|
114
|
-
const rootPkgPath = join(root, 'package.json');
|
|
115
|
-
let rootCaps = emptyCapabilities();
|
|
116
|
-
if (existsSync(rootPkgPath)) {
|
|
117
|
-
try {
|
|
118
|
-
rootCaps = detectFromPackageJson(JSON.parse(readFileSync(rootPkgPath, 'utf-8')));
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
/* fall through with empty caps */
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
// Default to the canonical Aperant monorepo layout. Passing `[]`
|
|
125
|
-
// disables the walk entirely (root-only escape hatch per spec ID-05).
|
|
126
|
-
const globs = opts && Array.isArray(opts.monorepo_globs) ? opts.monorepo_globs : ['apps/*'];
|
|
127
|
-
if (globs.length === 0)
|
|
128
|
-
return rootCaps;
|
|
129
|
-
let merged = rootCaps;
|
|
130
|
-
for (const glob of globs) {
|
|
131
|
-
const matches = expandSimpleGlob(root, glob);
|
|
132
|
-
for (const dir of matches) {
|
|
133
|
-
const childPkgPath = join(dir, 'package.json');
|
|
134
|
-
if (!existsSync(childPkgPath))
|
|
135
|
-
continue;
|
|
136
|
-
try {
|
|
137
|
-
const childCaps = detectFromPackageJson(JSON.parse(readFileSync(childPkgPath, 'utf-8')));
|
|
138
|
-
merged = orMergeCapabilities(merged, childCaps);
|
|
139
|
-
}
|
|
140
|
-
catch {
|
|
141
|
-
/* skip malformed package.json */
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return merged;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Expand a simple `prefix/*` glob against the root. Supports ONLY the
|
|
149
|
-
* `<dir>/*` shape (matches each direct subdirectory of `<dir>`). Other
|
|
150
|
-
* glob syntax is intentionally rejected — v1 keeps the dep surface
|
|
151
|
-
* small. Fails closed on malformed patterns (returns []).
|
|
152
|
-
*
|
|
153
|
-
* @param {string} root
|
|
154
|
-
* @param {string} glob
|
|
155
|
-
* @returns {string[]}
|
|
156
|
-
*/
|
|
157
|
-
function expandSimpleGlob(root, glob) {
|
|
158
|
-
if (typeof glob !== 'string' || !glob.endsWith('/*'))
|
|
159
|
-
return [];
|
|
160
|
-
const prefix = glob.slice(0, -2);
|
|
161
|
-
if (prefix.length === 0 || prefix.includes('*'))
|
|
162
|
-
return [];
|
|
163
|
-
const dir = join(root, prefix);
|
|
164
|
-
if (!existsSync(dir))
|
|
165
|
-
return [];
|
|
166
|
-
let entries;
|
|
167
|
-
try {
|
|
168
|
-
entries = readdirSync(dir);
|
|
169
|
-
}
|
|
170
|
-
catch {
|
|
171
|
-
return [];
|
|
172
|
-
}
|
|
173
|
-
const matches = [];
|
|
174
|
-
for (const name of entries) {
|
|
175
|
-
const sub = join(dir, name);
|
|
176
|
-
try {
|
|
177
|
-
if (statSync(sub).isDirectory())
|
|
178
|
-
matches.push(sub);
|
|
179
|
-
}
|
|
180
|
-
catch {
|
|
181
|
-
/* skip unreadable entries */
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return matches;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Boolean OR-merge of two capability records. Any flag true in either
|
|
188
|
-
* input is true in the output. The "Electron wins over web" rule from
|
|
189
|
-
* `detectFromPackageJson` is preserved when this is called repeatedly —
|
|
190
|
-
* each child's flags are honest about that child's own shape, and the
|
|
191
|
-
* OR-merge just unions them.
|
|
192
|
-
*
|
|
193
|
-
* @param {RuntimeCapabilities} a
|
|
194
|
-
* @param {RuntimeCapabilities} b
|
|
195
|
-
* @returns {RuntimeCapabilities}
|
|
12
|
+
* @typedef {import('../util/runtime-capabilities.mjs').RuntimeCapabilities} RuntimeCapabilities
|
|
196
13
|
*/
|
|
197
|
-
function orMergeCapabilities(a, b) {
|
|
198
|
-
return {
|
|
199
|
-
is_electron: a.is_electron || b.is_electron,
|
|
200
|
-
is_tauri: a.is_tauri || b.is_tauri,
|
|
201
|
-
is_nextjs: a.is_nextjs || b.is_nextjs,
|
|
202
|
-
is_nuxt: a.is_nuxt || b.is_nuxt,
|
|
203
|
-
is_web_frontend: a.is_web_frontend || b.is_web_frontend,
|
|
204
|
-
is_expo: a.is_expo || b.is_expo,
|
|
205
|
-
is_react_native: a.is_react_native || b.is_react_native,
|
|
206
|
-
has_node: a.has_node || b.has_node,
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
14
|
//# sourceMappingURL=runtime-detect.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-detect.mjs","sourceRoot":"","sources":["../../../src/cli/verify-proof/runtime-detect.mjs"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"runtime-detect.mjs","sourceRoot":"","sources":["../../../src/cli/verify-proof/runtime-detect.mjs"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACN,qBAAqB,EACrB,uBAAuB,GACvB,MAAM,kCAAkC,CAAA;AAEzC;;GAEG"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aperant",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "AI coding framework — composable skills for planning, executing, verifying, and reviewing code with any LLM provider. Works as Claude Code commands, Codex tasks, or programmatically.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mikalsen AI",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"skills/apt",
|
|
26
26
|
"skills/apt-author-skill",
|
|
27
27
|
"skills/apt-bootstrap",
|
|
28
|
+
"skills/apt-catch-up",
|
|
28
29
|
"skills/apt-caveman",
|
|
29
30
|
"skills/apt-classify",
|
|
30
31
|
"skills/apt-close-task",
|
|
@@ -105,9 +105,12 @@ Either shape is accepted:
|
|
|
105
105
|
|
|
106
106
|
Gate G8 (`consistency-check`) enforces this on ship via rules R4
|
|
107
107
|
(finding-propagation) and R5 (verdict-consistency):
|
|
108
|
-
- `verdict: "approved"`
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
- `verdict: "approved"` or `verdict: "approved-with-notes"` is incompatible
|
|
109
|
+
with any unresolved `critical` or `major` review finding (G42 Phase 1).
|
|
110
|
+
Neither verdict escapes R5 for blocking-severity findings. The sole bypass
|
|
111
|
+
is `--force --reason "<why>"` on the gate CLI (audit-logged). For
|
|
112
|
+
non-blocking findings (suggestion/note/info/nitpick), cite them in
|
|
113
|
+
`findings.notes` and use `approved-with-notes`.
|
|
111
114
|
- `verdict: "rejected"` requires at least one cited finding (rejected
|
|
112
115
|
without evidence is treated as drift).
|
|
113
116
|
|
|
@@ -75,6 +75,34 @@ SessionStart hook — zero latency on /apt. If `update_check` is null,
|
|
|
75
75
|
no chip. Skip the chip entirely once the user has run `/apt:update`
|
|
76
76
|
in the current session (the cache is cleared there).
|
|
77
77
|
|
|
78
|
+
**Catch-up panel (runtime-agnostic):** if the route envelope includes a
|
|
79
|
+
non-null `catch_up` field, print the combined panel BEFORE the mode handler
|
|
80
|
+
runs, regardless of runtime (Claude Code, Codex, Gemini, Cursor, …). The
|
|
81
|
+
panel has two halves; render `catch_up.welcome_back` first, then
|
|
82
|
+
`catch_up.team_digest`. Omit a half whose field is null.
|
|
83
|
+
|
|
84
|
+
If `catch_up.welcome_back` is present (your own half-finished work):
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Where you left off: {description} — {lifecycle_phase}{current_subtask ? " · subtask " + current_subtask : ""} ({relative_time})
|
|
88
|
+
{next_step ? " Next: " + next_step : ""}
|
|
89
|
+
{others_count > 0 ? " (+" + others_count + " others · /apt:resume)" : ""}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
If `catch_up.team_digest` is present (what teammates merged while you were away):
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
While you were away:
|
|
96
|
+
{for each entry in team_digest.entries: " #" + number + " " + title + " — " + author}
|
|
97
|
+
{team_digest.more_count > 0 ? " +" + team_digest.more_count + " more on main" : ""}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
This is display-only here — the Last-Seen Marker advance happens in route.mjs,
|
|
101
|
+
not in this skill. The panel is computed lazily on interactive (TTY) calls
|
|
102
|
+
only; non-TTY/background/spawned calls carry no `catch_up` field. Do not call
|
|
103
|
+
it an "activity feed", "changelog", or "notifications" — it is the
|
|
104
|
+
Welcome-Back Summary + Team-Change Digest.
|
|
105
|
+
|
|
78
106
|
Then proceed to the matching mode handler below. Do NOT deviate from the routing decision.
|
|
79
107
|
</mandatory_first_step>
|
|
80
108
|
|
|
@@ -129,6 +157,7 @@ Show available commands table:
|
|
|
129
157
|
| `apt:scan` | Discover standards + refresh feature registry |
|
|
130
158
|
| `apt:docs` | Generate/update documentation |
|
|
131
159
|
| `apt:resume` | Restore context after session break |
|
|
160
|
+
| `apt:catch-up` | Re-view the catch-up panel (Welcome-Back + Team-Change Digest) — never advances the Last-Seen Marker |
|
|
132
161
|
| `apt:pause` | Human-initiated handoff — save state when YOU need to stop |
|
|
133
162
|
| `apt:ship` | Create PR with traceability |
|
|
134
163
|
| `apt:close-task` | Post-merge closer — confirm PR merged, flip phase, drain narration ledger |
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: apt:catch-up
|
|
3
|
+
description: "Re-view the catch-up panel (Welcome-Back + Team-Change Digest) on demand"
|
|
4
|
+
apt-skill-version: {{APT_VERSION}}
|
|
5
|
+
stage: resume
|
|
6
|
+
intent: capture
|
|
7
|
+
when_to_use: "The user dismissed the auto catch-up panel on their last /apt and wants to re-summon it — an idempotent re-view of where they left off plus what teammates merged. Distinct from /apt:resume (full context restore) and never advances the Last-Seen Marker."
|
|
8
|
+
user_invocable: true
|
|
9
|
+
internal: false
|
|
10
|
+
spawns_agent: false
|
|
11
|
+
agent_name: null
|
|
12
|
+
task_context: none
|
|
13
|
+
default_execution_mode: auto
|
|
14
|
+
execution_modes:
|
|
15
|
+
- auto
|
|
16
|
+
allowed-tools: "Bash, Read"
|
|
17
|
+
argument-hint: "apt:catch-up"
|
|
18
|
+
gates: []
|
|
19
|
+
---
|
|
20
|
+
<objective>
|
|
21
|
+
Recompute and display the combined catch-up panel — the **Welcome-Back
|
|
22
|
+
Summary** (your most-recently-active task, phase, next step) and the
|
|
23
|
+
**Team-Change Digest** (the PRs teammates merged to main since you last
|
|
24
|
+
pulled) — exactly as the auto-on-apt display would show it, but **without
|
|
25
|
+
advancing the Last-Seen Marker**. This is a read-only re-view: a user who
|
|
26
|
+
dismissed the auto panel can re-summon it without disturbing the baseline and
|
|
27
|
+
without invoking the heavier `/apt:resume`.
|
|
28
|
+
</objective>
|
|
29
|
+
|
|
30
|
+
<your_environment>
|
|
31
|
+
- **Working directory:** The project root (where you were invoked)
|
|
32
|
+
- **apt-tools:** `node packages/framework/bin/apt-tools.mjs` or the installed `apt-tools` binary
|
|
33
|
+
- **Last-Seen Marker:** `.aperant/last-seen/{email-slug}.json` (gitignored, per-machine) — this skill READS it but NEVER writes it.
|
|
34
|
+
</your_environment>
|
|
35
|
+
|
|
36
|
+
<process>
|
|
37
|
+
|
|
38
|
+
## 1. Recompute the panel (read-only)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
node packages/framework/bin/apt-tools.mjs catch-up .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This computes the SAME panel the interactive route call produces, against the
|
|
45
|
+
**current** marker — and deliberately does **NOT** call `advanceLastSeen`
|
|
46
|
+
(recompute-only contract). Parse the JSON `catch_up` field from the envelope.
|
|
47
|
+
|
|
48
|
+
## 2. Render the panel
|
|
49
|
+
|
|
50
|
+
Render exactly as the `apt/SKILL.md` "Catch-up panel" block does — Welcome-Back
|
|
51
|
+
half first, then the Team-Change Digest half. Omit a half whose field is null.
|
|
52
|
+
|
|
53
|
+
If `catch_up` is null, tell the user there is nothing new since their last
|
|
54
|
+
visit (no active stale task and no new merges on main).
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
Where you left off: {description} — {lifecycle_phase} · subtask {current_subtask} ({relative_time})
|
|
58
|
+
Next: {next_step}
|
|
59
|
+
(+{others_count} others · /apt:resume)
|
|
60
|
+
|
|
61
|
+
While you were away:
|
|
62
|
+
#{number} {title} — {author}
|
|
63
|
+
+{more_count} more on main
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
</process>
|
|
67
|
+
|
|
68
|
+
<notes>
|
|
69
|
+
- **Never advances the marker.** Unlike the auto-on-apt display (which advances
|
|
70
|
+
the Last-Seen Marker after the panel is evaluated), this command is purely a
|
|
71
|
+
re-view. Re-running it is idempotent.
|
|
72
|
+
- **Distinct from `/apt:resume`.** Resume restores full context and routes to
|
|
73
|
+
the next action; catch-up is a lightweight orientation re-view.
|
|
74
|
+
- **v1 is lazy compute.** The panel is computed on demand here, bounded by the
|
|
75
|
+
commits since your last pull. A background pre-warm worker (like the
|
|
76
|
+
update-check worker) is a tracked follow-up (LD-12), not part of v1.
|
|
77
|
+
- **Vocabulary.** This is the Welcome-Back Summary + Team-Change Digest — not an
|
|
78
|
+
"activity feed", "changelog", or "notifications".
|
|
79
|
+
</notes>
|
|
@@ -247,10 +247,11 @@ The command resolves in this precedence order:
|
|
|
247
247
|
|
|
248
248
|
1. `config.json:pr_review.authorship_overrides['pr-${PR_NUMBER}']` (per-PR pin)
|
|
249
249
|
2. `config.json:pr_review.authorship_override` (global: `owned` | `external` | `auto`)
|
|
250
|
-
3. `gh pr view` → `
|
|
251
|
-
-
|
|
252
|
-
-
|
|
253
|
-
|
|
250
|
+
3. `gh pr view` → `gh.author.login` vs. viewer login (G44 — `owned` means a PR you **authored**, not a branch you can push to)
|
|
251
|
+
- Same-repo branch AND `gh.author.login === viewer login` → **owned**
|
|
252
|
+
- Any other same-repo PR (a teammate's, or a repo-`OWNER` viewing someone else's PR) → **external** (`authorAssociation` is no longer consulted for the `owned` decision — it is retained only in the human-readable signal)
|
|
253
|
+
- Fork (head-repo owner ≠ base-repo owner) → **external**
|
|
254
|
+
4. Offline / gh unavailable / ambiguous payload → **unknown** (treated as `external` for safety, see below)
|
|
254
255
|
|
|
255
256
|
When the result is `unknown`, treat it as `external` for safety and prompt the user:
|
|
256
257
|
|
|
@@ -469,6 +470,55 @@ fi
|
|
|
469
470
|
|
|
470
471
|
After this point, the per-round artifact root is `.aperant/pr-reviews/pr-${PR_NUMBER}/rounds/${ROUND}/` (the `${REVIEW_ID}` is still used for the git worktree branch and temporary files). Subsequent `git diff` invocations within the round use `${PINNED_HEAD_SHA}` as the head ref.
|
|
471
472
|
|
|
473
|
+
### Step 4c: Mergeability Pre-Check (PR reviews only)
|
|
474
|
+
|
|
475
|
+
**Why this exists.** The review diff is `git diff {BASE}...{HEAD}` (three-dot — from the *merge-base*), so it shows the PR's own changes relative to where it branched. It is **blind to drift on `{BASE}` since then** and therefore says nothing about whether the PR still merges cleanly. A PR can pass a glowing review and be unmergeable. This step closes that gap: it is **informational, never blocking** (the review still runs in full), but a conflicting/stale state MUST be surfaced so the reader doesn't trust a review of a diff that no longer applies.
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
# PR-mode only. Query GitHub's authoritative mergeability + measure drift.
|
|
479
|
+
if [ -n "$PR_NUMBER" ]; then
|
|
480
|
+
MERGE_JSON=$(gh pr view ${PR_NUMBER} --json mergeable,mergeStateStatus,baseRefName 2>/dev/null)
|
|
481
|
+
MERGEABLE=$(echo "$MERGE_JSON" | jq -r '.mergeable // "UNKNOWN"')
|
|
482
|
+
MERGE_STATE=$(echo "$MERGE_JSON" | jq -r '.mergeStateStatus // "UNKNOWN"')
|
|
483
|
+
BASE_REF=$(echo "$MERGE_JSON" | jq -r '.baseRefName // "main"')
|
|
484
|
+
git fetch origin "${BASE_REF}" 2>/dev/null
|
|
485
|
+
BEHIND=$(git rev-list --count ${PINNED_HEAD_SHA}..origin/${BASE_REF} 2>/dev/null || echo "?")
|
|
486
|
+
AHEAD=$(git rev-list --count origin/${BASE_REF}..${PINNED_HEAD_SHA} 2>/dev/null || echo "?")
|
|
487
|
+
|
|
488
|
+
# If GitHub reports a conflict (or hasn't computed yet), enumerate the conflicting
|
|
489
|
+
# files locally without touching any working tree (git >= 2.38):
|
|
490
|
+
CONFLICT_FILES=""
|
|
491
|
+
if [ "$MERGEABLE" = "CONFLICTING" ] || [ "$MERGE_STATE" = "DIRTY" ]; then
|
|
492
|
+
CONFLICT_FILES=$(git merge-tree --write-tree --name-only origin/${BASE_REF} ${PINNED_HEAD_SHA} 2>/dev/null \
|
|
493
|
+
| tail -n +2 | sed '/^$/d' | grep '/' )
|
|
494
|
+
fi
|
|
495
|
+
fi
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
Record the result in `metadata.json` under a `mergeability` key:
|
|
499
|
+
|
|
500
|
+
```json
|
|
501
|
+
{
|
|
502
|
+
"mergeability": {
|
|
503
|
+
"mergeable": "CONFLICTING | MERGEABLE | UNKNOWN",
|
|
504
|
+
"merge_state_status": "DIRTY | CLEAN | BLOCKED | BEHIND | ...",
|
|
505
|
+
"base_ref": "main",
|
|
506
|
+
"commits_behind_base": 101,
|
|
507
|
+
"commits_ahead_base": 91,
|
|
508
|
+
"conflicting_files": ["apps/.../App.tsx", "..."]
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
**How to use the result:**
|
|
514
|
+
|
|
515
|
+
- `MERGEABLE` ∈ {`CONFLICTING`} OR `MERGE_STATE` = `DIRTY` → the PR has conflicts. Surface a **⚠️ Mergeability** block in the Phase 5 intermediate report AND the Phase 8 final report, listing `commits_behind_base` and the `conflicting_files`. In **external / comment-only** mode, include the same block in the Phase 6b comment. State plainly that the branch needs a rebase/merge from `{BASE}` and that **the reviewed diff may be stale** with respect to current `{BASE}`.
|
|
516
|
+
- `MERGE_STATE` = `BEHIND` (mergeable but behind) → note the drift (`commits_behind_base`) as a softer advisory; no conflict, but the diff predates recent `{BASE}` commits.
|
|
517
|
+
- `MERGEABLE` = `UNKNOWN` (GitHub hasn't finished computing, common right after a push) → record `UNKNOWN`; optionally re-poll once after a few seconds. Do not block.
|
|
518
|
+
- `MERGEABLE` = `MERGEABLE`, `MERGE_STATE` = `CLEAN` → record it and move on silently.
|
|
519
|
+
|
|
520
|
+
This step never changes the review's findings or assessment — a conflicting PR with zero code findings is still `approve` on its own merits. Mergeability is reported as a **separate** signal so the reader knows whether the approval can actually land.
|
|
521
|
+
|
|
472
522
|
### Step 5: Read All Changed Files
|
|
473
523
|
|
|
474
524
|
For every file in the changed file list, read it in full using the Read tool **from the worktree**:
|
|
@@ -1058,6 +1108,10 @@ Review Synthesis (Before Auto-Fix)
|
|
|
1058
1108
|
Auto-Checks: {PASS/FAIL}
|
|
1059
1109
|
lint: {P/F} | typecheck: {P/F} | tests: {P/F}
|
|
1060
1110
|
|
|
1111
|
+
Mergeability (PR reviews — from Step 4c): {MERGEABLE/CONFLICTING/UNKNOWN}
|
|
1112
|
+
{if CONFLICTING/DIRTY: "⚠️ conflicts with {BASE} — {behind} commits behind — needs rebase — reviewed diff may be stale"}
|
|
1113
|
+
{if conflicting_files: list them}
|
|
1114
|
+
|
|
1061
1115
|
Validated Findings:
|
|
1062
1116
|
CRITICAL: {N}
|
|
1063
1117
|
HIGH: {N}
|
|
@@ -1630,6 +1684,7 @@ Output the human-readable summary:
|
|
|
1630
1684
|
|
|
1631
1685
|
Review ID: {REVIEW_ID}
|
|
1632
1686
|
Assessment: {APPROVE / REQUEST CHANGES / COMMENT}
|
|
1687
|
+
Mergeability: {MERGEABLE / CONFLICTING (N behind {BASE}, needs rebase) / UNKNOWN} # PR reviews — from Step 4c / metadata.json.mergeability
|
|
1633
1688
|
|
|
1634
1689
|
Scores:
|
|
1635
1690
|
Security: {score}/10
|
|
@@ -205,6 +205,7 @@ AskUserQuestion([
|
|
|
205
205
|
- "Visibility" → jump to **Step 3e** (Batch 6 only), then skip to **Step 4** and **Step 5**
|
|
206
206
|
- "Task Tracking" → jump to **Step 3g** (Batch 8 only), then skip to **Step 4** and **Step 5**
|
|
207
207
|
- "Changelog & Release Notes" → jump to **Step 3h** (Batch 9 only), then skip to **Step 4** and **Step 5**
|
|
208
|
+
- "Collaboration" → jump to **Step 3i** (Batch 10 only), then skip to **Step 4** and **Step 5**
|
|
208
209
|
- "Everything" → proceed to **Step 2** and run all batches (same as fresh setup). **Legacy-completes-Everything marker write:** if the starting config has no `onboarding` block (legacy unmarked config) and the user completes the full flow, write a full `onboarding` block at Step 5 as `{ completed: true, seeded_from_template: false, seeded_at: <ISO-8601 now> }` to record the explicit onboarding pass.
|
|
209
210
|
- "Done" → display "Settings unchanged." and exit
|
|
210
211
|
|
|
@@ -1180,6 +1181,74 @@ The selective-edit pass through Batch 9 MUST respect the §1b dispatch — it do
|
|
|
1180
1181
|
|
|
1181
1182
|
---
|
|
1182
1183
|
|
|
1184
|
+
## 3i. Present Settings (Batch 10: Collaboration Catch-Up)
|
|
1185
|
+
|
|
1186
|
+
The **collaboration catch-up** surfaces show on every interactive (TTY) `/apt`
|
|
1187
|
+
call: a **Welcome-Back Summary** (your most-recently-active task + next step,
|
|
1188
|
+
always-on, local-only) and a **Team-Change Digest** (the PRs teammates merged
|
|
1189
|
+
to main since you last pulled — gated to `share.visibility` `team`/`oss`).
|
|
1190
|
+
Written to `.aperant/config.json.collaboration`.
|
|
1191
|
+
|
|
1192
|
+
```
|
|
1193
|
+
AskUserQuestion([
|
|
1194
|
+
{
|
|
1195
|
+
question: "Show the Welcome-Back Summary when you return after a break?",
|
|
1196
|
+
header: "Welcome-Back",
|
|
1197
|
+
multiSelect: false,
|
|
1198
|
+
options: [
|
|
1199
|
+
{ label: "Yes (Recommended)", description: "On your next /apt after the staleness window, surface where you left off — task, phase, next step. Local only." },
|
|
1200
|
+
{ label: "No", description: "Never show the welcome-back nudge." }
|
|
1201
|
+
]
|
|
1202
|
+
},
|
|
1203
|
+
{
|
|
1204
|
+
question: "How many hours away before the Welcome-Back Summary fires?",
|
|
1205
|
+
header: "Threshold (hours)",
|
|
1206
|
+
multiSelect: false,
|
|
1207
|
+
options: [
|
|
1208
|
+
{ label: "16 (Recommended)", description: "Roughly 'since yesterday' — fires after an overnight gap." },
|
|
1209
|
+
{ label: "8", description: "Fires after a long lunch / half-day gap." },
|
|
1210
|
+
{ label: "24", description: "Once-a-day cadence." }
|
|
1211
|
+
]
|
|
1212
|
+
},
|
|
1213
|
+
{
|
|
1214
|
+
question: "Show the Team-Change Digest (teammates' merged PRs since your last pull)?",
|
|
1215
|
+
header: "Team Digest",
|
|
1216
|
+
multiSelect: false,
|
|
1217
|
+
options: [
|
|
1218
|
+
{ label: "Yes (Recommended)", description: "Only computes when share.visibility is team/oss; reads local git history, never fetches." },
|
|
1219
|
+
{ label: "No", description: "Never show the digest, even in team/oss mode." }
|
|
1220
|
+
]
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
question: "Maximum PRs to list in the digest before '+N more on main'?",
|
|
1224
|
+
header: "Digest Max Entries",
|
|
1225
|
+
multiSelect: false,
|
|
1226
|
+
options: [
|
|
1227
|
+
{ label: "7 (Recommended)", description: "Low-noise ceiling; the rest collapse into a '+N more' tail." },
|
|
1228
|
+
{ label: "5", description: "Tighter." },
|
|
1229
|
+
{ label: "12", description: "Roomier." }
|
|
1230
|
+
]
|
|
1231
|
+
}
|
|
1232
|
+
])
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
For hosts without structured prompts, present the same four questions as
|
|
1236
|
+
numbered lists (Batch 5 style) and read single-index responses.
|
|
1237
|
+
|
|
1238
|
+
### 3i.1 Review-Mode routing entry
|
|
1239
|
+
|
|
1240
|
+
The "1b. Review Mode" routing table (§1b) includes "Collaboration" as a
|
|
1241
|
+
selectable edit target — jumping directly back into this Batch 10 picker.
|
|
1242
|
+
|
|
1243
|
+
### 3i.2 Confirmation row
|
|
1244
|
+
|
|
1245
|
+
Add a row to the Step 8 table:
|
|
1246
|
+
```
|
|
1247
|
+
| Collaboration | welcome-back {on/off} ({N}h) · team-digest {on/off} (max {M}) |
|
|
1248
|
+
```
|
|
1249
|
+
|
|
1250
|
+
---
|
|
1251
|
+
|
|
1183
1252
|
## 4. Map Answers to Config
|
|
1184
1253
|
|
|
1185
1254
|
**AUDIT-001 — file-routing contract for per-device fields (UPDATED 0.8.1 for FRAMEWORK-RFC-001):** the
|
|
@@ -1295,6 +1364,12 @@ Note: task ids are slug-first since v0.6.6 — the date-format setting controls
|
|
|
1295
1364
|
- "Sub-Agents" → `"sub-agents"`
|
|
1296
1365
|
- "Sequential" → `"sequential"`
|
|
1297
1366
|
|
|
1367
|
+
**Collaboration Catch-Up (Batch 10):**
|
|
1368
|
+
- Welcome-Back "Yes" → `collaboration.welcome_back.enabled: true`, "No" → `false`
|
|
1369
|
+
- Threshold → `collaboration.welcome_back.threshold_hours: <8|16|24>`
|
|
1370
|
+
- Team Digest "Yes" → `collaboration.team_digest.enabled: true`, "No" → `false`
|
|
1371
|
+
- Digest Max Entries → `collaboration.team_digest.max_entries: <5|7|12>`
|
|
1372
|
+
|
|
1298
1373
|
## 5. Write Config
|
|
1299
1374
|
|
|
1300
1375
|
Write merged config to two files per AUDIT-001 routing (see Step 4 block):
|
|
@@ -1402,6 +1477,7 @@ Display:
|
|
|
1402
1477
|
| Debate Mode | {Auto / Agent Team / Sub-Agents / Sequential} |
|
|
1403
1478
|
| Visibility | {solo / team / oss} (overrides if any) |
|
|
1404
1479
|
| Changelog & Release Notes | dev: {Yes/No}; release-notes: {Yes/No} (audience, persona-filter) |
|
|
1480
|
+
| Collaboration | welcome-back {on/off} ({N}h) · team-digest {on/off} (max {M}) |
|
|
1405
1481
|
| Saved as Defaults | {Yes/No} |
|
|
1406
1482
|
|
|
1407
1483
|
Config saved to: .aperant/config.json
|
|
@@ -60,7 +60,7 @@ Before spawning any verifier subagent or running scoring against acceptance crit
|
|
|
60
60
|
</locked_decisions>
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
Verifiers apply this digest when interpreting "completeness" and "correctness" — if a decision explicitly deferred a behavior, its absence is NOT a verification failure.
|
|
63
|
+
Verifiers apply this digest when interpreting "completeness" and "correctness" — if a decision explicitly deferred a behavior AND the deferred finding has severity below critical or major, its absence is NOT a verification failure. A deferred critical or major finding IS a Completeness gap — score accordingly and note it in the issues list.
|
|
64
64
|
</decision_ledger_inject>
|
|
65
65
|
|
|
66
66
|
<process>
|
|
@@ -20,6 +20,7 @@ gates: []
|
|
|
20
20
|
config_keys:
|
|
21
21
|
- verification.open_report
|
|
22
22
|
- verification.report_formats
|
|
23
|
+
- verification.provision_mcp
|
|
23
24
|
---
|
|
24
25
|
|
|
25
26
|
# Proof Verification
|
|
@@ -104,13 +105,36 @@ disable the walk entirely (root-only behaviour, backwards compat).
|
|
|
104
105
|
The `verification.runtimes[]` override stays the final escape hatch
|
|
105
106
|
and is now usually unnecessary because the walk runs by default.
|
|
106
107
|
|
|
107
|
-
### Bundled drivers (
|
|
108
|
+
### Bundled drivers (5)
|
|
108
109
|
|
|
109
110
|
- **browser** (priority=100, ga) — Next.js / vanilla web frontends.
|
|
110
111
|
- **electron** (priority=90, ga) — Electron desktop apps.
|
|
112
|
+
- **tauri** (priority=85, ga) — Tauri desktop apps.
|
|
111
113
|
- **cli** (priority=60, ga) — headless CI, output-shape assertions.
|
|
112
114
|
- **api** (priority=50, ga) — HTTP / JSON-API regression tests.
|
|
113
115
|
|
|
116
|
+
### Install-time MCP provisioning (verification.provision_mcp)
|
|
117
|
+
|
|
118
|
+
`apt-tools init` (and `/apt:update`, which routes through the same path)
|
|
119
|
+
auto-provisions the MCP transport a driver needs into each SELECTED host
|
|
120
|
+
CLI's config, so verify-proof works at the prompt with no manual MCP
|
|
121
|
+
setup. It detects the project runtime and, per host:
|
|
122
|
+
|
|
123
|
+
- **claude** → JSON-merges the server into the project-root `.mcp.json`
|
|
124
|
+
(`mcpServers.<id>`).
|
|
125
|
+
- **codex** → upserts a `[mcp_servers.<id>]` table into the project-root
|
|
126
|
+
`.codex/config.toml`.
|
|
127
|
+
|
|
128
|
+
Electron and Tauri projects get the matching MCP server; web frontends
|
|
129
|
+
get the browser driver's declared `agent-browser` skill copied into the
|
|
130
|
+
host skill dir (`.claude/skills/` / `.agents/skills/`) — its `agent-browser`
|
|
131
|
+
CLI is a documented one-time prereq, the same class as the
|
|
132
|
+
`electron-mcp-server` / `tauri-plugin-mcp-server` npm packages (see each
|
|
133
|
+
driver's README). All writes are **TOFU/non-clobbering**: a pre-existing
|
|
134
|
+
server id, config table, or skill file is never overwritten. Opt out with
|
|
135
|
+
`verification.provision_mcp: false` (default `true`) — then init/update
|
|
136
|
+
writes no host MCP config and no skill.
|
|
137
|
+
|
|
114
138
|
### Driver authors
|
|
115
139
|
|
|
116
140
|
Third-party driver authors should run `apt-tools driver doctor .` before
|