@aperant/framework 0.10.0 → 0.12.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 +236 -1
- package/agents/apt-planner.md +15 -0
- package/agents/apt-verifier.md +15 -10
- package/bin/apt-proof-video.mjs +256 -76
- package/dist/cli/commands/apply-recipe.d.mts +6 -0
- package/dist/cli/commands/apply-recipe.d.mts.map +1 -0
- package/dist/cli/commands/apply-recipe.mjs +98 -0
- package/dist/cli/commands/apply-recipe.mjs.map +1 -0
- 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/mobile-prepare.d.mts +53 -0
- package/dist/cli/commands/mobile-prepare.d.mts.map +1 -0
- package/dist/cli/commands/mobile-prepare.mjs +139 -0
- package/dist/cli/commands/mobile-prepare.mjs.map +1 -0
- 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/recipe-diff.d.mts +6 -0
- package/dist/cli/commands/recipe-diff.d.mts.map +1 -0
- package/dist/cli/commands/recipe-diff.mjs +75 -0
- package/dist/cli/commands/recipe-diff.mjs.map +1 -0
- package/dist/cli/commands/roadmap.d.mts.map +1 -1
- package/dist/cli/commands/roadmap.mjs +53 -0
- package/dist/cli/commands/roadmap.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/verify-sandbox.d.mts +6 -0
- package/dist/cli/commands/verify-sandbox.d.mts.map +1 -0
- package/dist/cli/commands/verify-sandbox.mjs +200 -0
- package/dist/cli/commands/verify-sandbox.mjs.map +1 -0
- 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-qa.d.mts.map +1 -1
- package/dist/cli/consistency/parse-qa.mjs +18 -4
- package/dist/cli/consistency/parse-qa.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 +11 -10
- 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/coverage-check/user-outcomes.d.mts +7 -2
- package/dist/cli/coverage-check/user-outcomes.d.mts.map +1 -1
- package/dist/cli/coverage-check/user-outcomes.mjs +50 -17
- package/dist/cli/coverage-check/user-outcomes.mjs.map +1 -1
- package/dist/cli/dispatch.d.mts.map +1 -1
- package/dist/cli/dispatch.mjs +30 -0
- package/dist/cli/dispatch.mjs.map +1 -1
- package/dist/cli/gate/gates/verify-approved.d.mts +0 -48
- package/dist/cli/gate/gates/verify-approved.d.mts.map +1 -1
- package/dist/cli/gate/gates/verify-approved.mjs +23 -80
- package/dist/cli/gate/gates/verify-approved.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-server-specs.d.mts +6 -5
- package/dist/cli/install/mcp-server-specs.d.mts.map +1 -1
- package/dist/cli/install/mcp-server-specs.mjs +22 -4
- package/dist/cli/install/mcp-server-specs.mjs.map +1 -1
- package/dist/cli/roadmap/backend-adapter.d.mts +43 -0
- package/dist/cli/roadmap/backend-adapter.d.mts.map +1 -0
- package/dist/cli/roadmap/backend-adapter.mjs +222 -0
- package/dist/cli/roadmap/backend-adapter.mjs.map +1 -0
- package/dist/cli/util/runtime-capabilities.d.mts +7 -0
- package/dist/cli/util/runtime-capabilities.d.mts.map +1 -1
- package/dist/cli/util/runtime-capabilities.mjs +65 -0
- package/dist/cli/util/runtime-capabilities.mjs.map +1 -1
- package/dist/cli/verify-proof/manifest-validator.mjs +13 -0
- package/dist/cli/verify-proof/manifest-validator.mjs.map +1 -1
- package/dist/cli/verify-proof/resolver.d.mts +10 -7
- package/dist/cli/verify-proof/resolver.d.mts.map +1 -1
- package/dist/cli/verify-proof/resolver.mjs +28 -7
- package/dist/cli/verify-proof/resolver.mjs.map +1 -1
- package/dist/cli/verify-proof/sandbox/apply.d.mts +64 -0
- package/dist/cli/verify-proof/sandbox/apply.d.mts.map +1 -0
- package/dist/cli/verify-proof/sandbox/apply.mjs +379 -0
- package/dist/cli/verify-proof/sandbox/apply.mjs.map +1 -0
- package/dist/cli/verify-proof/sandbox/gate-predicate.d.mts +63 -0
- package/dist/cli/verify-proof/sandbox/gate-predicate.d.mts.map +1 -0
- package/dist/cli/verify-proof/sandbox/gate-predicate.mjs +115 -0
- package/dist/cli/verify-proof/sandbox/gate-predicate.mjs.map +1 -0
- package/dist/cli/verify-proof/sandbox/pattern-matcher.d.mts +57 -0
- package/dist/cli/verify-proof/sandbox/pattern-matcher.d.mts.map +1 -0
- package/dist/cli/verify-proof/sandbox/pattern-matcher.mjs +124 -0
- package/dist/cli/verify-proof/sandbox/pattern-matcher.mjs.map +1 -0
- package/dist/cli/verify-proof/sandbox/recipe-diff.d.mts +28 -0
- package/dist/cli/verify-proof/sandbox/recipe-diff.d.mts.map +1 -0
- package/dist/cli/verify-proof/sandbox/recipe-diff.mjs +190 -0
- package/dist/cli/verify-proof/sandbox/recipe-diff.mjs.map +1 -0
- package/dist/cli/verify-proof/sandbox/sandbox-config.d.mts +25 -0
- package/dist/cli/verify-proof/sandbox/sandbox-config.d.mts.map +1 -0
- package/dist/cli/verify-proof/sandbox/sandbox-config.mjs +85 -0
- package/dist/cli/verify-proof/sandbox/sandbox-config.mjs.map +1 -0
- package/dist/cli/verify-proof/sandbox/self-test.d.mts +39 -0
- package/dist/cli/verify-proof/sandbox/self-test.d.mts.map +1 -0
- package/dist/cli/verify-proof/sandbox/self-test.mjs +248 -0
- package/dist/cli/verify-proof/sandbox/self-test.mjs.map +1 -0
- package/dist/plugin/.claude-plugin/plugin.json +2 -1
- package/dist/plugin/agents/apt-planner.md +15 -0
- package/dist/plugin/agents/apt-verifier.md +15 -10
- 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-plan/SKILL.md +23 -0
- package/dist/plugin/skills/apt-pr-review/SKILL.md +5 -4
- package/dist/plugin/skills/apt-run/SKILL.md +1 -1
- package/dist/plugin/skills/apt-setup/SKILL.md +132 -0
- package/dist/plugin/skills/apt-verify/SKILL.md +20 -15
- package/dist/plugin/skills/apt-verify-proof/SKILL.md +146 -11
- package/dist/proof-report.d.ts.map +1 -1
- package/dist/proof-report.js +4 -1
- package/dist/proof-report.js.map +1 -1
- package/dist/types/config.d.ts +42 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/qa-scoring.d.ts +45 -9
- package/dist/types/qa-scoring.d.ts.map +1 -1
- package/dist/types/qa-scoring.js +34 -13
- package/dist/types/qa-scoring.js.map +1 -1
- package/dist/types/state.d.ts +7 -2
- package/dist/types/state.d.ts.map +1 -1
- package/dist/types/task-record.d.ts +10 -2
- package/dist/types/task-record.d.ts.map +1 -1
- package/drivers/mobile/README.md +40 -0
- package/drivers/mobile/driver.mjs +106 -0
- package/drivers/mobile/manifest.json +49 -0
- package/package.json +1 -1
- package/prompts/inbox-clarification.md +11 -0
- package/prompts/inbox-triage.md +20 -0
- package/prompts/qa_orchestrator_agentic.md +18 -17
- package/prompts/qa_reviewer.md +17 -15
- package/skills/apt/SKILL.md +29 -0
- package/skills/apt-catch-up/SKILL.md +79 -0
- package/skills/apt-plan/SKILL.md +23 -0
- package/skills/apt-pr-review/SKILL.md +5 -4
- package/skills/apt-run/SKILL.md +1 -1
- package/skills/apt-setup/SKILL.md +132 -0
- package/skills/apt-verifier.md +7 -4
- package/skills/apt-verify/SKILL.md +20 -15
- package/skills/apt-verify-proof/SKILL.md +146 -11
- package/src/cli/commands/apply-recipe.mjs +105 -0
- package/src/cli/commands/catch-up.mjs +67 -0
- package/src/cli/commands/mobile-prepare.mjs +151 -0
- package/src/cli/commands/pr-review.mjs +32 -11
- package/src/cli/commands/recipe-diff.mjs +81 -0
- package/src/cli/commands/roadmap.mjs +54 -0
- package/src/cli/commands/route.mjs +92 -1
- package/src/cli/commands/verify-sandbox.mjs +231 -0
- package/src/cli/config/share-policy.mjs +1 -0
- package/src/cli/config/upgrade-gitignore.mjs +1 -0
- package/src/cli/consistency/parse-qa.mjs +20 -4
- package/src/cli/consistency/rules/r5-verdict-consistency.mjs +11 -13
- 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/coverage-check/user-outcomes.mjs +52 -17
- package/src/cli/dispatch.mjs +29 -0
- package/src/cli/gate/gates/verify-approved.mjs +22 -81
- 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-server-specs.mjs +24 -4
- package/src/cli/roadmap/backend-adapter.mjs +231 -0
- package/src/cli/util/runtime-capabilities.mjs +67 -0
- package/src/cli/verify-proof/manifest-validator.mjs +15 -0
- package/src/cli/verify-proof/resolver.mjs +27 -7
- package/src/cli/verify-proof/sandbox/apply.mjs +401 -0
- package/src/cli/verify-proof/sandbox/gate-predicate.mjs +126 -0
- package/src/cli/verify-proof/sandbox/pattern-matcher.mjs +127 -0
- package/src/cli/verify-proof/sandbox/recipe-diff.mjs +208 -0
- package/src/cli/verify-proof/sandbox/sandbox-config.mjs +82 -0
- package/src/cli/verify-proof/sandbox/sandbox-schema.json +33 -0
- package/src/cli/verify-proof/sandbox/self-test.mjs +265 -0
- package/templates/config.json +21 -1
- package/templates/proof-verification.md +27 -8
- package/workflows/verify-proof.md +376 -302
|
@@ -7,29 +7,43 @@ export interface QADimensionScore {
|
|
|
7
7
|
score: number;
|
|
8
8
|
rationale: string;
|
|
9
9
|
}
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Threshold constants for QA verdict derivation.
|
|
12
|
+
*
|
|
13
|
+
* v0.9.0 (verify-proof-v2-outcome-walker_27-05-26) — `approved_with_notes`
|
|
14
|
+
* is DELETED. Dimensions are now informational rationale only; the verdict
|
|
15
|
+
* derives from the two-gate envelope (`automation_gate` + `proof_gate`),
|
|
16
|
+
* not per-dimension minimums.
|
|
17
|
+
*/
|
|
11
18
|
export declare const QA_DIMENSION_THRESHOLDS: {
|
|
12
19
|
readonly approved: 7;
|
|
13
|
-
readonly approved_with_notes: 5;
|
|
14
20
|
};
|
|
15
|
-
/**
|
|
21
|
+
/** Closed set of QA verdicts in v0.9.0+. `approved_with_notes` is deleted. */
|
|
22
|
+
export type QAVerdict = 'approved' | 'rejected' | 'needs_human';
|
|
23
|
+
/** The two boolean gates that drive verdict derivation. */
|
|
24
|
+
export type GateStatus = 'pass' | 'fail';
|
|
25
|
+
/** Scored QA signoff — verdict + checks + dimensions + findings */
|
|
16
26
|
export interface ScoredQASignoff {
|
|
17
|
-
status:
|
|
27
|
+
status: QAVerdict;
|
|
18
28
|
timestamp: string;
|
|
19
29
|
iterations: number;
|
|
20
30
|
dimensions: QADimensionScore[];
|
|
31
|
+
gates: {
|
|
32
|
+
automation_gate: GateStatus;
|
|
33
|
+
proof_gate: GateStatus;
|
|
34
|
+
};
|
|
21
35
|
checks: {
|
|
22
36
|
tests: {
|
|
23
|
-
status:
|
|
37
|
+
status: GateStatus;
|
|
24
38
|
count: number;
|
|
25
39
|
failures: string[];
|
|
26
40
|
};
|
|
27
41
|
typecheck: {
|
|
28
|
-
status:
|
|
42
|
+
status: GateStatus;
|
|
29
43
|
errors: string[];
|
|
30
44
|
};
|
|
31
45
|
lint: {
|
|
32
|
-
status:
|
|
46
|
+
status: GateStatus;
|
|
33
47
|
warnings: number;
|
|
34
48
|
};
|
|
35
49
|
};
|
|
@@ -40,6 +54,28 @@ export interface ScoredQASignoff {
|
|
|
40
54
|
}>;
|
|
41
55
|
notes: string;
|
|
42
56
|
}
|
|
43
|
-
/**
|
|
44
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Derive the v0.9.0 two-gate verdict from `{automation_gate, proof_gate}`.
|
|
59
|
+
*
|
|
60
|
+
* The legacy per-dimension `deriveVerdict(scores: QADimensionScore[])` is
|
|
61
|
+
* deleted along with `approved_with_notes` — dimensions are now informational
|
|
62
|
+
* rationale on the report.
|
|
63
|
+
*
|
|
64
|
+
* Rules:
|
|
65
|
+
* - `automation_gate: fail` → `rejected` (regardless of `proof_gate`).
|
|
66
|
+
* - `proof_gate: fail` → `needs_human` (signals UI-surface outcomes
|
|
67
|
+
* without proof) when automation is green; this aligns with the
|
|
68
|
+
* workflow-level rule "any test with needs_human_with_transport rolls
|
|
69
|
+
* up to needs_human" (callers that detect a hard fail without a
|
|
70
|
+
* transport hole should pass `proof_gate: 'fail'`).
|
|
71
|
+
* - Both gates pass → `approved`.
|
|
72
|
+
*
|
|
73
|
+
* Per AC13 (spec.md §3): the workflow's Step 7c rolls a `proof_gate: fail`
|
|
74
|
+
* caused by a UI-surface escape hatch up to `needs_human`; callers driving
|
|
75
|
+
* deriveVerdict from `{automation_gate, proof_gate}` get the same answer.
|
|
76
|
+
*/
|
|
77
|
+
export declare function deriveVerdict(input: {
|
|
78
|
+
automation_gate: GateStatus;
|
|
79
|
+
proof_gate: GateStatus;
|
|
80
|
+
}): QAVerdict;
|
|
45
81
|
//# sourceMappingURL=qa-scoring.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qa-scoring.d.ts","sourceRoot":"","sources":["../../src/types/qa-scoring.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,eAAO,MAAM,aAAa,2EAKhB,CAAA;AACV,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,WAAW,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"qa-scoring.d.ts","sourceRoot":"","sources":["../../src/types/qa-scoring.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,eAAO,MAAM,aAAa,2EAKhB,CAAA;AACV,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,WAAW,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB;;CAE1B,CAAA;AAEV,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,aAAa,CAAA;AAE/D,2DAA2D;AAC3D,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;AAExC,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,SAAS,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,gBAAgB,EAAE,CAAA;IAC9B,KAAK,EAAE;QACN,eAAe,EAAE,UAAU,CAAA;QAC3B,UAAU,EAAE,UAAU,CAAA;KACtB,CAAA;IACD,MAAM,EAAE;QACP,KAAK,EAAE;YAAE,MAAM,EAAE,UAAU,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;SAAE,CAAA;QAChE,SAAS,EAAE;YAAE,MAAM,EAAE,UAAU,CAAC;YAAC,MAAM,EAAE,MAAM,EAAE,CAAA;SAAE,CAAA;QACnD,IAAI,EAAE;YAAE,MAAM,EAAE,UAAU,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAA;KAC9C,CAAA;IACD,MAAM,EAAE,KAAK,CAAC;QACb,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAA;QACzC,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,EAAE,MAAM,CAAA;KACnB,CAAC,CAAA;IACF,KAAK,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACpC,eAAe,EAAE,UAAU,CAAA;IAC3B,UAAU,EAAE,UAAU,CAAA;CACtB,GAAG,SAAS,CAIZ"}
|
package/dist/types/qa-scoring.js
CHANGED
|
@@ -5,21 +5,42 @@ export const QA_DIMENSIONS = [
|
|
|
5
5
|
'code_quality',
|
|
6
6
|
'test_coverage',
|
|
7
7
|
];
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Threshold constants for QA verdict derivation.
|
|
10
|
+
*
|
|
11
|
+
* v0.9.0 (verify-proof-v2-outcome-walker_27-05-26) — `approved_with_notes`
|
|
12
|
+
* is DELETED. Dimensions are now informational rationale only; the verdict
|
|
13
|
+
* derives from the two-gate envelope (`automation_gate` + `proof_gate`),
|
|
14
|
+
* not per-dimension minimums.
|
|
15
|
+
*/
|
|
9
16
|
export const QA_DIMENSION_THRESHOLDS = {
|
|
10
|
-
approved: 7, //
|
|
11
|
-
approved_with_notes: 5, // All dimensions >= 5 = approved-with-notes
|
|
12
|
-
// Any dimension < 5 = rejected
|
|
17
|
+
approved: 7, // Retained as informational; the verdict derivation no longer reads it.
|
|
13
18
|
};
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Derive the v0.9.0 two-gate verdict from `{automation_gate, proof_gate}`.
|
|
21
|
+
*
|
|
22
|
+
* The legacy per-dimension `deriveVerdict(scores: QADimensionScore[])` is
|
|
23
|
+
* deleted along with `approved_with_notes` — dimensions are now informational
|
|
24
|
+
* rationale on the report.
|
|
25
|
+
*
|
|
26
|
+
* Rules:
|
|
27
|
+
* - `automation_gate: fail` → `rejected` (regardless of `proof_gate`).
|
|
28
|
+
* - `proof_gate: fail` → `needs_human` (signals UI-surface outcomes
|
|
29
|
+
* without proof) when automation is green; this aligns with the
|
|
30
|
+
* workflow-level rule "any test with needs_human_with_transport rolls
|
|
31
|
+
* up to needs_human" (callers that detect a hard fail without a
|
|
32
|
+
* transport hole should pass `proof_gate: 'fail'`).
|
|
33
|
+
* - Both gates pass → `approved`.
|
|
34
|
+
*
|
|
35
|
+
* Per AC13 (spec.md §3): the workflow's Step 7c rolls a `proof_gate: fail`
|
|
36
|
+
* caused by a UI-surface escape hatch up to `needs_human`; callers driving
|
|
37
|
+
* deriveVerdict from `{automation_gate, proof_gate}` get the same answer.
|
|
38
|
+
*/
|
|
39
|
+
export function deriveVerdict(input) {
|
|
40
|
+
if (input.automation_gate === 'fail')
|
|
17
41
|
return 'rejected';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (min >= QA_DIMENSION_THRESHOLDS.approved_with_notes)
|
|
22
|
-
return 'approved-with-notes';
|
|
23
|
-
return 'rejected';
|
|
42
|
+
if (input.proof_gate === 'fail')
|
|
43
|
+
return 'needs_human';
|
|
44
|
+
return 'approved';
|
|
24
45
|
}
|
|
25
46
|
//# sourceMappingURL=qa-scoring.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qa-scoring.js","sourceRoot":"","sources":["../../src/types/qa-scoring.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B,cAAc;IACd,aAAa;IACb,cAAc;IACd,eAAe;CACN,CAAA;AAUV
|
|
1
|
+
{"version":3,"file":"qa-scoring.js","sourceRoot":"","sources":["../../src/types/qa-scoring.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B,cAAc;IACd,aAAa;IACb,cAAc;IACd,eAAe;CACN,CAAA;AAUV;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACtC,QAAQ,EAAE,CAAC,EAAE,wEAAwE;CAC5E,CAAA;AA+BV;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,aAAa,CAAC,KAG7B;IACA,IAAI,KAAK,CAAC,eAAe,KAAK,MAAM;QAAE,OAAO,UAAU,CAAA;IACvD,IAAI,KAAK,CAAC,UAAU,KAAK,MAAM;QAAE,OAAO,aAAa,CAAA;IACrD,OAAO,UAAU,CAAA;AAClB,CAAC"}
|
package/dist/types/state.d.ts
CHANGED
|
@@ -24,12 +24,17 @@ export interface ActiveTask {
|
|
|
24
24
|
phase: TaskPhase;
|
|
25
25
|
progress: TaskProgress;
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* A task that has been completed.
|
|
29
|
+
*
|
|
30
|
+
* v0.9.0 — `qa_verdict` is the closed set `{approved, rejected, needs_human}`.
|
|
31
|
+
* The legacy `approved_with_notes` middle band is DELETED (no shim).
|
|
32
|
+
*/
|
|
28
33
|
export interface CompletedTask {
|
|
29
34
|
id: string;
|
|
30
35
|
description: string;
|
|
31
36
|
completed_at: string;
|
|
32
|
-
qa_verdict: 'approved' | '
|
|
37
|
+
qa_verdict: 'approved' | 'rejected' | 'needs_human';
|
|
33
38
|
commits: string[];
|
|
34
39
|
}
|
|
35
40
|
/** A decision recorded during task execution */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/types/state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,wDAAwD;AACxD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAA;AAE/D,sCAAsC;AACtC,MAAM,MAAM,SAAS,GAClB,YAAY,GACZ,UAAU,GACV,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,QAAQ,CAAA;AAEX,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC5B,cAAc,EAAE,MAAM,CAAA;IACtB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,oDAAoD;AACpD,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACvB,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,YAAY,CAAA;CACtB;AAED
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/types/state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,wDAAwD;AACxD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAA;AAE/D,sCAAsC;AACtC,MAAM,MAAM,SAAS,GAClB,YAAY,GACZ,UAAU,GACV,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,QAAQ,CAAA;AAEX,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC5B,cAAc,EAAE,MAAM,CAAA;IACtB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,oDAAoD;AACpD,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACvB,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,YAAY,CAAA;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,UAAU,GAAG,UAAU,GAAG,aAAa,CAAA;IACnD,OAAO,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,gDAAgD;AAChD,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;CACZ;AAED,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,UAAU,GAAG,IAAI,CAAA;IAC9B,eAAe,EAAE,aAAa,EAAE,CAAA;IAChC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACvC,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAA;IAClB,oEAAoE;IACpE,UAAU,CAAC,EAAE;QACZ,MAAM,EAAE,OAAO,CAAA;QACf,wBAAwB,EAAE,MAAM,CAAA;QAChC,YAAY,EAAE,MAAM,CAAA;KACpB,CAAA;CACD"}
|
|
@@ -62,13 +62,21 @@ export interface TaskRecord {
|
|
|
62
62
|
*/
|
|
63
63
|
pr_url?: string;
|
|
64
64
|
}
|
|
65
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Completed task row stored under `state.completed_tasks[]`.
|
|
67
|
+
*
|
|
68
|
+
* v0.9.0 — `qa_verdict` is the closed set
|
|
69
|
+
* `{approved, rejected, needs_human, completed}`. The legacy
|
|
70
|
+
* `approved_with_notes` middle band is DELETED (no shim). `completed`
|
|
71
|
+
* remains as a phase-only marker for tasks that closed without a
|
|
72
|
+
* verify-proof verdict.
|
|
73
|
+
*/
|
|
66
74
|
export interface CompletedTaskRecord {
|
|
67
75
|
id: string;
|
|
68
76
|
description: string;
|
|
69
77
|
scope: Scope;
|
|
70
78
|
completed_at: string;
|
|
71
|
-
qa_verdict: 'approved' | '
|
|
79
|
+
qa_verdict: 'approved' | 'rejected' | 'needs_human' | 'completed';
|
|
72
80
|
commits: string[];
|
|
73
81
|
lifecycle_phase?: LifecyclePhase;
|
|
74
82
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-record.d.ts","sourceRoot":"","sources":["../../src/types/task-record.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAA;AAE/D;iEACiE;AACjE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE;QACL,KAAK,EAAE,KAAK,CAAA;QACZ,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KACvB,CAAA;IACD,EAAE,EAAE;QACH,KAAK,EAAE,KAAK,CAAA;QACZ,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KACvB,CAAA;IACD,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;qEACiE;IACjE,cAAc,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,MAAM,WAAW,YAAY;IAC5B,cAAc,EAAE,MAAM,CAAA;IACtB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACvB,KAAK,EAAE,KAAK,CAAA;IACZ,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,eAAe,EAAE,cAAc,CAAA;IAC/B,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,QAAQ,EAAE,YAAY,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED
|
|
1
|
+
{"version":3,"file":"task-record.d.ts","sourceRoot":"","sources":["../../src/types/task-record.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAA;AAE/D;iEACiE;AACjE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE;QACL,KAAK,EAAE,KAAK,CAAA;QACZ,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KACvB,CAAA;IACD,EAAE,EAAE;QACH,KAAK,EAAE,KAAK,CAAA;QACZ,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KACvB,CAAA;IACD,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;qEACiE;IACjE,cAAc,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,MAAM,WAAW,YAAY;IAC5B,cAAc,EAAE,MAAM,CAAA;IACtB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACvB,KAAK,EAAE,KAAK,CAAA;IACZ,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,eAAe,EAAE,cAAc,CAAA;IAC/B,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,QAAQ,EAAE,YAAY,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,KAAK,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,UAAU,GAAG,UAAU,GAAG,aAAa,GAAG,WAAW,CAAA;IACjE,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,eAAe,CAAC,EAAE,cAAc,CAAA;CAChC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# mobile driver
|
|
2
|
+
|
|
3
|
+
Unified iOS + Android UI-driving verify-proof driver. Wraps the
|
|
4
|
+
[`mobile-mcp`](https://github.com/mobile-next/mobile-mcp) MCP server
|
|
5
|
+
(mobile-next, Apache-2.0) — one backend for both platforms, driven via the
|
|
6
|
+
native accessibility tree with screenshot-coordinate fallback (ADB for
|
|
7
|
+
Android, idb for iOS).
|
|
8
|
+
|
|
9
|
+
- **Targets:** `ios`, `android`, `expo`, `react-native`.
|
|
10
|
+
- **Transport:** `{ mcp_server_id: "mobile-mcp" }` (provisioned as
|
|
11
|
+
`npx -y @mobilenext/mobile-mcp@latest`).
|
|
12
|
+
- **Platform selection:** chosen INSIDE the tool call
|
|
13
|
+
(`mobile_list_available_devices` → device id), NOT at resolver time — that
|
|
14
|
+
is why one driver covers both platforms (decision D-01).
|
|
15
|
+
|
|
16
|
+
## Lifecycle boundary
|
|
17
|
+
|
|
18
|
+
This driver only **drives UI + captures evidence** against a foregrounded,
|
|
19
|
+
JS-ready app. The app lifecycle — build, install, launch, Metro start, and
|
|
20
|
+
the launch-readiness gate — is owned by `apt-tools mobile prepare`
|
|
21
|
+
(decisions D-03/D-04), which runs BEFORE any verb is dispatched.
|
|
22
|
+
|
|
23
|
+
## System prerequisites (validated, not installed)
|
|
24
|
+
|
|
25
|
+
`mobile-mcp` is pure npm, but the underlying device toolchain is NOT:
|
|
26
|
+
|
|
27
|
+
- **iOS:** `idb-companion` (`brew install idb-companion`) + Xcode + a booted
|
|
28
|
+
Simulator.
|
|
29
|
+
- **Android:** Android SDK + `adb` (`$ANDROID_HOME/platform-tools`) + an
|
|
30
|
+
emulator/device.
|
|
31
|
+
|
|
32
|
+
These are validated by the manifest's `preflight[]` via
|
|
33
|
+
`apt-tools driver doctor` (which records `missing_deps` with guidance) — the
|
|
34
|
+
framework never auto-installs them (decision D-09).
|
|
35
|
+
|
|
36
|
+
## Out of scope
|
|
37
|
+
|
|
38
|
+
Real-device runs and Mac Catalyst (separate RFCs). XcodeBuildMCP is an
|
|
39
|
+
optional future escalation for native-Xcode-heavy iOS builds, not a
|
|
40
|
+
dependency of this driver (decision D-02).
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mobile/driver.mjs — bundled unified mobile driver (iOS + Android).
|
|
3
|
+
*
|
|
4
|
+
* Wraps the `mobile-mcp` MCP server (mobile-next/mobile-mcp, Apache-2.0),
|
|
5
|
+
* the single UI-driving backend for BOTH platforms (decision D-01). The
|
|
6
|
+
* platform/device is chosen INSIDE the tool call (mobile_list_available_
|
|
7
|
+
* devices → device id), NOT at resolver time — that is why one driver
|
|
8
|
+
* targets ios/android/expo/react-native.
|
|
9
|
+
*
|
|
10
|
+
* The app lifecycle (build / install / launch / Metro / ready-gate) is
|
|
11
|
+
* owned by `apt-tools mobile prepare`, NOT this driver (D-03/D-04). This
|
|
12
|
+
* driver assumes a foregrounded, JS-ready app and only drives UI + captures
|
|
13
|
+
* evidence.
|
|
14
|
+
*
|
|
15
|
+
* Per ID-01 — the workflow prose NEVER names mcp__mobile-mcp__* tools; the
|
|
16
|
+
* verb→tool mapping lives ONLY here. Transport dispatch happens at the
|
|
17
|
+
* workflow-runner layer (which holds the model's tool surface).
|
|
18
|
+
*
|
|
19
|
+
* IDL verb → mobile-mcp tool mapping:
|
|
20
|
+
* launch → mobile_use_device (select the booted device/simulator)
|
|
21
|
+
* click → mobile_click_on_screen_at_coordinates
|
|
22
|
+
* type → mobile_type_keys
|
|
23
|
+
* key → mobile_press_button
|
|
24
|
+
* swipe → mobile_swipe_on_screen
|
|
25
|
+
* screenshot → mobile_save_screenshot
|
|
26
|
+
* capture_logs → mobile_device_logs
|
|
27
|
+
* assert_visible → mobile_list_elements_on_screen (element present)
|
|
28
|
+
* assert_text → mobile_list_elements_on_screen (text match)
|
|
29
|
+
* teardown → mobile_terminate_app (best-effort)
|
|
30
|
+
*
|
|
31
|
+
* The driver is a thin adapter: it validates input shape via the IDL
|
|
32
|
+
* arg-metadata and returns a VerbResult. The actual transport dispatch
|
|
33
|
+
* happens at the workflow runner layer. For conformance testing we expose
|
|
34
|
+
* the verb signatures as identity stubs returning VerbResult — the SDK
|
|
35
|
+
* conformance kit then validates the shape contract.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { validateVerbArgs } from '../../src/cli/verify-proof/idl/index.mjs'
|
|
39
|
+
|
|
40
|
+
/** Build a success VerbResult. */
|
|
41
|
+
function ok(evidence_paths = []) {
|
|
42
|
+
return { status: 'success', evidence_paths, duration_ms: 0, retry_count: 0 }
|
|
43
|
+
}
|
|
44
|
+
function fail(error) {
|
|
45
|
+
return { status: 'fail', evidence_paths: [], duration_ms: 0, retry_count: 0, error }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Validate args + return a VerbResult shape stub. Real transport invocation
|
|
50
|
+
* happens at the workflow-runner layer (model holds the tool surface —
|
|
51
|
+
* mcp__mobile-mcp__*).
|
|
52
|
+
*
|
|
53
|
+
* @param {string} verb
|
|
54
|
+
* @param {Record<string, unknown>} args
|
|
55
|
+
* @returns {{status: 'success'|'fail'|'skip', evidence_paths: string[], duration_ms: number, retry_count: number, error?: string}}
|
|
56
|
+
*/
|
|
57
|
+
function adaptVerb(verb, args) {
|
|
58
|
+
const check = validateVerbArgs(verb, args)
|
|
59
|
+
if (!check.valid) {
|
|
60
|
+
return fail(`mobile.${verb}: missing required args: ${check.missing.join(', ')}`)
|
|
61
|
+
}
|
|
62
|
+
if (verb === 'screenshot' && typeof args.output_path === 'string') {
|
|
63
|
+
return ok([args.output_path])
|
|
64
|
+
}
|
|
65
|
+
return ok([])
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function launch(args) {
|
|
69
|
+
return adaptVerb('launch', args)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function click(args) {
|
|
73
|
+
return adaptVerb('click', args)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export async function type(args) {
|
|
77
|
+
return adaptVerb('type', args)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function key(args) {
|
|
81
|
+
return adaptVerb('key', args)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function swipe(args) {
|
|
85
|
+
return adaptVerb('swipe', args)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function screenshot(args) {
|
|
89
|
+
return adaptVerb('screenshot', args)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export async function capture_logs(args) {
|
|
93
|
+
return adaptVerb('capture_logs', args)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function assert_visible(args) {
|
|
97
|
+
return adaptVerb('assert_visible', args)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function assert_text(args) {
|
|
101
|
+
return adaptVerb('assert_text', args)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function teardown(args) {
|
|
105
|
+
return adaptVerb('teardown', args)
|
|
106
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"driverId": "mobile",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"targets": ["ios", "android", "expo", "react-native"],
|
|
5
|
+
"capabilities": [
|
|
6
|
+
"launch",
|
|
7
|
+
"click",
|
|
8
|
+
"type",
|
|
9
|
+
"key",
|
|
10
|
+
"swipe",
|
|
11
|
+
"screenshot",
|
|
12
|
+
"capture_logs",
|
|
13
|
+
"assert_visible",
|
|
14
|
+
"assert_text",
|
|
15
|
+
"teardown"
|
|
16
|
+
],
|
|
17
|
+
"evidence_capabilities": ["screenshot", "capture_logs"],
|
|
18
|
+
"frameworkApiRange": "^1.0.0",
|
|
19
|
+
"priority": 80,
|
|
20
|
+
"stability": "ga",
|
|
21
|
+
"trust": {
|
|
22
|
+
"tier": "first_party_signed",
|
|
23
|
+
"publisher": {
|
|
24
|
+
"name": "Aperant",
|
|
25
|
+
"npm_scope": "@aperant",
|
|
26
|
+
"github_org": "Mikalsen-AI",
|
|
27
|
+
"verified": true
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"security": {
|
|
31
|
+
"sandbox_profile": "workspace_write",
|
|
32
|
+
"network": "deny",
|
|
33
|
+
"requires_user_approval": false
|
|
34
|
+
},
|
|
35
|
+
"audit": { "log_invocations": true, "log_manifest_hash": true },
|
|
36
|
+
"preflight": [
|
|
37
|
+
{
|
|
38
|
+
"name": "xcrun (iOS Simulator toolchain)",
|
|
39
|
+
"command": { "binary": "xcrun", "args": ["simctl", "help"] },
|
|
40
|
+
"required": false
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "adb (Android platform-tools)",
|
|
44
|
+
"command": { "binary": "adb", "args": ["--version"] },
|
|
45
|
+
"required": false
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"transport": { "mcp_server_id": "mobile-mcp" }
|
|
49
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aperant/framework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.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": "Mikalsen AI <hello@mikalsen.ai>",
|
|
6
6
|
"type": "module",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Run one read-only clarification turn using Work Record context, prior chat history, and the latest user response.
|
|
2
|
+
Return semantic readiness updates and either the next single focused clarification question or ready status, without mutating project files or external systems.
|
|
3
|
+
|
|
4
|
+
You are the Aperant clarification agent.
|
|
5
|
+
First call readPhaseOutput with phase="triage" to inspect the triage output.
|
|
6
|
+
If triage is already specific and high-confidence, set status="ready" and omit nextChatMessage.
|
|
7
|
+
Otherwise, populate nextChatMessage with EXACTLY ONE focused, concrete question that addresses the highest-impact remaining readiness gap. Do not batch multiple questions into one turn.
|
|
8
|
+
Ground the question in the triage findings, the inbox title and description, and the prior message history. Acknowledge what the user already said when relevant.
|
|
9
|
+
Set nextChatMessage.dimensionKey to the readiness dimension the question targets, and nextChatMessage.cardId to the matching open clarification card when one exists.
|
|
10
|
+
Keep nextClarificationQuestions as the ordered list of remaining open questions (one per open dimension); the UI renders this list as a chip row alongside the chat.
|
|
11
|
+
Use repository tools only when needed to sharpen the question.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Refine one Inbox Work Item into structured triage output.
|
|
2
|
+
Use supplied repository evidence and preserve read-only behavior.
|
|
3
|
+
Return semantic findings, readiness evidence, and clarification prompts without mutating project files or external systems.
|
|
4
|
+
|
|
5
|
+
You are the Aperant triage agent.
|
|
6
|
+
Produce structured JSON only via the provided schema.
|
|
7
|
+
Semantic capability mapping: repository_evidence maps to listFiles and readFile tools.
|
|
8
|
+
Use listFiles and readFile tools to ground claims in repository evidence.
|
|
9
|
+
Return a triage dossier with repo-evidenced facts, inferred assumptions, risks, acceptance criteria, and clarification plan.
|
|
10
|
+
Always include readinessEvaluation with rubricVersion, dimensions, missingDimensions, hardBlockers, and justificationSummary.
|
|
11
|
+
Universal readiness keys: problem_clarity, scope_definition, repo_evidence, risk_identification, acceptance_criteria_quality.
|
|
12
|
+
Bug-specific keys: repro_steps, expected_vs_actual, impact_assessment.
|
|
13
|
+
Feature-specific keys: user_value, solution_shape, dependency_mapping.
|
|
14
|
+
Enhancement-specific keys: current_behavior_baseline, incremental_scope, migration_safety.
|
|
15
|
+
Every readiness dimension requires key, score (0-100), evidence, justification, and optional hardBlocker.
|
|
16
|
+
Only place verified repository findings in repoEvidencedFacts.
|
|
17
|
+
For every inferred assumption, set disposition to requires_hitl_confirmation or accepted_assumption.
|
|
18
|
+
Do not present product commitments as facts unless repository evidence directly supports them.
|
|
19
|
+
Each proposed acceptance criterion must include a verificationMethod and Given/When/Then fields when behavior is being specified.
|
|
20
|
+
Prefer concise summaries and concrete touch points.
|
|
@@ -66,10 +66,10 @@ The reviewer writes `qa_report.md` and updates `implementation_plan.json` with a
|
|
|
66
66
|
|
|
67
67
|
Read the `qa_signoff` from `implementation_plan.json`. The reviewer now writes dimension scores alongside the status.
|
|
68
68
|
|
|
69
|
-
Read the dimension scores:
|
|
70
|
-
- If
|
|
71
|
-
- If
|
|
72
|
-
- If
|
|
69
|
+
Read the gates + dimension scores:
|
|
70
|
+
- If `automation_gate: pass` AND `proof_gate: pass` AND status is "approved" -> Build passes. Write final QA report. Done.
|
|
71
|
+
- If `automation_gate: pass` AND `proof_gate: fail` AND status is "needs_human" -> Transport gap. Write final QA report listing what the human must install (e.g. an MCP server). Done.
|
|
72
|
+
- If `automation_gate: fail` OR critical findings unresolved -> status is "rejected". Spawn fixer (Phase 4).
|
|
73
73
|
- If no scores written -> Reviewer failed to score. Re-spawn with explicit scoring instructions: "You MUST score all 4 dimensions (completeness, correctness, code_quality, test_coverage) on 1-10 before writing a verdict."
|
|
74
74
|
- If no signoff written at all -> Reviewer failed to update the file. Retry with explicit instructions.
|
|
75
75
|
|
|
@@ -100,10 +100,10 @@ When the reviewer rejects, triage based on dimension scores from the qa_signoff,
|
|
|
100
100
|
- Documentation formatting
|
|
101
101
|
- Non-functional improvements
|
|
102
102
|
|
|
103
|
-
**Decision Framework:**
|
|
104
|
-
- If
|
|
105
|
-
- If
|
|
106
|
-
- If
|
|
103
|
+
**Decision Framework (v0.9.0 two-gate envelope):**
|
|
104
|
+
- If `automation_gate: pass` AND `proof_gate: pass` AND no critical issues -> approve the build (write qa_signoff: approved)
|
|
105
|
+
- If `automation_gate: pass` AND `proof_gate: fail` (UI-surface outcome missing driver transport) -> write qa_signoff: needs_human with a `transport_gap` array
|
|
106
|
+
- If `automation_gate: fail` OR critical issues unresolved -> spawn qa_fixer with targeted guidance
|
|
107
107
|
- If the same critical issue appears 3+ times -> escalate to human
|
|
108
108
|
|
|
109
109
|
### Phase 5: Fix Cycle
|
|
@@ -137,19 +137,20 @@ Track iteration count. Your goal is to converge quickly:
|
|
|
137
137
|
|
|
138
138
|
## QUALITY GATES
|
|
139
139
|
|
|
140
|
-
### Approval Criteria (
|
|
140
|
+
### Approval Criteria (v0.9.0 two-gate envelope)
|
|
141
141
|
Approve when ALL of these are true:
|
|
142
|
-
-
|
|
142
|
+
- `automation_gate: pass` (tests + typecheck + lint all green)
|
|
143
|
+
- `proof_gate: pass` (every outcome has surface-appropriate evidence)
|
|
143
144
|
- No critical issues in the issues array
|
|
144
|
-
-
|
|
145
|
+
- Dimensions land >= 7 as informational rationale (does NOT drive the verdict)
|
|
145
146
|
|
|
146
|
-
###
|
|
147
|
-
- **approved**:
|
|
148
|
-
- **
|
|
149
|
-
- **rejected**:
|
|
147
|
+
### Verdict Closed Set
|
|
148
|
+
- **approved**: `automation_gate: pass` AND `proof_gate: pass` AND no critical issues
|
|
149
|
+
- **needs_human**: `automation_gate: pass` AND `proof_gate: fail` (transport gap)
|
|
150
|
+
- **rejected**: `automation_gate: fail` OR critical issues unresolved
|
|
150
151
|
|
|
151
|
-
### Acceptable Imperfections (
|
|
152
|
-
These
|
|
152
|
+
### Acceptable Imperfections (cited in `findings.notes` on an `approved` verdict)
|
|
153
|
+
These do NOT block approval and ride along as notes:
|
|
153
154
|
- Missing optional features (if spec marks them as optional)
|
|
154
155
|
- Code style deviations (if functionality is correct)
|
|
155
156
|
- Missing edge case handling for unlikely scenarios
|
package/prompts/qa_reviewer.md
CHANGED
|
@@ -37,13 +37,15 @@ You MUST score 4 dimensions on a 1-10 scale. The verdict is DERIVED from scores
|
|
|
37
37
|
**3-4 (Poor):** Significant problems. Multiple issues.
|
|
38
38
|
**1-2 (Failed):** Fundamentally broken or missing.
|
|
39
39
|
|
|
40
|
-
### Verdict Derivation (NOT your choice -- derived from
|
|
40
|
+
### Verdict Derivation (v0.9.0 two-gate envelope; NOT your choice -- derived from gates)
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
- **approved-with-notes**: ALL dimensions >= 5 AND no critical issues
|
|
44
|
-
- **rejected**: ANY dimension < 5 OR critical issues found
|
|
42
|
+
Verdict is the closed set `{approved, rejected, needs_human}`. It derives from the two-gate envelope (`automation_gate` AND `proof_gate`) per `/apt:verify-proof`. Dimensions are informational rationale only.
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
- **approved**: `automation_gate: pass` AND `proof_gate: pass` AND no critical findings.
|
|
45
|
+
- **needs_human**: `automation_gate: pass` AND `proof_gate: fail` (typically: UI-surface outcome with no driver transport — see verify-proof workflow).
|
|
46
|
+
- **rejected**: `automation_gate: fail` OR critical findings unresolved.
|
|
47
|
+
|
|
48
|
+
You MUST write scores BEFORE writing the verdict. The verdict follows from the gates, with dimensions as rationale.
|
|
47
49
|
|
|
48
50
|
---
|
|
49
51
|
|
|
@@ -440,7 +442,7 @@ Create a comprehensive QA report with dimension scores:
|
|
|
440
442
|
| test_coverage | {N}/10 | {evidence} |
|
|
441
443
|
|
|
442
444
|
**Minimum score:** {min}
|
|
443
|
-
**Derived verdict:** {approved|
|
|
445
|
+
**Derived verdict:** {approved|rejected|needs_human}
|
|
444
446
|
|
|
445
447
|
## Summary
|
|
446
448
|
|
|
@@ -514,7 +516,7 @@ For each critical/major issue, describe what the Coder Agent should do:
|
|
|
514
516
|
|
|
515
517
|
**Next Steps**:
|
|
516
518
|
- [If approved: Ready for merge]
|
|
517
|
-
- [If
|
|
519
|
+
- [If needs_human: Install the missing driver transport (e.g. MCP server) and re-run /apt:verify-proof]
|
|
518
520
|
- [If rejected: List of fixes needed, then re-run QA]
|
|
519
521
|
```
|
|
520
522
|
|
|
@@ -566,17 +568,17 @@ EOF
|
|
|
566
568
|
# Only commit actual code changes to the project
|
|
567
569
|
```
|
|
568
570
|
|
|
569
|
-
### If
|
|
571
|
+
### If NEEDS_HUMAN (transport gap):
|
|
570
572
|
|
|
571
|
-
Same as approved, but with status "
|
|
573
|
+
Same as approved, but with status `"needs_human"` and a `transport_gap` array describing what the human must install (e.g. an MCP server, a binary):
|
|
572
574
|
|
|
573
575
|
```json
|
|
574
576
|
{
|
|
575
577
|
"qa_signoff": {
|
|
576
|
-
"status": "
|
|
577
|
-
"
|
|
578
|
-
"
|
|
579
|
-
"
|
|
578
|
+
"status": "needs_human",
|
|
579
|
+
"transport_gap": [
|
|
580
|
+
"Missing MCP server: puppeteer (drivers/browser/manifest.json :: transport.mcp_server_id)",
|
|
581
|
+
"After install, re-run /apt:verify-proof"
|
|
580
582
|
],
|
|
581
583
|
"dimension_scores": {
|
|
582
584
|
"completeness": "[N]",
|
|
@@ -762,11 +764,11 @@ QA will automatically re-run after fixes.
|
|
|
762
764
|
|
|
763
765
|
The QA -> Fix -> QA loop continues until:
|
|
764
766
|
|
|
765
|
-
1.
|
|
767
|
+
1. **`automation_gate: pass`** (lint + typecheck + tests all green) AND **`proof_gate: pass`** (every outcome has surface-appropriate evidence)
|
|
766
768
|
2. **No critical issues remain**
|
|
767
769
|
3. **All tests pass**
|
|
768
770
|
4. **No regressions**
|
|
769
|
-
5. **QA derives approved
|
|
771
|
+
5. **QA derives `approved`** (the only ship-eligible verdict; `needs_human` requires installing the missing transport, `rejected` requires code fixes)
|
|
770
772
|
|
|
771
773
|
Maximum iterations: 5 (configurable)
|
|
772
774
|
|
package/skills/apt/SKILL.md
CHANGED
|
@@ -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 |
|