@aperant/framework 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +226 -29
- 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/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/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/validate-evidence.d.mts +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/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/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/design/frontmatter-schema.d.mts +8 -8
- package/dist/cli/dispatch.d.mts.map +1 -1
- package/dist/cli/dispatch.mjs +28 -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/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/personas/sidecar.d.mts +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/roadmap/lifecycle.d.mts +1 -1
- package/dist/cli/roadmap/rollup.d.mts +2 -2
- 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 +1 -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 +2 -2
- package/dist/plugin/skills/apt-plan/SKILL.md +23 -0
- package/dist/plugin/skills/apt-run/SKILL.md +1 -1
- package/dist/plugin/skills/apt-setup/SKILL.md +56 -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 +138 -138
- package/prompts/inbox-clarification.md +17 -0
- package/prompts/inbox-triage.md +21 -0
- package/prompts/qa_orchestrator_agentic.md +18 -17
- package/prompts/qa_reviewer.md +17 -15
- package/skills/apt/SKILL.md +2 -2
- package/skills/apt-plan/SKILL.md +23 -0
- package/skills/apt-run/SKILL.md +1 -1
- package/skills/apt-setup/SKILL.md +56 -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/mobile-prepare.mjs +151 -0
- package/src/cli/commands/recipe-diff.mjs +81 -0
- package/src/cli/commands/roadmap.mjs +54 -0
- package/src/cli/commands/verify-sandbox.mjs +231 -0
- package/src/cli/consistency/parse-qa.mjs +20 -4
- package/src/cli/consistency/rules/r5-verdict-consistency.mjs +11 -13
- package/src/cli/coverage-check/user-outcomes.mjs +52 -17
- package/src/cli/dispatch.mjs +27 -0
- package/src/cli/gate/gates/verify-approved.mjs +22 -81
- 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 +10 -1
- package/templates/proof-verification.md +27 -8
- package/workflows/verify-proof.md +376 -302
package/bin/apt-proof-video.mjs
CHANGED
|
@@ -646,13 +646,16 @@ function renderMarkdown(md) {
|
|
|
646
646
|
}
|
|
647
647
|
|
|
648
648
|
function statusBadge(status) {
|
|
649
|
+
// v0.9.0 — verdict enum is {approved, rejected, needs_human}.
|
|
650
|
+
// `approved-with-notes` is DELETED (no shim). `needs_human` is amber.
|
|
649
651
|
const colors = {
|
|
650
652
|
pass: '#22c55e',
|
|
651
653
|
approved: '#22c55e',
|
|
652
654
|
fail: '#ef4444',
|
|
653
655
|
rejected: '#ef4444',
|
|
654
656
|
partial: '#f59e0b',
|
|
655
|
-
|
|
657
|
+
needs_human: '#f59e0b',
|
|
658
|
+
needs_human_with_transport: '#f59e0b',
|
|
656
659
|
skip: '#6b7280',
|
|
657
660
|
error: '#ef4444',
|
|
658
661
|
}
|
|
@@ -810,7 +813,7 @@ function renderVideoCard(filename, mimeType, analysisData, index) {
|
|
|
810
813
|
</div>`
|
|
811
814
|
}
|
|
812
815
|
|
|
813
|
-
function generateReportHtml(opts) {
|
|
816
|
+
export function generateReportHtml(opts) {
|
|
814
817
|
const {
|
|
815
818
|
title,
|
|
816
819
|
runDate,
|
|
@@ -950,29 +953,41 @@ function generateReportHtml(opts) {
|
|
|
950
953
|
</div>`
|
|
951
954
|
}
|
|
952
955
|
|
|
953
|
-
|
|
954
|
-
|
|
956
|
+
// v0.9.0 — outcome-rooted rendering. One card per outcome with
|
|
957
|
+
// `data-outcome-id` + `data-surface` attributes on the root <div>
|
|
958
|
+
// (load-bearing for AC8). Parent prose + indented inferred children
|
|
959
|
+
// + per-child evidence rendered inside.
|
|
960
|
+
const outcomeResultColors = {
|
|
961
|
+
pass: '#22c55e',
|
|
962
|
+
fail: '#ef4444',
|
|
963
|
+
blocked: '#f59e0b',
|
|
964
|
+
partial: '#f59e0b',
|
|
965
|
+
needs_human_with_transport: '#f59e0b',
|
|
966
|
+
}
|
|
967
|
+
const outcomesSource = Array.isArray(v?.outcomes) && v.outcomes.length > 0 ? v.outcomes : []
|
|
968
|
+
const outcomesHtml =
|
|
969
|
+
outcomesSource.length > 0
|
|
955
970
|
? `<div class="section">
|
|
956
|
-
<h2>
|
|
957
|
-
${
|
|
958
|
-
.map((
|
|
959
|
-
const
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
}
|
|
965
|
-
const fColor = featureResultColors[f.result] ?? '#6b7280'
|
|
966
|
-
const passCount = f.tests.filter((t) => t.result === 'pass').length
|
|
967
|
-
const totalCount = f.tests.length
|
|
968
|
-
return `<div class="card" style="border-left:3px solid ${fColor};">
|
|
971
|
+
<h2>Outcome Verification</h2>
|
|
972
|
+
${outcomesSource
|
|
973
|
+
.map((o) => {
|
|
974
|
+
const fColor = outcomeResultColors[o.result] ?? '#6b7280'
|
|
975
|
+
const passCount = o.tests.filter((t) => t.result === 'pass').length
|
|
976
|
+
const totalCount = o.tests.length
|
|
977
|
+
const heading = o.prose ? `${o.outcome_id}: ${o.prose}` : (o.outcome_id ?? '')
|
|
978
|
+
return `<div class="card" data-outcome-id="${escapeHtml(o.outcome_id ?? '')}" data-surface="${escapeHtml(o.surface ?? '')}" style="border-left:3px solid ${fColor};">
|
|
969
979
|
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px;">
|
|
970
|
-
<h3 style="font-size:15px;color:#f1f5f9;margin:0;">${escapeHtml(
|
|
971
|
-
${
|
|
980
|
+
<h3 style="font-size:15px;color:#f1f5f9;margin:0;">${escapeHtml(heading)}</h3>
|
|
981
|
+
${o.surface ? `<span style="font-size:11px;color:#0B0B0F;background:#D6D876;padding:2px 8px;border-radius:8px;font-weight:600;">${escapeHtml(o.surface)}</span>` : ''}
|
|
982
|
+
${statusBadge(o.result ?? 'pending')}
|
|
972
983
|
<span style="font-size:12px;color:#64748b;margin-left:auto;">${passCount}/${totalCount} tests</span>
|
|
973
984
|
</div>
|
|
974
|
-
${
|
|
975
|
-
|
|
985
|
+
${
|
|
986
|
+
o.inferred && o.inferred.length > 0
|
|
987
|
+
? `<details style="margin-bottom:8px;"><summary style="font-size:12px;color:#94a3b8;cursor:pointer;">Inferred sub-checks (${o.inferred.length})</summary><ul style="margin:6px 0 0 20px;font-size:12px;color:#cbd5e1;list-style:disc;">${o.inferred.map((s) => `<li style="margin:2px 0;">${escapeHtml(s)}</li>`).join('')}</ul></details>`
|
|
988
|
+
: ''
|
|
989
|
+
}
|
|
990
|
+
${o.tests.map((t) => renderTestRow(t, o.outcome_id)).join('')}
|
|
976
991
|
</div>`
|
|
977
992
|
})
|
|
978
993
|
.join('')}
|
|
@@ -1207,9 +1222,17 @@ document.addEventListener('keydown', function(e) { if (e.key === 'Escape') close
|
|
|
1207
1222
|
<h1>${escapeHtml(title)}</h1>
|
|
1208
1223
|
<div class="meta">Generated: ${escapeHtml(runDate)}</div>
|
|
1209
1224
|
<div class="hero-status">${statusBadge(overallVerdict)}</div>
|
|
1225
|
+
${
|
|
1226
|
+
v?.gates
|
|
1227
|
+
? `<div style="display:flex;justify-content:center;gap:12px;margin-top:8px;">
|
|
1228
|
+
<span style="font-size:11px;color:#94a3b8;">automation_gate:</span>${statusBadge(v.gates.automation_gate ?? 'pending')}
|
|
1229
|
+
<span style="font-size:11px;color:#94a3b8;">proof_gate:</span>${statusBadge(v.gates.proof_gate ?? 'pending')}
|
|
1230
|
+
</div>`
|
|
1231
|
+
: ''
|
|
1232
|
+
}
|
|
1210
1233
|
<div style="margin-top:12px;">
|
|
1211
1234
|
<div style="display:flex;justify-content:center;gap:32px;">
|
|
1212
|
-
<div class="stat"><div class="stat-value">${v?.features?.length ?? screenshots.length}</div><div class="stat-label"
|
|
1235
|
+
<div class="stat"><div class="stat-value">${v?.outcomes?.length ?? v?.features?.length ?? screenshots.length}</div><div class="stat-label">${v?.outcomes?.length ? 'Outcomes' : 'Features'}</div></div>
|
|
1213
1236
|
<div class="stat"><div class="stat-value">${passedTests}</div><div class="stat-label">Passed</div></div>
|
|
1214
1237
|
<div class="stat"><div class="stat-value">${failedTests}</div><div class="stat-label">Failed</div></div>
|
|
1215
1238
|
<div class="stat"><div class="stat-value">${blockedTests}</div><div class="stat-label">Blocked</div></div>
|
|
@@ -1224,7 +1247,7 @@ ${summaryHtml}
|
|
|
1224
1247
|
${automatedChecksHtml}
|
|
1225
1248
|
${coverageHtml}
|
|
1226
1249
|
${dimensionsHtml}
|
|
1227
|
-
${
|
|
1250
|
+
${outcomesHtml}
|
|
1228
1251
|
${gapsHtml}
|
|
1229
1252
|
${skippedHtml}
|
|
1230
1253
|
${videosHtml}
|
|
@@ -1280,10 +1303,96 @@ function loadVerificationData(proofDir) {
|
|
|
1280
1303
|
return null
|
|
1281
1304
|
}
|
|
1282
1305
|
|
|
1306
|
+
/**
|
|
1307
|
+
* Closed-set validator for `automated_checks.{tests,typecheck,lint}.status`.
|
|
1308
|
+
*
|
|
1309
|
+
* v0.9.0 (verify-proof-v2-outcome-walker_27-05-26) — `status` MUST be in
|
|
1310
|
+
* `{pass, fail}`. Anything else (e.g. the legacy "enforced_at_commit"
|
|
1311
|
+
* dodge string) is coerced to `'fail'` so downstream gate derivation
|
|
1312
|
+
* surfaces the issue. Returns the canonical lowercase value.
|
|
1313
|
+
*
|
|
1314
|
+
* Exported for testing.
|
|
1315
|
+
*/
|
|
1316
|
+
export function normalizeAutomatedCheckStatus(status) {
|
|
1317
|
+
if (status === 'pass' || status === 'fail') return status
|
|
1318
|
+
return 'fail'
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
/**
|
|
1322
|
+
* Closed set of UI surfaces (electron, web, electron+web). Used by
|
|
1323
|
+
* `deriveProofGate` to detect the fail-closed branch: a UI-surface test
|
|
1324
|
+
* carrying `evidence: "file-evidence: ..."` is REJECTED as proof and
|
|
1325
|
+
* its effective result is forced to `needs_human_with_transport`.
|
|
1326
|
+
*/
|
|
1327
|
+
const UI_SURFACES = new Set(['electron', 'web', 'electron+web'])
|
|
1328
|
+
|
|
1329
|
+
/**
|
|
1330
|
+
* Compute the effective `result` for a single test entry per AC9.
|
|
1331
|
+
*
|
|
1332
|
+
* - If `surface` is a UI surface AND `evidence` matches `^file-evidence:`,
|
|
1333
|
+
* the effective result is `needs_human_with_transport` regardless of
|
|
1334
|
+
* the written `result`.
|
|
1335
|
+
* - Otherwise, the written `result` is honored as-is.
|
|
1336
|
+
*
|
|
1337
|
+
* Exported for testing.
|
|
1338
|
+
*/
|
|
1339
|
+
export function effectiveTestResult(test) {
|
|
1340
|
+
if (!test || typeof test !== 'object') return 'pending'
|
|
1341
|
+
const surface = typeof test.surface === 'string' ? test.surface : ''
|
|
1342
|
+
const evidence = typeof test.evidence === 'string' ? test.evidence : ''
|
|
1343
|
+
if (UI_SURFACES.has(surface) && /^file-evidence:/i.test(evidence)) {
|
|
1344
|
+
return 'needs_human_with_transport'
|
|
1345
|
+
}
|
|
1346
|
+
return test.result ?? 'pending'
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
/**
|
|
1350
|
+
* Derive `proof_gate` (`pass | fail`) from the per-test evidence story.
|
|
1351
|
+
*
|
|
1352
|
+
* v0.9.0 — `proof_gate = fail` iff ANY test's effective result is `fail`.
|
|
1353
|
+
* A `needs_human_with_transport` result does NOT fail the proof_gate on
|
|
1354
|
+
* its own — it bubbles up to the overall verdict as `needs_human` via
|
|
1355
|
+
* `deriveVerdict`. Missing surface evidence on a UI outcome (caught by
|
|
1356
|
+
* `effectiveTestResult`) becomes `needs_human_with_transport`, not `fail`.
|
|
1357
|
+
*
|
|
1358
|
+
* Exported for testing.
|
|
1359
|
+
*/
|
|
1360
|
+
export function deriveProofGate(verification) {
|
|
1361
|
+
const tests = Array.isArray(verification?.tests) ? verification.tests : []
|
|
1362
|
+
if (tests.length === 0) return 'fail'
|
|
1363
|
+
for (const t of tests) {
|
|
1364
|
+
if (effectiveTestResult(t) === 'fail') return 'fail'
|
|
1365
|
+
}
|
|
1366
|
+
return 'pass'
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
/**
|
|
1370
|
+
* Derive `automation_gate` (`pass | fail`) from the three automated checks.
|
|
1371
|
+
*
|
|
1372
|
+
* v0.9.0 — `automation_gate = pass` iff ALL THREE of `tests`, `typecheck`,
|
|
1373
|
+
* `lint` are `pass`. Missing checks count as `fail`. Per-check status is
|
|
1374
|
+
* normalized via `normalizeAutomatedCheckStatus` first so the legacy
|
|
1375
|
+
* `enforced_at_commit` string surfaces as `fail` rather than slipping
|
|
1376
|
+
* through.
|
|
1377
|
+
*
|
|
1378
|
+
* Exported for testing.
|
|
1379
|
+
*/
|
|
1380
|
+
export function deriveAutomationGate(automatedChecks) {
|
|
1381
|
+
if (!automatedChecks || typeof automatedChecks !== 'object') return 'fail'
|
|
1382
|
+
const statuses = ['tests', 'typecheck', 'lint'].map((key) => {
|
|
1383
|
+
const entry = automatedChecks[key]
|
|
1384
|
+
if (!entry || typeof entry !== 'object') return 'fail'
|
|
1385
|
+
return normalizeAutomatedCheckStatus(entry.status)
|
|
1386
|
+
})
|
|
1387
|
+
return statuses.every((s) => s === 'pass') ? 'pass' : 'fail'
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1283
1390
|
/**
|
|
1284
1391
|
* Map verification.json schema to the internal shape used by generateReportHtml().
|
|
1392
|
+
*
|
|
1393
|
+
* Exported for testing (verify-proof-renderer-outcome-grouping.test.ts).
|
|
1285
1394
|
*/
|
|
1286
|
-
function mapVerificationJson(json) {
|
|
1395
|
+
export function mapVerificationJson(json) {
|
|
1287
1396
|
const meta = json.meta ?? {}
|
|
1288
1397
|
const checks = json.automated_checks ?? {}
|
|
1289
1398
|
const tests = json.tests ?? []
|
|
@@ -1292,39 +1401,73 @@ function mapVerificationJson(json) {
|
|
|
1292
1401
|
const skipped = json.skipped ?? []
|
|
1293
1402
|
const coverage = json.coverage ?? null
|
|
1294
1403
|
|
|
1295
|
-
// Map automated checks
|
|
1404
|
+
// Map automated checks. v0.9.0 (verify-proof-v2-outcome-walker_27-05-26)
|
|
1405
|
+
// — `status` MUST be in the closed set {pass, fail}. The legacy
|
|
1406
|
+
// `enforced_at_commit` dodge string is no longer valid; if the input
|
|
1407
|
+
// carries it (or any other non-{pass,fail} value), the per-check status
|
|
1408
|
+
// becomes `fail` so the proof-gate derivation surfaces the issue.
|
|
1296
1409
|
const automatedChecks = {
|
|
1297
1410
|
tests: checks.tests
|
|
1298
1411
|
? {
|
|
1299
|
-
status: checks.tests.status,
|
|
1412
|
+
status: normalizeAutomatedCheckStatus(checks.tests.status),
|
|
1300
1413
|
output: checks.tests.output ?? '',
|
|
1301
1414
|
count: checks.tests.count,
|
|
1302
1415
|
}
|
|
1303
1416
|
: null,
|
|
1304
1417
|
typecheck: checks.typecheck
|
|
1305
|
-
? {
|
|
1418
|
+
? {
|
|
1419
|
+
status: normalizeAutomatedCheckStatus(checks.typecheck.status),
|
|
1420
|
+
output: checks.typecheck.output ?? '',
|
|
1421
|
+
}
|
|
1306
1422
|
: null,
|
|
1307
|
-
lint: checks.lint
|
|
1423
|
+
lint: checks.lint
|
|
1424
|
+
? {
|
|
1425
|
+
status: normalizeAutomatedCheckStatus(checks.lint.status),
|
|
1426
|
+
output: checks.lint.output ?? '',
|
|
1427
|
+
}
|
|
1428
|
+
: null,
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
// v0.9.0 (verify-proof-v2-outcome-walker_27-05-26) — group tests by
|
|
1432
|
+
// `outcome_id` instead of the legacy `registry_id.split('-')[0]` prefix.
|
|
1433
|
+
// `meta.outcomes[]` (when present) provides the parent prose + inferred
|
|
1434
|
+
// children for each card. Per-test mapping preserves `outcome_id`,
|
|
1435
|
+
// `surface`, and `transport` so the renderer can render them.
|
|
1436
|
+
const metaOutcomes = Array.isArray(meta.outcomes) ? meta.outcomes : []
|
|
1437
|
+
const outcomeMeta = new Map()
|
|
1438
|
+
for (const o of metaOutcomes) {
|
|
1439
|
+
if (o && typeof o === 'object' && typeof o.id === 'string') {
|
|
1440
|
+
outcomeMeta.set(o.id, o)
|
|
1441
|
+
}
|
|
1308
1442
|
}
|
|
1309
1443
|
|
|
1310
|
-
|
|
1311
|
-
const featureGroups = new Map()
|
|
1444
|
+
const outcomeGroups = new Map()
|
|
1312
1445
|
for (const t of tests) {
|
|
1313
|
-
const groupKey = t.
|
|
1314
|
-
if (!
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1446
|
+
const groupKey = t.outcome_id ?? 'unassigned'
|
|
1447
|
+
if (!outcomeGroups.has(groupKey)) {
|
|
1448
|
+
const m = outcomeMeta.get(groupKey)
|
|
1449
|
+
outcomeGroups.set(groupKey, {
|
|
1450
|
+
outcome_id: groupKey,
|
|
1451
|
+
surface: m?.surface ?? t.surface ?? '',
|
|
1452
|
+
prose: typeof m?.text === 'string' ? m.text : '',
|
|
1453
|
+
inferred: Array.isArray(m?.inferred) ? m.inferred.slice() : [],
|
|
1320
1454
|
result: '',
|
|
1321
1455
|
tests: [],
|
|
1322
1456
|
})
|
|
1323
1457
|
}
|
|
1324
|
-
|
|
1458
|
+
const group = outcomeGroups.get(groupKey)
|
|
1459
|
+
// First test on the group establishes the surface if meta didn't.
|
|
1460
|
+
if (!group.surface && typeof t.surface === 'string') {
|
|
1461
|
+
group.surface = t.surface
|
|
1462
|
+
}
|
|
1463
|
+
group.tests.push({
|
|
1325
1464
|
name: t.name ?? t.id,
|
|
1326
1465
|
id: t.id,
|
|
1327
1466
|
registry_id: t.registry_id,
|
|
1467
|
+
outcome_id: t.outcome_id ?? null,
|
|
1468
|
+
surface: t.surface ?? null,
|
|
1469
|
+
transport: t.transport ?? null,
|
|
1470
|
+
inferred_index: typeof t.inferred_index === 'number' ? t.inferred_index : null,
|
|
1328
1471
|
precondition: t.precondition ?? '',
|
|
1329
1472
|
action: t.action ?? '',
|
|
1330
1473
|
expected: t.expected ?? '',
|
|
@@ -1337,19 +1480,31 @@ function mapVerificationJson(json) {
|
|
|
1337
1480
|
})
|
|
1338
1481
|
}
|
|
1339
1482
|
|
|
1340
|
-
// Derive
|
|
1341
|
-
const
|
|
1342
|
-
for (const [,
|
|
1343
|
-
const results =
|
|
1344
|
-
if (results.
|
|
1345
|
-
else if (results.some((r) => r === '
|
|
1346
|
-
|
|
1347
|
-
else
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1483
|
+
// Derive per-outcome result roll-up.
|
|
1484
|
+
const outcomes = []
|
|
1485
|
+
for (const [, o] of outcomeGroups) {
|
|
1486
|
+
const results = o.tests.map((t) => t.result)
|
|
1487
|
+
if (results.some((r) => r === 'fail')) o.result = 'fail'
|
|
1488
|
+
else if (results.some((r) => r === 'needs_human_with_transport'))
|
|
1489
|
+
o.result = 'needs_human_with_transport'
|
|
1490
|
+
else if (results.every((r) => r === 'pass')) o.result = 'pass'
|
|
1491
|
+
else if (results.some((r) => r === 'blocked')) o.result = 'partial'
|
|
1492
|
+
else o.result = 'partial'
|
|
1493
|
+
outcomes.push(o)
|
|
1351
1494
|
}
|
|
1352
1495
|
|
|
1496
|
+
// Legacy `features` array — kept as a deprecated alias for one release
|
|
1497
|
+
// per CHANGELOG. Same payload, but keyed `name`/`id` for the legacy
|
|
1498
|
+
// HTML renderer until ST8's rewrite lands.
|
|
1499
|
+
const features = outcomes.map((o) => ({
|
|
1500
|
+
name: o.outcome_id,
|
|
1501
|
+
id: o.outcome_id,
|
|
1502
|
+
route: '',
|
|
1503
|
+
mcp: '',
|
|
1504
|
+
result: o.result,
|
|
1505
|
+
tests: o.tests,
|
|
1506
|
+
}))
|
|
1507
|
+
|
|
1353
1508
|
// Map dimensions
|
|
1354
1509
|
const dimensions = []
|
|
1355
1510
|
for (const [key, val] of Object.entries(dims)) {
|
|
@@ -1373,6 +1528,22 @@ function mapVerificationJson(json) {
|
|
|
1373
1528
|
fix_plan: g.fix_plan ?? null,
|
|
1374
1529
|
}))
|
|
1375
1530
|
|
|
1531
|
+
// v0.9.0 — propagate the two-gate envelope to the renderer. Also
|
|
1532
|
+
// derive automation_gate from automated_checks as a fallback when the
|
|
1533
|
+
// input doesn't carry it explicitly (forward-compat for older
|
|
1534
|
+
// verification.json that pre-dates the schema extension).
|
|
1535
|
+
const gatesInput = json.gates && typeof json.gates === 'object' ? json.gates : {}
|
|
1536
|
+
const gates = {
|
|
1537
|
+
automation_gate:
|
|
1538
|
+
gatesInput.automation_gate === 'pass' || gatesInput.automation_gate === 'fail'
|
|
1539
|
+
? gatesInput.automation_gate
|
|
1540
|
+
: deriveAutomationGate(automatedChecks),
|
|
1541
|
+
proof_gate:
|
|
1542
|
+
gatesInput.proof_gate === 'pass' || gatesInput.proof_gate === 'fail'
|
|
1543
|
+
? gatesInput.proof_gate
|
|
1544
|
+
: deriveProofGate({ tests }),
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1376
1547
|
return {
|
|
1377
1548
|
frontmatter: {
|
|
1378
1549
|
run_id: meta.run_id,
|
|
@@ -1387,6 +1558,8 @@ function mapVerificationJson(json) {
|
|
|
1387
1558
|
verdictText: meta.verdict ?? '',
|
|
1388
1559
|
},
|
|
1389
1560
|
automatedChecks,
|
|
1561
|
+
gates,
|
|
1562
|
+
outcomes,
|
|
1390
1563
|
features,
|
|
1391
1564
|
dimensions,
|
|
1392
1565
|
gaps: mappedGaps,
|
|
@@ -1876,6 +2049,9 @@ async function cmdReport(args) {
|
|
|
1876
2049
|
}
|
|
1877
2050
|
}
|
|
1878
2051
|
|
|
2052
|
+
// v0.9.0 — emit `outcomesCount` (the new field); `featuresCount` is
|
|
2053
|
+
// retained for one release as a deprecated sentinel (always `0`) so
|
|
2054
|
+
// downstream consumers don't crash on missing key. See CHANGELOG.
|
|
1879
2055
|
output({
|
|
1880
2056
|
status: 'ok',
|
|
1881
2057
|
report: {
|
|
@@ -1884,7 +2060,8 @@ async function cmdReport(args) {
|
|
|
1884
2060
|
screenshotCount: scanned.images.length,
|
|
1885
2061
|
videoCount: scanned.videos.length,
|
|
1886
2062
|
verdictCount: verdicts.length,
|
|
1887
|
-
|
|
2063
|
+
outcomesCount: verification?.outcomes?.length ?? 0,
|
|
2064
|
+
featuresCount: 0,
|
|
1888
2065
|
gapsCount: verification?.gaps?.length ?? 0,
|
|
1889
2066
|
mode: isArchive ? 'archive' : 'relative',
|
|
1890
2067
|
title,
|
|
@@ -2044,35 +2221,38 @@ All output is JSON to stdout. Progress goes to stderr.`
|
|
|
2044
2221
|
}
|
|
2045
2222
|
|
|
2046
2223
|
// ---------------------------------------------------------------------------
|
|
2047
|
-
// Dispatch
|
|
2224
|
+
// Dispatch (only runs when invoked as the CLI entry point, not when imported)
|
|
2048
2225
|
// ---------------------------------------------------------------------------
|
|
2049
2226
|
|
|
2050
|
-
const
|
|
2051
|
-
|
|
2227
|
+
const isCliEntry = process.argv[1] === __filename
|
|
2228
|
+
if (isCliEntry) {
|
|
2229
|
+
const args = process.argv.slice(2)
|
|
2230
|
+
const command = args[0]
|
|
2052
2231
|
|
|
2053
|
-
if (!command || command === '--help' || command === '-h') {
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
}
|
|
2232
|
+
if (!command || command === '--help' || command === '-h') {
|
|
2233
|
+
printHelp()
|
|
2234
|
+
process.exit(0)
|
|
2235
|
+
}
|
|
2057
2236
|
|
|
2058
|
-
if (command === '--version' || command === '-v') {
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
}
|
|
2237
|
+
if (command === '--version' || command === '-v') {
|
|
2238
|
+
process.stdout.write(getVersion() + '\n')
|
|
2239
|
+
process.exit(0)
|
|
2240
|
+
}
|
|
2062
2241
|
|
|
2063
|
-
switch (command) {
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2242
|
+
switch (command) {
|
|
2243
|
+
case 'analyze':
|
|
2244
|
+
await cmdAnalyze(args.slice(1))
|
|
2245
|
+
break
|
|
2246
|
+
case 'capture':
|
|
2247
|
+
await cmdCapture(args.slice(1))
|
|
2248
|
+
break
|
|
2249
|
+
case 'report':
|
|
2250
|
+
await cmdReport(args.slice(1))
|
|
2251
|
+
break
|
|
2252
|
+
case 'models':
|
|
2253
|
+
await cmdModels()
|
|
2254
|
+
break
|
|
2255
|
+
default:
|
|
2256
|
+
fail(`Unknown command: ${command}. Run apt-proof-video --help for usage.`)
|
|
2257
|
+
}
|
|
2078
2258
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-recipe.d.mts","sourceRoot":"","sources":["../../../src/cli/commands/apply-recipe.mjs"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,2CAHW,MAAM,UACN,MAAM,EAAE,uDAuElB"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/apply-recipe.mjs — `apt-tools apply-recipe <projectDir> [--confirm] [--accept-all] [--force]`.
|
|
3
|
+
*
|
|
4
|
+
* Wraps applyRecipe() at the CLI surface.
|
|
5
|
+
*
|
|
6
|
+
* --confirm switches from dry-run (the default) to live writes.
|
|
7
|
+
* --accept-all bypasses per-change confirmation (pipeline/scripted use).
|
|
8
|
+
* --force overrides the TOFU user_modified guard — overwrites files
|
|
9
|
+
* whose SHA diverges from the recipe's expected before value.
|
|
10
|
+
* Files containing the recipe's marker are still skipped.
|
|
11
|
+
*
|
|
12
|
+
* The two flags compose: `--confirm` alone enters live mode but defers
|
|
13
|
+
* per-change accept/skip to the caller — without `--accept-all` and
|
|
14
|
+
* without a stdin-driven prompt, every change is SKIPPED (fail-safe per
|
|
15
|
+
* ID-02). Adopters using the interactive apt-setup SKILL.md mini-flow
|
|
16
|
+
* walk each change one at a time before invoking the CLI with
|
|
17
|
+
* `--accept-all` once they've reviewed the diff. Adopters in CI /
|
|
18
|
+
* fan-out / scripted contexts pass both flags up front.
|
|
19
|
+
*
|
|
20
|
+
* Exit codes:
|
|
21
|
+
* 0 — applyRecipe completed (dry-run or confirmed)
|
|
22
|
+
* 1 — usage error / no-recipe-match / applyRecipe threw
|
|
23
|
+
*/
|
|
24
|
+
import { parseFlags } from '../util/args.mjs';
|
|
25
|
+
import { err, exitWith, ok } from '../util/result.mjs';
|
|
26
|
+
import { loadRuntimeCapabilities } from '../util/runtime-capabilities.mjs';
|
|
27
|
+
import { applyRecipe } from '../verify-proof/sandbox/apply.mjs';
|
|
28
|
+
import { matchPatternForProject } from '../verify-proof/sandbox/pattern-matcher.mjs';
|
|
29
|
+
import { discoverBundledRecipes } from '../verify-proof/sandbox/sandbox-config.mjs';
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} projectDir
|
|
32
|
+
* @param {string[]} [extra]
|
|
33
|
+
*/
|
|
34
|
+
export async function cmdApplyRecipe(projectDir, extra = []) {
|
|
35
|
+
if (!projectDir) {
|
|
36
|
+
return err('Usage: apt-tools apply-recipe <project-dir> [--confirm] [--accept-all]');
|
|
37
|
+
}
|
|
38
|
+
const flags = parseFlags(extra);
|
|
39
|
+
const confirm = flags.has('confirm');
|
|
40
|
+
const acceptAll = flags.has('accept-all');
|
|
41
|
+
const force = flags.has('force');
|
|
42
|
+
const recipes = discoverBundledRecipes();
|
|
43
|
+
const runtime = loadRuntimeCapabilities(projectDir);
|
|
44
|
+
const explicitRecipeId = flags.get('recipe') ?? null;
|
|
45
|
+
let recipeId;
|
|
46
|
+
let matchReason;
|
|
47
|
+
if (explicitRecipeId) {
|
|
48
|
+
recipeId = explicitRecipeId;
|
|
49
|
+
matchReason = 'explicit';
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const match = matchPatternForProject(projectDir, runtime, recipes);
|
|
53
|
+
recipeId = match.recipeId;
|
|
54
|
+
matchReason = match.reason;
|
|
55
|
+
}
|
|
56
|
+
if (!recipeId) {
|
|
57
|
+
return exitWith({
|
|
58
|
+
status: 'error',
|
|
59
|
+
command: 'apply-recipe',
|
|
60
|
+
code: 'E_NO_RECIPE',
|
|
61
|
+
reason: matchReason,
|
|
62
|
+
runtime,
|
|
63
|
+
docs: 'docs/verify-proof-sandbox-patterns.md',
|
|
64
|
+
}, 1);
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const result = await applyRecipe({
|
|
68
|
+
projectDir,
|
|
69
|
+
recipeId,
|
|
70
|
+
recipes,
|
|
71
|
+
confirm,
|
|
72
|
+
// AC8 + ID-02 — only auto-accept when the caller passed
|
|
73
|
+
// --accept-all explicitly. Without the flag the underlying
|
|
74
|
+
// applyRecipe defaults to skip (every change recorded as
|
|
75
|
+
// `user_declined`); callers driving per-change UX wrap the
|
|
76
|
+
// applier directly with their own confirmer.
|
|
77
|
+
perChangeConfirm: acceptAll ? async () => 'accept' : undefined,
|
|
78
|
+
force,
|
|
79
|
+
});
|
|
80
|
+
return ok({
|
|
81
|
+
status: 'ok',
|
|
82
|
+
command: 'apply-recipe',
|
|
83
|
+
project_dir: projectDir,
|
|
84
|
+
recipe_id: recipeId,
|
|
85
|
+
recipe_version: result.recipe_version,
|
|
86
|
+
confirm,
|
|
87
|
+
accept_all: acceptAll,
|
|
88
|
+
aborted: result.aborted,
|
|
89
|
+
writes: result.writes,
|
|
90
|
+
skips: result.skips,
|
|
91
|
+
audit_path: result.audit_path,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
return err(`apply-recipe: ${e?.message ?? String(e)}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=apply-recipe.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-recipe.mjs","sourceRoot":"","sources":["../../../src/cli/commands/apply-recipe.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {{ binary: string, args: string[] }} LocalCommand
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the ordered launch sequence for a (platform, mode, device).
|
|
6
|
+
*
|
|
7
|
+
* - mode 'expo' — `npx expo run:ios|run:android` builds, installs, launches,
|
|
8
|
+
* and starts Metro in one step (the common Expo/RN path).
|
|
9
|
+
* - mode 'native' — device-prep only (`xcrun simctl boot` / `adb
|
|
10
|
+
* wait-for-device`); the native build+install+launch is delegated (gradle /
|
|
11
|
+
* the XcodeBuildMCP escalation per D-02), out of scope for v1's planner.
|
|
12
|
+
*
|
|
13
|
+
* @param {{ platform?: string, mode?: string, device?: string }} [opts]
|
|
14
|
+
* @returns {LocalCommand[]}
|
|
15
|
+
*/
|
|
16
|
+
export function planLaunchSequence(opts?: {
|
|
17
|
+
platform?: string;
|
|
18
|
+
mode?: string;
|
|
19
|
+
device?: string;
|
|
20
|
+
}): LocalCommand[];
|
|
21
|
+
/**
|
|
22
|
+
* Launch-readiness predicate (D-04). A successful screenshot alone is NOT
|
|
23
|
+
* enough — for RN/Expo it can capture a native splash, an Expo loading
|
|
24
|
+
* overlay, a redbox, or the dev-client launcher. ALL signals must hold before
|
|
25
|
+
* UI driving starts. For a pure-native app (no JS bundle) the caller passes
|
|
26
|
+
* `bundleConnected: true` and `launcherState: false`.
|
|
27
|
+
*
|
|
28
|
+
* @param {{ foregrounded?: boolean, bundleConnected?: boolean, redbox?: boolean, launcherState?: boolean }} [signals]
|
|
29
|
+
* @returns {boolean}
|
|
30
|
+
*/
|
|
31
|
+
export function isAppReady(signals?: {
|
|
32
|
+
foregrounded?: boolean;
|
|
33
|
+
bundleConnected?: boolean;
|
|
34
|
+
redbox?: boolean;
|
|
35
|
+
launcherState?: boolean;
|
|
36
|
+
}): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* `apt-tools mobile prepare <project-dir> --platform <ios|android>
|
|
39
|
+
* [--mode <expo|native>] [--device <id>]`
|
|
40
|
+
*
|
|
41
|
+
* @param {string} projectDir
|
|
42
|
+
* @param {string[]} args
|
|
43
|
+
* @returns {{ envelope: object, exitCode: number }}
|
|
44
|
+
*/
|
|
45
|
+
export function cmdMobilePrepare(projectDir: string, args: string[]): {
|
|
46
|
+
envelope: object;
|
|
47
|
+
exitCode: number;
|
|
48
|
+
};
|
|
49
|
+
export type LocalCommand = {
|
|
50
|
+
binary: string;
|
|
51
|
+
args: string[];
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=mobile-prepare.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mobile-prepare.d.mts","sourceRoot":"","sources":["../../../src/cli/commands/mobile-prepare.mjs"],"names":[],"mappings":"AAoBA;;GAEG;AAEH;;;;;;;;;;;GAWG;AACH,0CAHW;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD,YAAY,EAAE,CAsB1B;AAED;;;;;;;;;GASG;AACH,qCAHW;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9F,OAAO,CAUnB;AA+BD;;;;;;;GAOG;AACH,6CAJW,MAAM,QACN,MAAM,EAAE,GACN;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAqClD;2BAjIY;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE"}
|