avorelo 0.3.0 → 0.3.2
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/README.md +10 -5
- package/dist/avorelo.mjs +1141 -242
- package/package.json +1 -1
package/dist/avorelo.mjs
CHANGED
|
@@ -362,6 +362,16 @@ function listReceipts(dir) {
|
|
|
362
362
|
}
|
|
363
363
|
return out;
|
|
364
364
|
}
|
|
365
|
+
function readReceipt(dir, receiptId) {
|
|
366
|
+
const path = join(localReceiptDir(dir), `${receiptId}.json`);
|
|
367
|
+
if (!existsSync(path)) return null;
|
|
368
|
+
try {
|
|
369
|
+
const r2 = JSON.parse(readFileSync(path, "utf8"));
|
|
370
|
+
return r2 && typeof r2.receiptId === "string" ? r2 : null;
|
|
371
|
+
} catch {
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
365
375
|
var init_receipts = __esm({
|
|
366
376
|
"src/avorelo/kernel/receipts/index.ts"() {
|
|
367
377
|
init_redaction();
|
|
@@ -5659,9 +5669,9 @@ function executeMultiAgentReview(reviewPlan, executorResult, plan, ctx) {
|
|
|
5659
5669
|
break;
|
|
5660
5670
|
}
|
|
5661
5671
|
}
|
|
5662
|
-
const
|
|
5672
|
+
const finalVerdict2 = determineFinalVerdict(rounds, stopCondition);
|
|
5663
5673
|
const routedToManualGate = stopCondition === "REVIEWER_DISAGREEMENT" || stopCondition === "MAX_REVIEW_ROUNDS_REACHED" || stopCondition === "VERIFIER_OVERRIDE";
|
|
5664
|
-
const modelConsensusOnly =
|
|
5674
|
+
const modelConsensusOnly = finalVerdict2 === "approved" && rounds.every((r2) => r2.verifierPassed === null);
|
|
5665
5675
|
const reasonCodes = [
|
|
5666
5676
|
...reviewPlan.triggerReasonCodes,
|
|
5667
5677
|
`REVIEW_ROUNDS:${rounds.length}`,
|
|
@@ -5673,7 +5683,7 @@ function executeMultiAgentReview(reviewPlan, executorResult, plan, ctx) {
|
|
|
5673
5683
|
attempted: true,
|
|
5674
5684
|
roundsCompleted: rounds.length,
|
|
5675
5685
|
maxRoundsReached: stopCondition === "MAX_REVIEW_ROUNDS_REACHED",
|
|
5676
|
-
finalVerdict,
|
|
5686
|
+
finalVerdict: finalVerdict2,
|
|
5677
5687
|
rounds,
|
|
5678
5688
|
totalDurationMs: Date.now() - start,
|
|
5679
5689
|
reasonCodes,
|
|
@@ -6523,7 +6533,7 @@ init_run();
|
|
|
6523
6533
|
init_work_contract();
|
|
6524
6534
|
init_receipts();
|
|
6525
6535
|
init_state_ledger();
|
|
6526
|
-
import { writeFileSync as writeFileSync37, mkdirSync as mkdirSync39, existsSync as
|
|
6536
|
+
import { writeFileSync as writeFileSync37, mkdirSync as mkdirSync39, existsSync as existsSync62, readFileSync as readFileSync46, appendFileSync as appendFileSync11, rmSync as rmSync3, unlinkSync as unlinkSync4 } from "node:fs";
|
|
6527
6537
|
import { join as join61 } from "node:path";
|
|
6528
6538
|
|
|
6529
6539
|
// src/avorelo/capabilities/activation/index.ts
|
|
@@ -6604,93 +6614,170 @@ function doctor(targetDir) {
|
|
|
6604
6614
|
return { ok: checks.every((c) => c.passed), checks, hookLatencyMs: fired.latencyMs };
|
|
6605
6615
|
}
|
|
6606
6616
|
|
|
6607
|
-
// src/avorelo/capabilities/activation/activation-
|
|
6608
|
-
import {
|
|
6609
|
-
import {
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
const dir = join23(targetDir, ACTIVATION_STATE_DIR);
|
|
6616
|
-
mkdirSync12(dir, { recursive: true });
|
|
6617
|
-
const path = join23(dir, ACTIVATION_STATE_FILE);
|
|
6618
|
-
const safe = redact(state).value;
|
|
6619
|
-
writeFileSync12(path, JSON.stringify(safe, null, 2));
|
|
6620
|
-
return path;
|
|
6621
|
-
}
|
|
6622
|
-
function readActivationState(targetDir) {
|
|
6623
|
-
const path = join23(targetDir, ACTIVATION_STATE_DIR, ACTIVATION_STATE_FILE);
|
|
6624
|
-
if (!existsSync25(path)) return null;
|
|
6617
|
+
// src/avorelo/capabilities/activation/activation-preflight.ts
|
|
6618
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
6619
|
+
import { execSync } from "node:child_process";
|
|
6620
|
+
import { platform, tmpdir as tmpdir2 } from "node:os";
|
|
6621
|
+
function runPreflight(targetDir) {
|
|
6622
|
+
const checks = [];
|
|
6623
|
+
const isWindows = platform() === "win32";
|
|
6624
|
+
let nodeOk = false;
|
|
6625
6625
|
try {
|
|
6626
|
-
const
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
return parsed;
|
|
6626
|
+
const v = execSync("node --version", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
6627
|
+
nodeOk = v.startsWith("v");
|
|
6628
|
+
checks.push({ id: "node_available", label: "Node.js available", passed: nodeOk, details: v });
|
|
6630
6629
|
} catch {
|
|
6631
|
-
|
|
6630
|
+
checks.push({ id: "node_available", label: "Node.js available", passed: false, details: "node not found in PATH", recovery: "Install Node.js from https://nodejs.org (LTS recommended)" });
|
|
6632
6631
|
}
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6632
|
+
let npmOk = false;
|
|
6633
|
+
try {
|
|
6634
|
+
const v = execSync("npm --version", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
6635
|
+
npmOk = true;
|
|
6636
|
+
checks.push({ id: "npm_available", label: "npm available", passed: true, details: `npm ${v}` });
|
|
6637
|
+
} catch {
|
|
6638
|
+
checks.push({ id: "npm_available", label: "npm available", passed: false, details: "npm not found in PATH", recovery: "npm is included with Node.js \u2014 reinstall Node.js from https://nodejs.org" });
|
|
6640
6639
|
}
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6640
|
+
let npxOk = false;
|
|
6641
|
+
try {
|
|
6642
|
+
const v = execSync("npx --version", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
6643
|
+
npxOk = true;
|
|
6644
|
+
checks.push({ id: "npx_available", label: "npx available", passed: true, details: `npx ${v}` });
|
|
6645
|
+
} catch {
|
|
6646
|
+
checks.push({ id: "npx_available", label: "npx available", passed: false, details: "npx not found in PATH", recovery: "npx is included with npm 5.2+. Update Node.js to get a recent npm." });
|
|
6647
|
+
}
|
|
6648
|
+
let cacheOk = false;
|
|
6649
|
+
try {
|
|
6650
|
+
const cachePath = execSync("npm config get cache", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
6651
|
+
if (cachePath && existsSync25(cachePath)) {
|
|
6652
|
+
cacheOk = true;
|
|
6653
|
+
checks.push({ id: "npm_cache_writable", label: "npm cache directory accessible", passed: true, details: "cache directory exists" });
|
|
6654
|
+
} else {
|
|
6655
|
+
checks.push({
|
|
6656
|
+
id: "npm_cache_writable",
|
|
6657
|
+
label: "npm cache directory accessible",
|
|
6658
|
+
passed: false,
|
|
6659
|
+
details: "cache path does not exist",
|
|
6660
|
+
recovery: isWindows ? 'Use a temporary cache. PowerShell: $env:npm_config_cache="$env:TEMP\\npm-cache-avorelo"; npx -y avorelo@latest activate. cmd.exe: cmd /c "set npm_config_cache=%TEMP%\\npm-cache-avorelo && npx -y avorelo@latest activate"' : "Use a temporary cache: npm_config_cache=$(mktemp -d) npx -y avorelo@latest activate"
|
|
6661
|
+
});
|
|
6662
|
+
}
|
|
6663
|
+
} catch {
|
|
6664
|
+
checks.push({
|
|
6665
|
+
id: "npm_cache_writable",
|
|
6666
|
+
label: "npm cache directory accessible",
|
|
6667
|
+
passed: false,
|
|
6668
|
+
details: "could not read npm cache config",
|
|
6669
|
+
recovery: isWindows ? 'Use a temporary cache. PowerShell: $env:npm_config_cache="$env:TEMP\\npm-cache-avorelo"; npx -y avorelo@latest activate. cmd.exe: cmd /c "set npm_config_cache=%TEMP%\\npm-cache-avorelo && npx -y avorelo@latest activate"' : "Use a temporary cache: npm_config_cache=$(mktemp -d) npx -y avorelo@latest activate"
|
|
6670
|
+
});
|
|
6671
|
+
}
|
|
6672
|
+
let tempOk = false;
|
|
6673
|
+
try {
|
|
6674
|
+
const td = tmpdir2();
|
|
6675
|
+
tempOk = existsSync25(td);
|
|
6676
|
+
checks.push({ id: "temp_dir_writable", label: "Temp directory writable", passed: tempOk, details: tempOk ? "temp dir accessible" : "temp dir not found" });
|
|
6677
|
+
} catch {
|
|
6678
|
+
checks.push({ id: "temp_dir_writable", label: "Temp directory writable", passed: false, details: "cannot access temp directory" });
|
|
6679
|
+
}
|
|
6680
|
+
let targetOk = false;
|
|
6681
|
+
try {
|
|
6682
|
+
targetOk = existsSync25(targetDir);
|
|
6683
|
+
checks.push({ id: "target_dir_writable", label: "Target directory exists", passed: targetOk, details: targetOk ? "directory accessible" : "directory not found" });
|
|
6684
|
+
} catch {
|
|
6685
|
+
checks.push({ id: "target_dir_writable", label: "Target directory exists", passed: false, details: "cannot access target directory" });
|
|
6686
|
+
}
|
|
6687
|
+
let psOk = true;
|
|
6688
|
+
if (isWindows) {
|
|
6689
|
+
try {
|
|
6690
|
+
const policy = execSync("powershell -NoProfile -Command Get-ExecutionPolicy", { encoding: "utf8", timeout: 5e3 }).trim().toLowerCase();
|
|
6691
|
+
const blocked = policy === "restricted" || policy === "allsigned";
|
|
6692
|
+
psOk = !blocked;
|
|
6693
|
+
checks.push({
|
|
6694
|
+
id: "powershell_execution_policy",
|
|
6695
|
+
label: "PowerShell execution policy",
|
|
6696
|
+
passed: psOk,
|
|
6697
|
+
details: `Policy: ${policy}`,
|
|
6698
|
+
recovery: blocked ? "PowerShell is blocking script execution. Use Command Prompt instead:\n cmd /c npx -y avorelo@latest activate" : void 0
|
|
6699
|
+
});
|
|
6700
|
+
} catch {
|
|
6701
|
+
checks.push({ id: "powershell_execution_policy", label: "PowerShell execution policy", passed: true, details: "could not check (non-PowerShell shell)" });
|
|
6702
|
+
}
|
|
6703
|
+
}
|
|
6704
|
+
let registryOk = false;
|
|
6705
|
+
try {
|
|
6706
|
+
const result3 = execSync("npm view avorelo@latest version", { encoding: "utf8", timeout: 15e3 }).trim();
|
|
6707
|
+
registryOk = /^\d+\.\d+\.\d+/.test(result3);
|
|
6708
|
+
checks.push({ id: "network_npm_registry", label: "npm registry reachable", passed: registryOk, details: registryOk ? `latest: ${result3}` : "unexpected response" });
|
|
6709
|
+
} catch {
|
|
6710
|
+
checks.push({ id: "network_npm_registry", label: "npm registry reachable", passed: false, details: "cannot reach npm registry", recovery: "Check your network connection. If behind a proxy, configure npm: npm config set proxy <url>" });
|
|
6711
|
+
}
|
|
6712
|
+
const allPassed = checks.every((c) => c.passed);
|
|
6713
|
+
const canStart = nodeOk && npmOk && npxOk;
|
|
6714
|
+
let fallbackCommand;
|
|
6715
|
+
if (!allPassed && isWindows) {
|
|
6716
|
+
fallbackCommand = buildWindowsFallbackCommand();
|
|
6717
|
+
}
|
|
6718
|
+
const taxonomy = allPassed ? "READY" : canStart ? "LOCAL_PREFLIGHT_FAILED" : "BLOCKED_BY_RUNNER_BEFORE_AVORELO_STARTED";
|
|
6719
|
+
return { ok: allPassed, canStart, checks, fallbackCommand, taxonomy };
|
|
6661
6720
|
}
|
|
6662
|
-
function
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6721
|
+
function buildWindowsFallbackCommand() {
|
|
6722
|
+
return [
|
|
6723
|
+
":: Avorelo activation \u2014 safe Windows fallback",
|
|
6724
|
+
":: Run this in Command Prompt (cmd.exe), not PowerShell",
|
|
6725
|
+
"set AVORELO_TEMP=%TEMP%\\avorelo-activate-%RANDOM%",
|
|
6726
|
+
"mkdir %AVORELO_TEMP%",
|
|
6727
|
+
"set npm_config_cache=%AVORELO_TEMP%\\npm-cache",
|
|
6728
|
+
"cd /d %AVORELO_TEMP%",
|
|
6729
|
+
"npx -y avorelo@latest activate",
|
|
6730
|
+
"npx -y avorelo@latest status"
|
|
6731
|
+
].join("\n");
|
|
6732
|
+
}
|
|
6733
|
+
function formatPreflightReport(result3) {
|
|
6734
|
+
const lines = ["", "Avorelo Activation Preflight", ""];
|
|
6735
|
+
for (const c of result3.checks) {
|
|
6736
|
+
const icon = c.passed ? "\u2713" : "\u2717";
|
|
6737
|
+
lines.push(` ${icon} ${c.label}: ${c.details}`);
|
|
6738
|
+
if (!c.passed && c.recovery) {
|
|
6739
|
+
for (const line of c.recovery.split("\n")) {
|
|
6740
|
+
lines.push(` \u2192 ${line}`);
|
|
6741
|
+
}
|
|
6742
|
+
}
|
|
6666
6743
|
}
|
|
6667
|
-
|
|
6668
|
-
if (
|
|
6669
|
-
|
|
6744
|
+
lines.push("");
|
|
6745
|
+
if (result3.ok) {
|
|
6746
|
+
lines.push(" All checks passed. Ready to activate.");
|
|
6747
|
+
} else if (result3.canStart) {
|
|
6748
|
+
lines.push(" Some checks failed but activation can attempt to proceed.");
|
|
6749
|
+
lines.push(" Fix the issues above for the best experience.");
|
|
6750
|
+
} else {
|
|
6751
|
+
lines.push(" Activation cannot start in this environment.");
|
|
6752
|
+
lines.push(" Avorelo requires Node.js and npm to be available.");
|
|
6753
|
+
if (result3.fallbackCommand) {
|
|
6754
|
+
lines.push("");
|
|
6755
|
+
lines.push(" Safe fallback command:");
|
|
6756
|
+
for (const line of result3.fallbackCommand.split("\n")) {
|
|
6757
|
+
lines.push(` ${line}`);
|
|
6758
|
+
}
|
|
6759
|
+
}
|
|
6670
6760
|
}
|
|
6671
|
-
|
|
6761
|
+
lines.push("");
|
|
6762
|
+
return lines.join("\n");
|
|
6672
6763
|
}
|
|
6673
6764
|
|
|
6674
|
-
// src/avorelo/capabilities/activation/activation-runner.ts
|
|
6675
|
-
import { join as join27 } from "node:path";
|
|
6676
|
-
import { existsSync as existsSync29 } from "node:fs";
|
|
6677
|
-
|
|
6678
6765
|
// src/avorelo/capabilities/activation/activation-detector.ts
|
|
6679
|
-
import { existsSync as existsSync26, readFileSync as
|
|
6680
|
-
import { join as
|
|
6681
|
-
import { execSync } from "node:child_process";
|
|
6682
|
-
import { platform } from "node:os";
|
|
6766
|
+
import { existsSync as existsSync26, readFileSync as readFileSync12 } from "node:fs";
|
|
6767
|
+
import { join as join23 } from "node:path";
|
|
6768
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
6769
|
+
import { platform as platform2 } from "node:os";
|
|
6683
6770
|
function tryExec(cmd, cwd) {
|
|
6684
6771
|
try {
|
|
6685
|
-
return
|
|
6772
|
+
return execSync2(cmd, { cwd, stdio: "pipe", timeout: 5e3 }).toString().trim();
|
|
6686
6773
|
} catch {
|
|
6687
6774
|
return null;
|
|
6688
6775
|
}
|
|
6689
6776
|
}
|
|
6690
6777
|
function commandExists(cmd) {
|
|
6691
6778
|
try {
|
|
6692
|
-
const check =
|
|
6693
|
-
|
|
6779
|
+
const check = platform2() === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
6780
|
+
execSync2(check, { stdio: "pipe", timeout: 3e3 });
|
|
6694
6781
|
return true;
|
|
6695
6782
|
} catch {
|
|
6696
6783
|
return false;
|
|
@@ -6707,18 +6794,18 @@ function detectRepoIdentity(dir) {
|
|
|
6707
6794
|
function detectEnvironment(dir) {
|
|
6708
6795
|
const nodeVersion = tryExec("node --version", dir);
|
|
6709
6796
|
let packageManager = null;
|
|
6710
|
-
if (existsSync26(
|
|
6711
|
-
else if (existsSync26(
|
|
6712
|
-
else if (existsSync26(
|
|
6713
|
-
else if (existsSync26(
|
|
6714
|
-
else if (existsSync26(
|
|
6797
|
+
if (existsSync26(join23(dir, "pnpm-lock.yaml"))) packageManager = "pnpm";
|
|
6798
|
+
else if (existsSync26(join23(dir, "yarn.lock"))) packageManager = "yarn";
|
|
6799
|
+
else if (existsSync26(join23(dir, "bun.lockb"))) packageManager = "bun";
|
|
6800
|
+
else if (existsSync26(join23(dir, "package-lock.json"))) packageManager = "npm";
|
|
6801
|
+
else if (existsSync26(join23(dir, "package.json"))) packageManager = "npm";
|
|
6715
6802
|
let framework = null;
|
|
6716
6803
|
let testCommand = null;
|
|
6717
6804
|
let sitePreviewCommand = null;
|
|
6718
|
-
const pkgPath =
|
|
6805
|
+
const pkgPath = join23(dir, "package.json");
|
|
6719
6806
|
if (existsSync26(pkgPath)) {
|
|
6720
6807
|
try {
|
|
6721
|
-
const pkg = JSON.parse(
|
|
6808
|
+
const pkg = JSON.parse(readFileSync12(pkgPath, "utf8"));
|
|
6722
6809
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
6723
6810
|
if (deps.next) framework = "next";
|
|
6724
6811
|
else if (deps.react) framework = "react";
|
|
@@ -6732,29 +6819,29 @@ function detectEnvironment(dir) {
|
|
|
6732
6819
|
} catch {
|
|
6733
6820
|
}
|
|
6734
6821
|
}
|
|
6735
|
-
if (existsSync26(
|
|
6736
|
-
return { os:
|
|
6822
|
+
if (existsSync26(join23(dir, "main.wasp"))) framework = "wasp";
|
|
6823
|
+
return { os: platform2(), nodeVersion, packageManager, framework, testCommand, sitePreviewCommand };
|
|
6737
6824
|
}
|
|
6738
6825
|
function detectAiTools(dir) {
|
|
6739
6826
|
return {
|
|
6740
|
-
claudeCodeDetected: existsSync26(
|
|
6741
|
-
codexDetected: existsSync26(
|
|
6742
|
-
cursorDetected: existsSync26(
|
|
6743
|
-
agentsMdDetected: existsSync26(
|
|
6744
|
-
claudeMdDetected: existsSync26(
|
|
6745
|
-
cursorRulesDetected: existsSync26(
|
|
6746
|
-
codexConfigDetected: existsSync26(
|
|
6827
|
+
claudeCodeDetected: existsSync26(join23(dir, ".claude")) || existsSync26(join23(dir, ".claude", "settings.json")),
|
|
6828
|
+
codexDetected: existsSync26(join23(dir, ".codex")),
|
|
6829
|
+
cursorDetected: existsSync26(join23(dir, ".cursor")),
|
|
6830
|
+
agentsMdDetected: existsSync26(join23(dir, "AGENTS.md")),
|
|
6831
|
+
claudeMdDetected: existsSync26(join23(dir, "CLAUDE.md")),
|
|
6832
|
+
cursorRulesDetected: existsSync26(join23(dir, ".cursor", "rules")),
|
|
6833
|
+
codexConfigDetected: existsSync26(join23(dir, ".codex", "config.toml")) || existsSync26(join23(dir, "codex.json"))
|
|
6747
6834
|
};
|
|
6748
6835
|
}
|
|
6749
6836
|
function detectModelsAndTools(dir) {
|
|
6750
|
-
const ROOT2 =
|
|
6837
|
+
const ROOT2 = join23(import.meta.dirname, "..", "..", "..", "..");
|
|
6751
6838
|
const env = process.env;
|
|
6752
6839
|
return {
|
|
6753
|
-
skillsRegistryAvailable: existsSync26(
|
|
6754
|
-
modelRouterAvailable: existsSync26(
|
|
6755
|
-
primitiveRouterAvailable: existsSync26(
|
|
6756
|
-
scannersAvailable: existsSync26(
|
|
6757
|
-
browserProofAvailable: commandExists("playwright") || commandExists("npx") && existsSync26(
|
|
6840
|
+
skillsRegistryAvailable: existsSync26(join23(ROOT2, "src/avorelo/validation/skill-operating-system/registry.ts")),
|
|
6841
|
+
modelRouterAvailable: existsSync26(join23(ROOT2, "src/avorelo/validation/model-routing/index.ts")),
|
|
6842
|
+
primitiveRouterAvailable: existsSync26(join23(ROOT2, "tools/route-primitive.ts")),
|
|
6843
|
+
scannersAvailable: existsSync26(join23(ROOT2, "src/avorelo/validation/scanners/index.ts")),
|
|
6844
|
+
browserProofAvailable: commandExists("playwright") || commandExists("npx") && existsSync26(join23(dir, "node_modules", "@playwright")),
|
|
6758
6845
|
githubAvailable: commandExists("gh"),
|
|
6759
6846
|
billingEnvDetected: !!(env.LEMON_SQUEEZY_PRO_CHECKOUT_URL || env.LEMON_SQUEEZY_API_KEY),
|
|
6760
6847
|
authEnvDetected: !!(env.AUTH_SECRET || env.JWT_SECRET || env.SESSION_SECRET),
|
|
@@ -6788,8 +6875,79 @@ function runFullDetection(dir) {
|
|
|
6788
6875
|
return { repo, environment, aiTools, modelsAndTools, summary: { toolsDetected, modelsDetected, missingAdvisory } };
|
|
6789
6876
|
}
|
|
6790
6877
|
|
|
6878
|
+
// src/avorelo/capabilities/activation/activation-state.ts
|
|
6879
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12, existsSync as existsSync27 } from "node:fs";
|
|
6880
|
+
import { join as join24, resolve as resolve3 } from "node:path";
|
|
6881
|
+
init_redaction();
|
|
6882
|
+
var ACTIVATION_STATE_CONTRACT = "avorelo.activationState.v1";
|
|
6883
|
+
var ACTIVATION_STATE_DIR = ".avorelo/activation";
|
|
6884
|
+
var ACTIVATION_STATE_FILE = "activation-state.json";
|
|
6885
|
+
function writeActivationState(targetDir, state) {
|
|
6886
|
+
const dir = join24(targetDir, ACTIVATION_STATE_DIR);
|
|
6887
|
+
mkdirSync12(dir, { recursive: true });
|
|
6888
|
+
const path = join24(dir, ACTIVATION_STATE_FILE);
|
|
6889
|
+
const safe = redact(state).value;
|
|
6890
|
+
writeFileSync12(path, JSON.stringify(safe, null, 2));
|
|
6891
|
+
return path;
|
|
6892
|
+
}
|
|
6893
|
+
function readActivationState(targetDir) {
|
|
6894
|
+
const path = join24(targetDir, ACTIVATION_STATE_DIR, ACTIVATION_STATE_FILE);
|
|
6895
|
+
if (!existsSync27(path)) return null;
|
|
6896
|
+
try {
|
|
6897
|
+
const raw = readFileSync13(path, "utf8");
|
|
6898
|
+
const parsed = JSON.parse(raw);
|
|
6899
|
+
if (parsed.contract !== ACTIVATION_STATE_CONTRACT && parsed.contract !== "avorelo.activationState.v2") return null;
|
|
6900
|
+
return parsed;
|
|
6901
|
+
} catch {
|
|
6902
|
+
return null;
|
|
6903
|
+
}
|
|
6904
|
+
}
|
|
6905
|
+
function verifyActivationState(targetDir) {
|
|
6906
|
+
const checks = [];
|
|
6907
|
+
const state = readActivationState(targetDir);
|
|
6908
|
+
if (!state) {
|
|
6909
|
+
checks.push({ id: "state_exists", passed: false, reason: "Activation state not found" });
|
|
6910
|
+
return { valid: false, checks };
|
|
6911
|
+
}
|
|
6912
|
+
checks.push({ id: "state_exists", passed: true, reason: "Activation state found" });
|
|
6913
|
+
const validContracts = [ACTIVATION_STATE_CONTRACT, "avorelo.activationState.v2"];
|
|
6914
|
+
const contractOk = validContracts.includes(state.contract);
|
|
6915
|
+
checks.push({ id: "contract_valid", passed: contractOk, reason: contractOk ? "Contract matches" : `Expected ${ACTIVATION_STATE_CONTRACT} or v2, got ${state.contract}` });
|
|
6916
|
+
checks.push({ id: "redacted", passed: state.redacted === true, reason: state.redacted ? "State is redacted" : "State is NOT redacted" });
|
|
6917
|
+
const raw2 = state;
|
|
6918
|
+
const billingLive = raw2.billing?.billingLive;
|
|
6919
|
+
checks.push({ id: "billing_not_live", passed: billingLive === false, reason: billingLive === false ? "Billing not live" : "BILLING IS LIVE \u2014 violation" });
|
|
6920
|
+
const authLive = raw2.cloud?.authLive ?? raw2.auth?.sessionAvailable === true;
|
|
6921
|
+
checks.push({ id: "auth_not_live", passed: !authLive, reason: !authLive ? "Auth not live" : "AUTH IS LIVE \u2014 violation" });
|
|
6922
|
+
const cloudSyncLive = raw2.cloud?.cloudSyncLive;
|
|
6923
|
+
checks.push({ id: "cloud_sync_not_live", passed: cloudSyncLive === false, reason: cloudSyncLive === false ? "Cloud sync not live" : "CLOUD SYNC IS LIVE \u2014 violation" });
|
|
6924
|
+
checks.push({ id: "production_not_ready", passed: state.productionReady === false, reason: state.productionReady === false ? "Production not ready (correct)" : "PRODUCTION MARKED READY \u2014 violation" });
|
|
6925
|
+
const raw = JSON.stringify(state);
|
|
6926
|
+
const hasSecret = carriesRawSecret(raw);
|
|
6927
|
+
checks.push({ id: "no_secrets", passed: !hasSecret, reason: hasSecret ? "RAW SECRET DETECTED in state" : "No raw secrets" });
|
|
6928
|
+
const legacyTokens = ["wuz", "cco", "claudecode-optimizer"];
|
|
6929
|
+
const oldNaming = legacyTokens.some((t) => raw.toLowerCase().includes(t));
|
|
6930
|
+
checks.push({ id: "no_old_naming", passed: !oldNaming, reason: oldNaming ? "Old naming leakage detected" : "No old naming leakage" });
|
|
6931
|
+
return { valid: checks.every((c) => c.passed), checks };
|
|
6932
|
+
}
|
|
6933
|
+
function repairActivationState(targetDir) {
|
|
6934
|
+
const state = readActivationState(targetDir);
|
|
6935
|
+
if (!state) {
|
|
6936
|
+
return { repaired: false, message: "No activation state found. Run: npx avorelo activate" };
|
|
6937
|
+
}
|
|
6938
|
+
const validContracts2 = [ACTIVATION_STATE_CONTRACT, "avorelo.activationState.v2"];
|
|
6939
|
+
if (!validContracts2.includes(state.contract)) {
|
|
6940
|
+
return { repaired: false, message: `Corrupt contract: ${state.contract}. Run: npx avorelo activate (will re-create)` };
|
|
6941
|
+
}
|
|
6942
|
+
return { repaired: true, message: "Activation state is valid." };
|
|
6943
|
+
}
|
|
6944
|
+
|
|
6945
|
+
// src/avorelo/capabilities/activation/activation-runner.ts
|
|
6946
|
+
import { join as join27 } from "node:path";
|
|
6947
|
+
import { existsSync as existsSync30 } from "node:fs";
|
|
6948
|
+
|
|
6791
6949
|
// src/avorelo/capabilities/activation/activation-repair.ts
|
|
6792
|
-
import { existsSync as
|
|
6950
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13, readFileSync as readFileSync14, appendFileSync as appendFileSync2 } from "node:fs";
|
|
6793
6951
|
import { join as join25 } from "node:path";
|
|
6794
6952
|
function runSafeRepairs(targetDir) {
|
|
6795
6953
|
const repairs = [];
|
|
@@ -6805,7 +6963,7 @@ function runSafeRepairs(targetDir) {
|
|
|
6805
6963
|
];
|
|
6806
6964
|
for (const d of dirs) {
|
|
6807
6965
|
const p = join25(targetDir, d);
|
|
6808
|
-
if (!
|
|
6966
|
+
if (!existsSync28(p)) {
|
|
6809
6967
|
try {
|
|
6810
6968
|
mkdirSync13(p, { recursive: true });
|
|
6811
6969
|
repairs.push({ id: `create_dir_${d.replace(/[/.]/g, "_")}`, label: `Create ${d}`, status: "applied", path: p });
|
|
@@ -6818,7 +6976,7 @@ function runSafeRepairs(targetDir) {
|
|
|
6818
6976
|
}
|
|
6819
6977
|
repairGitignore(targetDir, repairs);
|
|
6820
6978
|
const contractPath = join25(targetDir, ".avorelo", "run-entry", "activation-contract.json");
|
|
6821
|
-
if (!
|
|
6979
|
+
if (!existsSync28(contractPath)) {
|
|
6822
6980
|
try {
|
|
6823
6981
|
writeFileSync13(contractPath, JSON.stringify({
|
|
6824
6982
|
contract: "avorelo.activationContract.v1",
|
|
@@ -6843,7 +7001,7 @@ var GITIGNORE_BLOCK = `${GITIGNORE_MARKER_START}
|
|
|
6843
7001
|
${GITIGNORE_MARKER_END}`;
|
|
6844
7002
|
function repairGitignore(targetDir, repairs) {
|
|
6845
7003
|
const gitignorePath = join25(targetDir, ".gitignore");
|
|
6846
|
-
if (!
|
|
7004
|
+
if (!existsSync28(gitignorePath)) {
|
|
6847
7005
|
try {
|
|
6848
7006
|
writeFileSync13(gitignorePath, GITIGNORE_BLOCK + "\n");
|
|
6849
7007
|
repairs.push({ id: "gitignore_create", label: "Create .gitignore with Avorelo block", status: "applied", path: gitignorePath });
|
|
@@ -6870,7 +7028,7 @@ function repairGitignore(targetDir, repairs) {
|
|
|
6870
7028
|
}
|
|
6871
7029
|
|
|
6872
7030
|
// src/avorelo/capabilities/activation/activation-run-entry.ts
|
|
6873
|
-
import { existsSync as
|
|
7031
|
+
import { existsSync as existsSync29, readFileSync as readFileSync15, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14 } from "node:fs";
|
|
6874
7032
|
import { join as join26, dirname as dirname3 } from "node:path";
|
|
6875
7033
|
var MARKER_START = "<!-- >>> Avorelo Run Entry (managed \u2014 do not edit between markers) >>> -->";
|
|
6876
7034
|
var MARKER_END = "<!-- <<< Avorelo Run Entry <<< -->";
|
|
@@ -6895,14 +7053,14 @@ Commands:
|
|
|
6895
7053
|
${MARKER_END}`;
|
|
6896
7054
|
function installBlock(filePath, blockContent) {
|
|
6897
7055
|
const dir = dirname3(filePath);
|
|
6898
|
-
if (!
|
|
7056
|
+
if (!existsSync29(dir)) {
|
|
6899
7057
|
try {
|
|
6900
7058
|
mkdirSync14(dir, { recursive: true });
|
|
6901
7059
|
} catch {
|
|
6902
7060
|
return { path: filePath, action: "blocked", reason: "Cannot create directory" };
|
|
6903
7061
|
}
|
|
6904
7062
|
}
|
|
6905
|
-
if (!
|
|
7063
|
+
if (!existsSync29(filePath)) {
|
|
6906
7064
|
try {
|
|
6907
7065
|
writeFileSync14(filePath, blockContent + "\n");
|
|
6908
7066
|
return { path: filePath, action: "created" };
|
|
@@ -6941,14 +7099,14 @@ function installRunEntry(targetDir) {
|
|
|
6941
7099
|
const claudeMd = join26(targetDir, "CLAUDE.md");
|
|
6942
7100
|
surfaces.push(installBlock(claudeMd, RUN_ENTRY_BLOCK));
|
|
6943
7101
|
const agentsMd = join26(targetDir, "AGENTS.md");
|
|
6944
|
-
if (
|
|
7102
|
+
if (existsSync29(agentsMd)) {
|
|
6945
7103
|
surfaces.push(installBlock(agentsMd, RUN_ENTRY_BLOCK));
|
|
6946
7104
|
} else {
|
|
6947
7105
|
surfaces.push({ path: agentsMd, action: "skipped", reason: "AGENTS.md does not exist \u2014 not creating" });
|
|
6948
7106
|
advisory.push("AGENTS.md not present");
|
|
6949
7107
|
}
|
|
6950
7108
|
const cursorDir = join26(targetDir, ".cursor", "rules");
|
|
6951
|
-
if (
|
|
7109
|
+
if (existsSync29(join26(targetDir, ".cursor"))) {
|
|
6952
7110
|
const cursorRule = join26(cursorDir, "avorelo.mdc");
|
|
6953
7111
|
const cursorBlock = [
|
|
6954
7112
|
"---",
|
|
@@ -6961,7 +7119,7 @@ function installRunEntry(targetDir) {
|
|
|
6961
7119
|
"Check `npx avorelo status` before starting work.",
|
|
6962
7120
|
"Use Avorelo validators for proof. Do not claim production readiness without receipts."
|
|
6963
7121
|
].join("\n");
|
|
6964
|
-
if (!
|
|
7122
|
+
if (!existsSync29(cursorRule)) {
|
|
6965
7123
|
try {
|
|
6966
7124
|
mkdirSync14(cursorDir, { recursive: true });
|
|
6967
7125
|
writeFileSync14(cursorRule, cursorBlock + "\n");
|
|
@@ -6975,7 +7133,7 @@ function installRunEntry(targetDir) {
|
|
|
6975
7133
|
} else {
|
|
6976
7134
|
advisory.push(".cursor not present");
|
|
6977
7135
|
}
|
|
6978
|
-
if (
|
|
7136
|
+
if (existsSync29(join26(targetDir, ".codex"))) {
|
|
6979
7137
|
advisory.push("Codex detected \u2014 manual run-entry recommended");
|
|
6980
7138
|
}
|
|
6981
7139
|
let contractPath;
|
|
@@ -7636,7 +7794,7 @@ function runFullActivation(targetDir) {
|
|
|
7636
7794
|
nextAction: "Run: npx avorelo status"
|
|
7637
7795
|
};
|
|
7638
7796
|
const dashboardPath = join27(targetDir, ".avorelo", "dashboard", "index.html");
|
|
7639
|
-
const localDashboard = { available:
|
|
7797
|
+
const localDashboard = { available: existsSync30(dashboardPath), path: existsSync30(dashboardPath) ? dashboardPath : void 0 };
|
|
7640
7798
|
const blockers = repairsBlocked.length;
|
|
7641
7799
|
const activationStatus = blockers > 0 ? "blocked" : "active_with_holds";
|
|
7642
7800
|
const existingState = readActivationState(targetDir);
|
|
@@ -8017,7 +8175,7 @@ function prepareDashboardHtmlWithEntitlements(html, model) {
|
|
|
8017
8175
|
|
|
8018
8176
|
// src/avorelo/adapters/lemon-squeezy/subscription-store.ts
|
|
8019
8177
|
init_redaction();
|
|
8020
|
-
import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync15, readFileSync as readFileSync16, readdirSync as readdirSync8, existsSync as
|
|
8178
|
+
import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync15, readFileSync as readFileSync16, readdirSync as readdirSync8, existsSync as existsSync31, renameSync } from "node:fs";
|
|
8021
8179
|
import { join as join28 } from "node:path";
|
|
8022
8180
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
8023
8181
|
function subscriptionDir(baseDir) {
|
|
@@ -8043,7 +8201,7 @@ function writeSubscription(baseDir, record) {
|
|
|
8043
8201
|
function readSubscription(baseDir, providerSubscriptionId) {
|
|
8044
8202
|
const dir = subscriptionDir(baseDir);
|
|
8045
8203
|
const path = join28(dir, `sub_${providerSubscriptionId}.json`);
|
|
8046
|
-
if (!
|
|
8204
|
+
if (!existsSync31(path)) return null;
|
|
8047
8205
|
try {
|
|
8048
8206
|
const r2 = JSON.parse(readFileSync16(path, "utf8"));
|
|
8049
8207
|
return r2 && typeof r2.id === "string" && typeof r2.plan === "string" ? r2 : null;
|
|
@@ -8065,7 +8223,7 @@ function readSubscriptionByUser(baseDir, userId) {
|
|
|
8065
8223
|
}
|
|
8066
8224
|
function listSubscriptions(baseDir) {
|
|
8067
8225
|
const dir = subscriptionDir(baseDir);
|
|
8068
|
-
if (!
|
|
8226
|
+
if (!existsSync31(dir)) return [];
|
|
8069
8227
|
const out = [];
|
|
8070
8228
|
for (const f of readdirSync8(dir)) {
|
|
8071
8229
|
if (!f.endsWith(".json") || f.includes(".tmp.")) continue;
|
|
@@ -8088,7 +8246,7 @@ function writeUnmatchedEvent(baseDir, event) {
|
|
|
8088
8246
|
}
|
|
8089
8247
|
function listUnmatchedEvents(baseDir) {
|
|
8090
8248
|
const dir = unmatchedDir(baseDir);
|
|
8091
|
-
if (!
|
|
8249
|
+
if (!existsSync31(dir)) return [];
|
|
8092
8250
|
const out = [];
|
|
8093
8251
|
for (const f of readdirSync8(dir)) {
|
|
8094
8252
|
if (!f.endsWith(".json") || f.includes(".tmp.")) continue;
|
|
@@ -8351,12 +8509,12 @@ function open(dir, opts) {
|
|
|
8351
8509
|
|
|
8352
8510
|
// src/avorelo/capabilities/control-center/index.ts
|
|
8353
8511
|
init_redaction();
|
|
8354
|
-
import { mkdirSync as mkdirSync25, writeFileSync as writeFileSync24, existsSync as
|
|
8512
|
+
import { mkdirSync as mkdirSync25, writeFileSync as writeFileSync24, existsSync as existsSync40, readFileSync as readFileSync24 } from "node:fs";
|
|
8355
8513
|
import { join as join40 } from "node:path";
|
|
8356
8514
|
|
|
8357
8515
|
// src/avorelo/capabilities/runtime-flow/index.ts
|
|
8358
8516
|
import { createHash as createHash12 } from "node:crypto";
|
|
8359
|
-
import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync23, appendFileSync as appendFileSync9, readFileSync as readFileSync23, existsSync as
|
|
8517
|
+
import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync23, appendFileSync as appendFileSync9, readFileSync as readFileSync23, existsSync as existsSync39 } from "node:fs";
|
|
8360
8518
|
import { join as join39 } from "node:path";
|
|
8361
8519
|
|
|
8362
8520
|
// src/avorelo/kernel/work-contract/routing.ts
|
|
@@ -8621,7 +8779,7 @@ init_session();
|
|
|
8621
8779
|
|
|
8622
8780
|
// src/avorelo/capabilities/context-compiler/index.ts
|
|
8623
8781
|
import { createHash as createHash7 } from "node:crypto";
|
|
8624
|
-
import { appendFileSync as appendFileSync3, existsSync as
|
|
8782
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync32, mkdirSync as mkdirSync17, readFileSync as readFileSync17, writeFileSync as writeFileSync17 } from "node:fs";
|
|
8625
8783
|
import { join as join30 } from "node:path";
|
|
8626
8784
|
|
|
8627
8785
|
// src/avorelo/capabilities/secret-boundary/index.ts
|
|
@@ -9281,7 +9439,7 @@ function writeContextPack(dir, pack) {
|
|
|
9281
9439
|
}
|
|
9282
9440
|
|
|
9283
9441
|
// src/avorelo/capabilities/continuity/index.ts
|
|
9284
|
-
import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync18, readFileSync as readFileSync18, existsSync as
|
|
9442
|
+
import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync18, readFileSync as readFileSync18, existsSync as existsSync33, appendFileSync as appendFileSync4 } from "node:fs";
|
|
9285
9443
|
import { join as join31 } from "node:path";
|
|
9286
9444
|
init_redactor();
|
|
9287
9445
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -9437,7 +9595,7 @@ function writeContinuity(dir, packet) {
|
|
|
9437
9595
|
}
|
|
9438
9596
|
function loadLatestContinuity(dir) {
|
|
9439
9597
|
const latest = join31(continuityDir(dir), "latest.json");
|
|
9440
|
-
if (!
|
|
9598
|
+
if (!existsSync33(latest)) return null;
|
|
9441
9599
|
try {
|
|
9442
9600
|
const p = JSON.parse(readFileSync18(latest, "utf8"));
|
|
9443
9601
|
return p && p.contract === "avorelo.nextRunContinuity.v1" ? p : null;
|
|
@@ -9448,7 +9606,7 @@ function loadLatestContinuity(dir) {
|
|
|
9448
9606
|
|
|
9449
9607
|
// src/avorelo/capabilities/token-cost-evidence/index.ts
|
|
9450
9608
|
init_redactor();
|
|
9451
|
-
import { mkdirSync as mkdirSync19, readFileSync as readFileSync19, existsSync as
|
|
9609
|
+
import { mkdirSync as mkdirSync19, readFileSync as readFileSync19, existsSync as existsSync34, appendFileSync as appendFileSync5 } from "node:fs";
|
|
9452
9610
|
import { join as join32 } from "node:path";
|
|
9453
9611
|
import { createHash as createHash8 } from "node:crypto";
|
|
9454
9612
|
var FORBIDDEN_IMPORT_KEYS = [
|
|
@@ -9744,7 +9902,7 @@ function writeTokenCostEvidence(dir, e) {
|
|
|
9744
9902
|
}
|
|
9745
9903
|
function loadTokenCostEvidence(dir) {
|
|
9746
9904
|
const path = join32(evidenceDir(dir), "token-cost.jsonl");
|
|
9747
|
-
if (!
|
|
9905
|
+
if (!existsSync34(path)) return [];
|
|
9748
9906
|
const out = [];
|
|
9749
9907
|
for (const line of readFileSync19(path, "utf8").split(/\r?\n/)) {
|
|
9750
9908
|
if (!line.trim()) continue;
|
|
@@ -9759,7 +9917,7 @@ function loadTokenCostEvidence(dir) {
|
|
|
9759
9917
|
|
|
9760
9918
|
// src/avorelo/capabilities/proof-report/index.ts
|
|
9761
9919
|
init_redactor();
|
|
9762
|
-
import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync20, appendFileSync as appendFileSync6, existsSync as
|
|
9920
|
+
import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync20, appendFileSync as appendFileSync6, existsSync as existsSync35, readFileSync as readFileSync20 } from "node:fs";
|
|
9763
9921
|
import { join as join33 } from "node:path";
|
|
9764
9922
|
import { createHash as createHash9 } from "node:crypto";
|
|
9765
9923
|
var rs = (s) => redactString2(String(s ?? ""), "handoff", "report").redacted;
|
|
@@ -9916,7 +10074,7 @@ function writeProofReport(dir, r2) {
|
|
|
9916
10074
|
}
|
|
9917
10075
|
function loadLatestProofReport(dir) {
|
|
9918
10076
|
const latest = join33(reportsDir(dir), "proof-report.latest.json");
|
|
9919
|
-
if (!
|
|
10077
|
+
if (!existsSync35(latest)) return null;
|
|
9920
10078
|
try {
|
|
9921
10079
|
return JSON.parse(readFileSync20(latest, "utf8"));
|
|
9922
10080
|
} catch {
|
|
@@ -9926,7 +10084,7 @@ function loadLatestProofReport(dir) {
|
|
|
9926
10084
|
|
|
9927
10085
|
// src/avorelo/capabilities/value-ledger/index.ts
|
|
9928
10086
|
init_redactor();
|
|
9929
|
-
import { mkdirSync as mkdirSync21, writeFileSync as writeFileSync21, readFileSync as readFileSync21, existsSync as
|
|
10087
|
+
import { mkdirSync as mkdirSync21, writeFileSync as writeFileSync21, readFileSync as readFileSync21, existsSync as existsSync36, appendFileSync as appendFileSync7 } from "node:fs";
|
|
9930
10088
|
import { join as join34 } from "node:path";
|
|
9931
10089
|
import { createHash as createHash10 } from "node:crypto";
|
|
9932
10090
|
function safeText2(s) {
|
|
@@ -10075,7 +10233,7 @@ function appendValueLedgerEntry(dir, e) {
|
|
|
10075
10233
|
}
|
|
10076
10234
|
function loadValueLedgerEntries(dir) {
|
|
10077
10235
|
const path = join34(ledgerDir(dir), "value-ledger.jsonl");
|
|
10078
|
-
if (!
|
|
10236
|
+
if (!existsSync36(path)) return [];
|
|
10079
10237
|
const out = [];
|
|
10080
10238
|
for (const line of readFileSync21(path, "utf8").split(/\r?\n/)) {
|
|
10081
10239
|
if (!line.trim()) continue;
|
|
@@ -10251,7 +10409,7 @@ import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync22 } from "node
|
|
|
10251
10409
|
import { join as join38 } from "node:path";
|
|
10252
10410
|
|
|
10253
10411
|
// src/avorelo/capabilities/context-check/scanner.ts
|
|
10254
|
-
import { existsSync as
|
|
10412
|
+
import { existsSync as existsSync37, readdirSync as readdirSync9, statSync as statSync3, openSync, readSync, closeSync } from "node:fs";
|
|
10255
10413
|
import { join as join36, relative, sep as sep3 } from "node:path";
|
|
10256
10414
|
var BYTES_PER_TOKEN_ESTIMATE = 4;
|
|
10257
10415
|
var MAX_SCAN_DEPTH = 5;
|
|
@@ -10306,7 +10464,7 @@ function extractReferences(content) {
|
|
|
10306
10464
|
function scanClaude(repoRoot2) {
|
|
10307
10465
|
const sources = [];
|
|
10308
10466
|
const rootMd = join36(repoRoot2, "CLAUDE.md");
|
|
10309
|
-
if (
|
|
10467
|
+
if (existsSync37(rootMd)) {
|
|
10310
10468
|
const meta = fileMeta(rootMd);
|
|
10311
10469
|
if (meta) {
|
|
10312
10470
|
const content = safeRead(rootMd);
|
|
@@ -10320,7 +10478,7 @@ function scanClaude(repoRoot2) {
|
|
|
10320
10478
|
}
|
|
10321
10479
|
}
|
|
10322
10480
|
const claudeDir = join36(repoRoot2, ".claude");
|
|
10323
|
-
if (
|
|
10481
|
+
if (existsSync37(claudeDir)) {
|
|
10324
10482
|
try {
|
|
10325
10483
|
for (const entry of walkDir(claudeDir, 3)) {
|
|
10326
10484
|
if (!entry.endsWith(".md") && !entry.endsWith(".json") && !entry.endsWith(".txt")) continue;
|
|
@@ -10365,7 +10523,7 @@ function scanClaude(repoRoot2) {
|
|
|
10365
10523
|
}
|
|
10366
10524
|
function scanAgents(repoRoot2) {
|
|
10367
10525
|
const agentsMd = join36(repoRoot2, "AGENTS.md");
|
|
10368
|
-
if (!
|
|
10526
|
+
if (!existsSync37(agentsMd)) return [];
|
|
10369
10527
|
const meta = fileMeta(agentsMd);
|
|
10370
10528
|
if (!meta) return [];
|
|
10371
10529
|
const content = safeRead(agentsMd);
|
|
@@ -10380,9 +10538,9 @@ function scanAgents(repoRoot2) {
|
|
|
10380
10538
|
function scanCursor(repoRoot2) {
|
|
10381
10539
|
const sources = [];
|
|
10382
10540
|
const cursorDir = join36(repoRoot2, ".cursor");
|
|
10383
|
-
if (!
|
|
10541
|
+
if (!existsSync37(cursorDir)) return sources;
|
|
10384
10542
|
const rulesDir = join36(cursorDir, "rules");
|
|
10385
|
-
if (
|
|
10543
|
+
if (existsSync37(rulesDir)) {
|
|
10386
10544
|
try {
|
|
10387
10545
|
for (const entry of walkDir(rulesDir, 2)) {
|
|
10388
10546
|
if (!entry.endsWith(".mdc") && !entry.endsWith(".md") && !entry.endsWith(".txt")) continue;
|
|
@@ -10404,7 +10562,7 @@ function scanCursor(repoRoot2) {
|
|
|
10404
10562
|
}
|
|
10405
10563
|
}
|
|
10406
10564
|
const cursorrules = join36(repoRoot2, ".cursorrules");
|
|
10407
|
-
if (
|
|
10565
|
+
if (existsSync37(cursorrules)) {
|
|
10408
10566
|
const meta = fileMeta(cursorrules);
|
|
10409
10567
|
if (meta) {
|
|
10410
10568
|
sources.push({
|
|
@@ -10430,7 +10588,7 @@ function extractCursorGlobs(content) {
|
|
|
10430
10588
|
function scanCodex(repoRoot2) {
|
|
10431
10589
|
const sources = [];
|
|
10432
10590
|
const codexMd = join36(repoRoot2, "CODEX.md");
|
|
10433
|
-
if (
|
|
10591
|
+
if (existsSync37(codexMd)) {
|
|
10434
10592
|
const meta = fileMeta(codexMd);
|
|
10435
10593
|
if (meta) {
|
|
10436
10594
|
sources.push({
|
|
@@ -10443,7 +10601,7 @@ function scanCodex(repoRoot2) {
|
|
|
10443
10601
|
}
|
|
10444
10602
|
}
|
|
10445
10603
|
const codexDir = join36(repoRoot2, ".codex");
|
|
10446
|
-
if (
|
|
10604
|
+
if (existsSync37(codexDir)) {
|
|
10447
10605
|
try {
|
|
10448
10606
|
for (const entry of walkDir(codexDir, 2)) {
|
|
10449
10607
|
const meta = fileMeta(entry);
|
|
@@ -10467,7 +10625,7 @@ function scanGeneric(repoRoot2) {
|
|
|
10467
10625
|
const knownFiles = [".github/copilot-instructions.md", "CONTRIBUTING.md"];
|
|
10468
10626
|
for (const rel of knownFiles) {
|
|
10469
10627
|
const full = join36(repoRoot2, rel);
|
|
10470
|
-
if (
|
|
10628
|
+
if (existsSync37(full)) {
|
|
10471
10629
|
const meta = fileMeta(full);
|
|
10472
10630
|
if (meta) {
|
|
10473
10631
|
sources.push({
|
|
@@ -10503,7 +10661,7 @@ function* walkDir(dir, maxDepth, depth = 0) {
|
|
|
10503
10661
|
}
|
|
10504
10662
|
|
|
10505
10663
|
// src/avorelo/capabilities/context-check/classifier.ts
|
|
10506
|
-
import { existsSync as
|
|
10664
|
+
import { existsSync as existsSync38 } from "node:fs";
|
|
10507
10665
|
import { join as join37, dirname as dirname4 } from "node:path";
|
|
10508
10666
|
var OVERSIZE_WARNING_TOKENS = 8e3;
|
|
10509
10667
|
var OVERSIZE_ATTENTION_TOKENS = 25e3;
|
|
@@ -10529,7 +10687,7 @@ function checkBrokenReferences(src, repoRoot2) {
|
|
|
10529
10687
|
for (const ref of src.references) {
|
|
10530
10688
|
const resolvedPath = join37(repoRoot2, dirname4(src.path), ref);
|
|
10531
10689
|
const resolvedFromRoot = join37(repoRoot2, ref);
|
|
10532
|
-
if (!
|
|
10690
|
+
if (!existsSync38(resolvedPath) && !existsSync38(resolvedFromRoot)) {
|
|
10533
10691
|
findings.push({
|
|
10534
10692
|
code: "BROKEN_CONTEXT_REFERENCE",
|
|
10535
10693
|
severity: "warning",
|
|
@@ -10586,7 +10744,7 @@ function checkRuleMatchesNoFiles(src, repoRoot2) {
|
|
|
10586
10744
|
for (const glob of src.appliesToPaths) {
|
|
10587
10745
|
if (glob.includes("*")) continue;
|
|
10588
10746
|
const target = join37(repoRoot2, glob);
|
|
10589
|
-
if (!
|
|
10747
|
+
if (!existsSync38(target)) {
|
|
10590
10748
|
return [{
|
|
10591
10749
|
code: "RULE_MATCHES_NO_FILES",
|
|
10592
10750
|
severity: "info",
|
|
@@ -10984,6 +11142,477 @@ function buildSummary(status, sourceCount, findingCount) {
|
|
|
10984
11142
|
|
|
10985
11143
|
// src/avorelo/capabilities/runtime-flow/index.ts
|
|
10986
11144
|
init_redaction();
|
|
11145
|
+
|
|
11146
|
+
// src/avorelo/kernel/work-controls/index.ts
|
|
11147
|
+
var BUILTIN_CONTROLS = [
|
|
11148
|
+
{
|
|
11149
|
+
controlId: "secrets_guard",
|
|
11150
|
+
title: "Secrets Guard",
|
|
11151
|
+
purpose: "Block tasks, commands, syncs, and receipts that would leak secrets or env values.",
|
|
11152
|
+
enforcementPoints: ["before_task_start", "before_shell_command", "before_secret_or_env_access", "before_cloud_sync", "before_receipt_finalize"],
|
|
11153
|
+
defaultState: "enabled",
|
|
11154
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11155
|
+
localOnlyBehavior: "Detects secret and env exposure locally, returns coded findings only, never persists raw values.",
|
|
11156
|
+
cloudBehavior: "Never allows raw secret or env material into sync payloads.",
|
|
11157
|
+
dataPersisted: ["reason codes", "redaction classes", "safe next actions"],
|
|
11158
|
+
testsRequired: ["no raw env persistence", "no secret printing", "DENY short-circuit"],
|
|
11159
|
+
uiCopy: "Block secret or env leakage."
|
|
11160
|
+
},
|
|
11161
|
+
{
|
|
11162
|
+
controlId: "scope_drift_guard",
|
|
11163
|
+
title: "Scope Drift Guard",
|
|
11164
|
+
purpose: "Stop broad or out-of-scope work before it silently expands.",
|
|
11165
|
+
enforcementPoints: ["before_task_start", "before_file_write"],
|
|
11166
|
+
defaultState: "enabled",
|
|
11167
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11168
|
+
localOnlyBehavior: "Uses route and write-scope metadata only.",
|
|
11169
|
+
cloudBehavior: "Only safe scope codes may be synced.",
|
|
11170
|
+
dataPersisted: ["reason codes", "triggered control id"],
|
|
11171
|
+
testsRequired: ["ASK for broad scope", "DENY for out-of-scope writes"],
|
|
11172
|
+
uiCopy: "Stop scope drift before it spreads."
|
|
11173
|
+
},
|
|
11174
|
+
{
|
|
11175
|
+
controlId: "risky_action_approval",
|
|
11176
|
+
title: "Risky Action Approval",
|
|
11177
|
+
purpose: "Ask before risky work starts when the routed task already requires confirmation or manual review.",
|
|
11178
|
+
enforcementPoints: ["before_task_start"],
|
|
11179
|
+
defaultState: "enabled",
|
|
11180
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11181
|
+
localOnlyBehavior: "Maps current route/risk/proof metadata to a clear ASK verdict.",
|
|
11182
|
+
cloudBehavior: "Only approval-required state may be synced, never task content.",
|
|
11183
|
+
dataPersisted: ["verdict", "reason codes", "approval-required flag"],
|
|
11184
|
+
testsRequired: ["ASK requires explicit approval", "approval clears ASK but not DENY"],
|
|
11185
|
+
uiCopy: "Ask before risky actions."
|
|
11186
|
+
},
|
|
11187
|
+
{
|
|
11188
|
+
controlId: "shell_command_approval",
|
|
11189
|
+
title: "Shell Command Approval",
|
|
11190
|
+
purpose: "Ask before risky shell commands and deny obviously destructive ones.",
|
|
11191
|
+
enforcementPoints: ["before_shell_command"],
|
|
11192
|
+
defaultState: "enabled",
|
|
11193
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11194
|
+
localOnlyBehavior: "Evaluates the command string locally and never stores terminal output.",
|
|
11195
|
+
cloudBehavior: "Only coded gate outcomes may sync.",
|
|
11196
|
+
dataPersisted: ["reason codes", "verdict"],
|
|
11197
|
+
testsRequired: ["ASK for risky commands", "DENY for destructive commands"],
|
|
11198
|
+
uiCopy: "Ask before risky shell commands."
|
|
11199
|
+
},
|
|
11200
|
+
{
|
|
11201
|
+
controlId: "file_write_approval",
|
|
11202
|
+
title: "File Write Approval",
|
|
11203
|
+
purpose: "Require confirmation before sensitive file writes.",
|
|
11204
|
+
enforcementPoints: ["before_file_write"],
|
|
11205
|
+
defaultState: "enabled",
|
|
11206
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11207
|
+
localOnlyBehavior: "Uses path classification only, not file contents.",
|
|
11208
|
+
cloudBehavior: "Only write gate metadata may sync.",
|
|
11209
|
+
dataPersisted: ["reason codes", "verdict"],
|
|
11210
|
+
testsRequired: ["ASK for sensitive writes"],
|
|
11211
|
+
uiCopy: "Ask before sensitive file writes."
|
|
11212
|
+
},
|
|
11213
|
+
{
|
|
11214
|
+
controlId: "dependency_install_approval",
|
|
11215
|
+
title: "Dependency Install Approval",
|
|
11216
|
+
purpose: "Pause before package installs or dependency changes.",
|
|
11217
|
+
enforcementPoints: ["before_dependency_install", "before_shell_command"],
|
|
11218
|
+
defaultState: "enabled",
|
|
11219
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11220
|
+
localOnlyBehavior: "Uses command metadata only.",
|
|
11221
|
+
cloudBehavior: "Only approval-required metadata may sync.",
|
|
11222
|
+
dataPersisted: ["reason codes", "verdict"],
|
|
11223
|
+
testsRequired: ["ASK for dependency install"],
|
|
11224
|
+
uiCopy: "Ask before dependency installs."
|
|
11225
|
+
},
|
|
11226
|
+
{
|
|
11227
|
+
controlId: "release_guard",
|
|
11228
|
+
title: "Release Guard",
|
|
11229
|
+
purpose: "Require explicit approval before package publish or release tagging.",
|
|
11230
|
+
enforcementPoints: ["before_package_publish", "before_release_tag", "before_task_start"],
|
|
11231
|
+
defaultState: "enabled",
|
|
11232
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11233
|
+
localOnlyBehavior: "Evaluates release intent locally and records approval state.",
|
|
11234
|
+
cloudBehavior: "Only release gate receipts may sync.",
|
|
11235
|
+
dataPersisted: ["verdict", "reason codes", "approval-required flag"],
|
|
11236
|
+
testsRequired: ["ASK for publish", "ASK for release tag"],
|
|
11237
|
+
uiCopy: "Prevent publish or release without approval."
|
|
11238
|
+
},
|
|
11239
|
+
{
|
|
11240
|
+
controlId: "production_deploy_guard",
|
|
11241
|
+
title: "Production Deploy Guard",
|
|
11242
|
+
purpose: "Escalate production-impacting work beyond a normal ASK.",
|
|
11243
|
+
enforcementPoints: ["before_production_deploy", "before_task_start"],
|
|
11244
|
+
defaultState: "enabled",
|
|
11245
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11246
|
+
localOnlyBehavior: "Records the stronger approval requirement locally.",
|
|
11247
|
+
cloudBehavior: "Only coded escalation metadata may sync.",
|
|
11248
|
+
dataPersisted: ["verdict", "reason codes", "approval-required flag"],
|
|
11249
|
+
testsRequired: ["ESCALATE for production deploy without stronger approval"],
|
|
11250
|
+
uiCopy: "Require stronger approval for production deploys."
|
|
11251
|
+
},
|
|
11252
|
+
{
|
|
11253
|
+
controlId: "proof_required_before_done",
|
|
11254
|
+
title: "Proof Required Before Done",
|
|
11255
|
+
purpose: "Block done claims until outcome and post-action proof exist.",
|
|
11256
|
+
enforcementPoints: ["after_agent_claims_done", "before_receipt_finalize", "before_test_claim"],
|
|
11257
|
+
defaultState: "enabled",
|
|
11258
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11259
|
+
localOnlyBehavior: "Checks proof metadata only; never stores raw test logs or diffs.",
|
|
11260
|
+
cloudBehavior: "Only proof status may sync.",
|
|
11261
|
+
dataPersisted: ["proof-required flag", "reason codes", "safe next actions"],
|
|
11262
|
+
testsRequired: ["REQUIRE_PROOF without evidence", "proof gate deterministic"],
|
|
11263
|
+
uiCopy: "Require proof before done."
|
|
11264
|
+
},
|
|
11265
|
+
{
|
|
11266
|
+
controlId: "raw_payload_upload_guard",
|
|
11267
|
+
title: "Raw Prompt/Source/Diff Upload Guard",
|
|
11268
|
+
purpose: "Deny cloud sync when raw prompt, source, diff, env, terminal, or secret payloads are present.",
|
|
11269
|
+
enforcementPoints: ["before_cloud_sync"],
|
|
11270
|
+
defaultState: "enabled",
|
|
11271
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11272
|
+
localOnlyBehavior: "Evaluates payload safety flags locally before any sync attempt.",
|
|
11273
|
+
cloudBehavior: "Hard-denies unsafe sync.",
|
|
11274
|
+
dataPersisted: ["reason codes", "verdict"],
|
|
11275
|
+
testsRequired: ["no raw prompt upload", "no raw source upload", "no raw diff upload"],
|
|
11276
|
+
uiCopy: "Receipts, not raw source."
|
|
11277
|
+
},
|
|
11278
|
+
{
|
|
11279
|
+
controlId: "model_worthiness_guard",
|
|
11280
|
+
title: "Model Worthiness Guard",
|
|
11281
|
+
purpose: "Warn when a trivial task is not worth an expensive or deep review path.",
|
|
11282
|
+
enforcementPoints: ["before_task_start"],
|
|
11283
|
+
defaultState: "warn_only",
|
|
11284
|
+
packaging: { free: true, pro: true, teams: true },
|
|
11285
|
+
localOnlyBehavior: "Uses routing/task metadata only.",
|
|
11286
|
+
cloudBehavior: "Only safe warning metadata may sync.",
|
|
11287
|
+
dataPersisted: ["warning reason codes"],
|
|
11288
|
+
testsRequired: ["WARN for trivial task with expensive model request"],
|
|
11289
|
+
uiCopy: "Warn when deep review is not worth it."
|
|
11290
|
+
}
|
|
11291
|
+
];
|
|
11292
|
+
var CONTROL_BY_ID = new Map(BUILTIN_CONTROLS.map((control) => [control.controlId, control]));
|
|
11293
|
+
var VERDICT_PRECEDENCE = [
|
|
11294
|
+
"DENY",
|
|
11295
|
+
"ESCALATE",
|
|
11296
|
+
"ASK",
|
|
11297
|
+
"REQUIRE_PROOF",
|
|
11298
|
+
"WARN",
|
|
11299
|
+
"ALLOW",
|
|
11300
|
+
"NOOP"
|
|
11301
|
+
];
|
|
11302
|
+
var DESTRUCTIVE_SHELL_RE = /\b(rm\s+-rf|del\s+\/s|drop\s+table|git\s+push\s+--force|mkfs|dd\s+if=)\b/i;
|
|
11303
|
+
var RISKY_SHELL_RE = /\b(npm\s+publish|git\s+tag|railway|netlify|vercel|docker\s+push|kubectl|terraform\s+apply)\b/i;
|
|
11304
|
+
var DEPENDENCY_INSTALL_RE = /\b(npm|pnpm|yarn|bun)\s+(install|add)\b/i;
|
|
11305
|
+
function hasRawPayload(ctx) {
|
|
11306
|
+
return !!(ctx.containsRawPrompt || ctx.containsRawSource || ctx.containsRawSecret || ctx.containsEnvValue || ctx.containsGitDiff || ctx.containsTerminalLog);
|
|
11307
|
+
}
|
|
11308
|
+
function hasProof(ctx) {
|
|
11309
|
+
const levels = ctx.evidenceLevels ?? [];
|
|
11310
|
+
return levels.includes("OUTCOME") && levels.includes("POST_ACTION");
|
|
11311
|
+
}
|
|
11312
|
+
function buildTrigger(controlId, enforcementPoint, verdict, reason, reasonCodes, nextAction) {
|
|
11313
|
+
const def = CONTROL_BY_ID.get(controlId);
|
|
11314
|
+
return {
|
|
11315
|
+
controlId,
|
|
11316
|
+
title: def.title,
|
|
11317
|
+
verdict,
|
|
11318
|
+
enforcementPoint,
|
|
11319
|
+
reason,
|
|
11320
|
+
reasonCodes,
|
|
11321
|
+
nextAction
|
|
11322
|
+
};
|
|
11323
|
+
}
|
|
11324
|
+
function evaluateSecretsGuard(point, ctx) {
|
|
11325
|
+
if (point === "before_cloud_sync" && hasRawPayload(ctx)) {
|
|
11326
|
+
return buildTrigger(
|
|
11327
|
+
"raw_payload_upload_guard",
|
|
11328
|
+
point,
|
|
11329
|
+
"DENY",
|
|
11330
|
+
"Cloud sync is blocked because the payload still contains raw prompt, source, diff, secret, env, or terminal data.",
|
|
11331
|
+
["RAW_PAYLOAD_BLOCKED"],
|
|
11332
|
+
"Redact the payload and sync metadata only."
|
|
11333
|
+
);
|
|
11334
|
+
}
|
|
11335
|
+
if (ctx.safeRunDecision === "block" || ctx.containsRawSecret || ctx.containsEnvValue) {
|
|
11336
|
+
return buildTrigger(
|
|
11337
|
+
"secrets_guard",
|
|
11338
|
+
point,
|
|
11339
|
+
"DENY",
|
|
11340
|
+
"This action would expose secret or env material beyond Avorelo's trust boundary.",
|
|
11341
|
+
["SECRET_OR_ENV_EXPOSURE"],
|
|
11342
|
+
"Remove the secret/env access, rotate if needed, and retry with safe references only."
|
|
11343
|
+
);
|
|
11344
|
+
}
|
|
11345
|
+
return null;
|
|
11346
|
+
}
|
|
11347
|
+
function evaluateScopeGuard(point, ctx) {
|
|
11348
|
+
if (point === "before_file_write" && ctx.outOfScopeWrite) {
|
|
11349
|
+
return buildTrigger(
|
|
11350
|
+
"scope_drift_guard",
|
|
11351
|
+
point,
|
|
11352
|
+
"DENY",
|
|
11353
|
+
"The requested write is outside the approved work scope.",
|
|
11354
|
+
["OUT_OF_SCOPE_WRITE"],
|
|
11355
|
+
"Narrow the task or explicitly approve the additional scope before writing."
|
|
11356
|
+
);
|
|
11357
|
+
}
|
|
11358
|
+
if (point === "before_task_start" && ctx.route === "needs_decision") {
|
|
11359
|
+
return buildTrigger(
|
|
11360
|
+
"scope_drift_guard",
|
|
11361
|
+
point,
|
|
11362
|
+
"ASK",
|
|
11363
|
+
"The task scope is too broad or ambiguous to start safely without a confirmation step.",
|
|
11364
|
+
["SCOPE_CONFIRMATION_REQUIRED"],
|
|
11365
|
+
"Clarify the scope, target files, or success criteria before continuing."
|
|
11366
|
+
);
|
|
11367
|
+
}
|
|
11368
|
+
return null;
|
|
11369
|
+
}
|
|
11370
|
+
function evaluateRiskyActionApproval(point, ctx) {
|
|
11371
|
+
if (point !== "before_task_start") return null;
|
|
11372
|
+
if (ctx.approvalPolicy === "require_confirmation" || ctx.approvalPolicy === "require_manual_review") {
|
|
11373
|
+
if (ctx.userApproved) {
|
|
11374
|
+
return buildTrigger(
|
|
11375
|
+
"risky_action_approval",
|
|
11376
|
+
point,
|
|
11377
|
+
"ALLOW",
|
|
11378
|
+
"The risky action had an explicit approval, so Avorelo can proceed without weakening safety.",
|
|
11379
|
+
["RISKY_ACTION_APPROVED"],
|
|
11380
|
+
null
|
|
11381
|
+
);
|
|
11382
|
+
}
|
|
11383
|
+
return buildTrigger(
|
|
11384
|
+
"risky_action_approval",
|
|
11385
|
+
point,
|
|
11386
|
+
"ASK",
|
|
11387
|
+
"This task has enough risk that it needs an explicit approval before work starts.",
|
|
11388
|
+
["RISKY_ACTION_APPROVAL_REQUIRED"],
|
|
11389
|
+
"Confirm the risky action before continuing."
|
|
11390
|
+
);
|
|
11391
|
+
}
|
|
11392
|
+
return null;
|
|
11393
|
+
}
|
|
11394
|
+
function evaluateShellCommand(point, ctx) {
|
|
11395
|
+
if (point !== "before_shell_command" || !ctx.command) return null;
|
|
11396
|
+
if (DESTRUCTIVE_SHELL_RE.test(ctx.command)) {
|
|
11397
|
+
return buildTrigger(
|
|
11398
|
+
"shell_command_approval",
|
|
11399
|
+
point,
|
|
11400
|
+
"DENY",
|
|
11401
|
+
"The shell command is destructive enough that Avorelo blocks it by default.",
|
|
11402
|
+
["DESTRUCTIVE_SHELL_COMMAND"],
|
|
11403
|
+
"Use a safer command or get the destructive step handled outside the automated flow."
|
|
11404
|
+
);
|
|
11405
|
+
}
|
|
11406
|
+
if (ctx.dependencyInstallRequested || DEPENDENCY_INSTALL_RE.test(ctx.command)) {
|
|
11407
|
+
if (ctx.userApproved) {
|
|
11408
|
+
return buildTrigger(
|
|
11409
|
+
"dependency_install_approval",
|
|
11410
|
+
point,
|
|
11411
|
+
"ALLOW",
|
|
11412
|
+
"The dependency install had explicit approval.",
|
|
11413
|
+
["DEPENDENCY_INSTALL_APPROVED"],
|
|
11414
|
+
null
|
|
11415
|
+
);
|
|
11416
|
+
}
|
|
11417
|
+
return buildTrigger(
|
|
11418
|
+
"dependency_install_approval",
|
|
11419
|
+
point,
|
|
11420
|
+
"ASK",
|
|
11421
|
+
"Dependency installation is paused until the user explicitly approves it.",
|
|
11422
|
+
["DEPENDENCY_INSTALL_APPROVAL_REQUIRED"],
|
|
11423
|
+
"Approve the dependency install, or use the existing lockfile and local dependencies only."
|
|
11424
|
+
);
|
|
11425
|
+
}
|
|
11426
|
+
if (RISKY_SHELL_RE.test(ctx.command)) {
|
|
11427
|
+
if (ctx.userApproved) {
|
|
11428
|
+
return buildTrigger(
|
|
11429
|
+
"shell_command_approval",
|
|
11430
|
+
point,
|
|
11431
|
+
"ALLOW",
|
|
11432
|
+
"The risky shell command had explicit approval.",
|
|
11433
|
+
["SHELL_COMMAND_APPROVED"],
|
|
11434
|
+
null
|
|
11435
|
+
);
|
|
11436
|
+
}
|
|
11437
|
+
return buildTrigger(
|
|
11438
|
+
"shell_command_approval",
|
|
11439
|
+
point,
|
|
11440
|
+
"ASK",
|
|
11441
|
+
"This shell command can change external or release state and needs explicit approval.",
|
|
11442
|
+
["SHELL_COMMAND_APPROVAL_REQUIRED"],
|
|
11443
|
+
"Approve the shell command before continuing."
|
|
11444
|
+
);
|
|
11445
|
+
}
|
|
11446
|
+
return null;
|
|
11447
|
+
}
|
|
11448
|
+
function evaluateFileWrite(point, ctx) {
|
|
11449
|
+
if (point !== "before_file_write" || !ctx.sensitiveFilePath) return null;
|
|
11450
|
+
if (ctx.userApproved) {
|
|
11451
|
+
return buildTrigger(
|
|
11452
|
+
"file_write_approval",
|
|
11453
|
+
point,
|
|
11454
|
+
"ALLOW",
|
|
11455
|
+
"The sensitive file write had explicit approval.",
|
|
11456
|
+
["FILE_WRITE_APPROVED"],
|
|
11457
|
+
null
|
|
11458
|
+
);
|
|
11459
|
+
}
|
|
11460
|
+
return buildTrigger(
|
|
11461
|
+
"file_write_approval",
|
|
11462
|
+
point,
|
|
11463
|
+
"ASK",
|
|
11464
|
+
"This write touches a sensitive surface and needs confirmation first.",
|
|
11465
|
+
["SENSITIVE_FILE_WRITE_APPROVAL_REQUIRED"],
|
|
11466
|
+
"Approve the write or narrow the task to a non-sensitive path."
|
|
11467
|
+
);
|
|
11468
|
+
}
|
|
11469
|
+
function evaluateRelease(point, ctx) {
|
|
11470
|
+
if (point === "before_task_start" && ctx.productionImpact) {
|
|
11471
|
+
if (ctx.adminApproved || ctx.teamApproved) {
|
|
11472
|
+
return buildTrigger(
|
|
11473
|
+
"production_deploy_guard",
|
|
11474
|
+
point,
|
|
11475
|
+
"ALLOW",
|
|
11476
|
+
"The production-impacting task has stronger approval coverage.",
|
|
11477
|
+
["PRODUCTION_APPROVED"],
|
|
11478
|
+
null
|
|
11479
|
+
);
|
|
11480
|
+
}
|
|
11481
|
+
return buildTrigger(
|
|
11482
|
+
"production_deploy_guard",
|
|
11483
|
+
point,
|
|
11484
|
+
"ESCALATE",
|
|
11485
|
+
"Production-impacting work needs stronger approval than a normal ASK.",
|
|
11486
|
+
["PRODUCTION_ESCALATION_REQUIRED"],
|
|
11487
|
+
"Get stronger approval before changing production-facing state."
|
|
11488
|
+
);
|
|
11489
|
+
}
|
|
11490
|
+
if (point === "before_package_publish" || point === "before_release_tag") {
|
|
11491
|
+
if (ctx.userApproved) {
|
|
11492
|
+
return buildTrigger(
|
|
11493
|
+
"release_guard",
|
|
11494
|
+
point,
|
|
11495
|
+
"ALLOW",
|
|
11496
|
+
"The release step has explicit approval.",
|
|
11497
|
+
["RELEASE_APPROVED"],
|
|
11498
|
+
null
|
|
11499
|
+
);
|
|
11500
|
+
}
|
|
11501
|
+
return buildTrigger(
|
|
11502
|
+
"release_guard",
|
|
11503
|
+
point,
|
|
11504
|
+
"ASK",
|
|
11505
|
+
"Package publish and release tagging stay paused until explicitly approved.",
|
|
11506
|
+
["RELEASE_APPROVAL_REQUIRED"],
|
|
11507
|
+
"Approve the release step before continuing."
|
|
11508
|
+
);
|
|
11509
|
+
}
|
|
11510
|
+
if (point === "before_production_deploy") {
|
|
11511
|
+
if (ctx.adminApproved || ctx.teamApproved) {
|
|
11512
|
+
return buildTrigger(
|
|
11513
|
+
"production_deploy_guard",
|
|
11514
|
+
point,
|
|
11515
|
+
"ALLOW",
|
|
11516
|
+
"The production deploy has stronger approval coverage.",
|
|
11517
|
+
["PRODUCTION_APPROVED"],
|
|
11518
|
+
null
|
|
11519
|
+
);
|
|
11520
|
+
}
|
|
11521
|
+
return buildTrigger(
|
|
11522
|
+
"production_deploy_guard",
|
|
11523
|
+
point,
|
|
11524
|
+
"ESCALATE",
|
|
11525
|
+
"Production deploys need stronger approval than a normal ASK.",
|
|
11526
|
+
["PRODUCTION_ESCALATION_REQUIRED"],
|
|
11527
|
+
"Get the stronger production approval before deploying."
|
|
11528
|
+
);
|
|
11529
|
+
}
|
|
11530
|
+
return null;
|
|
11531
|
+
}
|
|
11532
|
+
function evaluateProof(point, ctx) {
|
|
11533
|
+
if (point !== "after_agent_claims_done" && point !== "before_receipt_finalize" && point !== "before_test_claim") return null;
|
|
11534
|
+
if (!ctx.agentClaimsDone) return null;
|
|
11535
|
+
if (hasProof(ctx)) {
|
|
11536
|
+
return buildTrigger(
|
|
11537
|
+
"proof_required_before_done",
|
|
11538
|
+
point,
|
|
11539
|
+
"ALLOW",
|
|
11540
|
+
"Outcome and post-action evidence are present, so the done claim can stand.",
|
|
11541
|
+
["PROOF_PRESENT"],
|
|
11542
|
+
null
|
|
11543
|
+
);
|
|
11544
|
+
}
|
|
11545
|
+
return buildTrigger(
|
|
11546
|
+
"proof_required_before_done",
|
|
11547
|
+
point,
|
|
11548
|
+
"REQUIRE_PROOF",
|
|
11549
|
+
"The agent claimed done before outcome and post-action proof existed.",
|
|
11550
|
+
["PROOF_REQUIRED_BEFORE_DONE"],
|
|
11551
|
+
"Run the missing verification and attach outcome plus post-action evidence before marking done."
|
|
11552
|
+
);
|
|
11553
|
+
}
|
|
11554
|
+
function evaluateModelWorthiness(point, ctx) {
|
|
11555
|
+
if (point !== "before_task_start") return null;
|
|
11556
|
+
if (!ctx.expensiveModelRequested || !ctx.taskSeemsTrivial) return null;
|
|
11557
|
+
return buildTrigger(
|
|
11558
|
+
"model_worthiness_guard",
|
|
11559
|
+
point,
|
|
11560
|
+
"WARN",
|
|
11561
|
+
"This task looks trivial relative to the requested review depth.",
|
|
11562
|
+
["MODEL_WORTHINESS_WARN"],
|
|
11563
|
+
"Use a lighter-weight path unless deeper review is actually needed."
|
|
11564
|
+
);
|
|
11565
|
+
}
|
|
11566
|
+
function finalVerdict(triggers) {
|
|
11567
|
+
if (triggers.length === 0) return "NOOP";
|
|
11568
|
+
for (const verdict of VERDICT_PRECEDENCE) {
|
|
11569
|
+
if (triggers.some((trigger) => trigger.verdict === verdict)) return verdict;
|
|
11570
|
+
}
|
|
11571
|
+
return "NOOP";
|
|
11572
|
+
}
|
|
11573
|
+
function listWorkControls() {
|
|
11574
|
+
return BUILTIN_CONTROLS.map((control) => ({ ...control, enforcementPoints: [...control.enforcementPoints], packaging: { ...control.packaging }, dataPersisted: [...control.dataPersisted], testsRequired: [...control.testsRequired] }));
|
|
11575
|
+
}
|
|
11576
|
+
function getWorkControl(controlId) {
|
|
11577
|
+
const found = CONTROL_BY_ID.get(controlId);
|
|
11578
|
+
if (!found) return null;
|
|
11579
|
+
return {
|
|
11580
|
+
...found,
|
|
11581
|
+
enforcementPoints: [...found.enforcementPoints],
|
|
11582
|
+
packaging: { ...found.packaging },
|
|
11583
|
+
dataPersisted: [...found.dataPersisted],
|
|
11584
|
+
testsRequired: [...found.testsRequired]
|
|
11585
|
+
};
|
|
11586
|
+
}
|
|
11587
|
+
function evaluateWorkControls(enforcementPoint, ctx) {
|
|
11588
|
+
const triggers = [
|
|
11589
|
+
evaluateSecretsGuard(enforcementPoint, ctx),
|
|
11590
|
+
evaluateScopeGuard(enforcementPoint, ctx),
|
|
11591
|
+
evaluateRiskyActionApproval(enforcementPoint, ctx),
|
|
11592
|
+
evaluateShellCommand(enforcementPoint, ctx),
|
|
11593
|
+
evaluateFileWrite(enforcementPoint, ctx),
|
|
11594
|
+
evaluateRelease(enforcementPoint, ctx),
|
|
11595
|
+
evaluateProof(enforcementPoint, ctx),
|
|
11596
|
+
evaluateModelWorthiness(enforcementPoint, ctx)
|
|
11597
|
+
].filter((trigger) => trigger !== null);
|
|
11598
|
+
const verdict = finalVerdict(triggers);
|
|
11599
|
+
const reasonCodes = Array.from(new Set(triggers.flatMap((trigger) => trigger.reasonCodes)));
|
|
11600
|
+
const safeNextActions = Array.from(new Set(triggers.map((trigger) => trigger.nextAction).filter((value) => typeof value === "string" && value.length > 0)));
|
|
11601
|
+
const blockingTrigger = triggers.find((trigger) => trigger.verdict === verdict) ?? null;
|
|
11602
|
+
return {
|
|
11603
|
+
enforcementPoint,
|
|
11604
|
+
finalVerdict: verdict,
|
|
11605
|
+
finalReason: blockingTrigger?.reason ?? "No relevant work control fired.",
|
|
11606
|
+
reasonCodes,
|
|
11607
|
+
approvalRequired: triggers.some((trigger) => trigger.verdict === "ASK" || trigger.verdict === "ESCALATE"),
|
|
11608
|
+
proofRequired: triggers.some((trigger) => trigger.verdict === "REQUIRE_PROOF"),
|
|
11609
|
+
triggers,
|
|
11610
|
+
safeNextActions,
|
|
11611
|
+
deterministic: true
|
|
11612
|
+
};
|
|
11613
|
+
}
|
|
11614
|
+
|
|
11615
|
+
// src/avorelo/capabilities/runtime-flow/index.ts
|
|
10987
11616
|
function runtimeDir(dir) {
|
|
10988
11617
|
return join39(dir, ".avorelo", "runtime");
|
|
10989
11618
|
}
|
|
@@ -11018,6 +11647,22 @@ function safeFallbackProjection(reasonCodes, extraVerifierPlan = []) {
|
|
|
11018
11647
|
containsRawSecret: false
|
|
11019
11648
|
};
|
|
11020
11649
|
}
|
|
11650
|
+
function toRuntimeWorkControls(evaluation) {
|
|
11651
|
+
return {
|
|
11652
|
+
enforcementPoint: evaluation.enforcementPoint,
|
|
11653
|
+
finalVerdict: evaluation.finalVerdict,
|
|
11654
|
+
finalReason: evaluation.finalReason,
|
|
11655
|
+
reasonCodes: evaluation.reasonCodes,
|
|
11656
|
+
approvalRequired: evaluation.approvalRequired,
|
|
11657
|
+
proofRequired: evaluation.proofRequired,
|
|
11658
|
+
triggeredControls: evaluation.triggers.map((trigger) => ({
|
|
11659
|
+
controlId: trigger.controlId,
|
|
11660
|
+
verdict: trigger.verdict,
|
|
11661
|
+
reasonCodes: trigger.reasonCodes
|
|
11662
|
+
})),
|
|
11663
|
+
safeNextActions: evaluation.safeNextActions
|
|
11664
|
+
};
|
|
11665
|
+
}
|
|
11021
11666
|
function freshRuntimeId(seed) {
|
|
11022
11667
|
return "rts_" + createHash12("sha256").update(seed).digest("hex").slice(0, 12);
|
|
11023
11668
|
}
|
|
@@ -11082,6 +11727,20 @@ function runRuntimeSession(input) {
|
|
|
11082
11727
|
const routing = decideRouting({ task, dir, planTier });
|
|
11083
11728
|
const c = routing.contract;
|
|
11084
11729
|
const displayTask = routing.displayTask;
|
|
11730
|
+
const taskStartControls = evaluateWorkControls("before_task_start", {
|
|
11731
|
+
task: displayTask,
|
|
11732
|
+
planTier,
|
|
11733
|
+
route: c.route,
|
|
11734
|
+
riskClass: c.riskClass,
|
|
11735
|
+
proofTier: c.proofTier,
|
|
11736
|
+
approvalPolicy: c.approvalPolicy,
|
|
11737
|
+
safeRunDecision: c.safetyBoundary.safeRunDecision,
|
|
11738
|
+
secretRiskCodes: c.safetyBoundary.secretRiskCodes,
|
|
11739
|
+
userApproved: routing.gate === "allow",
|
|
11740
|
+
productionImpact: /deploy|release|publish|production|prod/i.test(displayTask),
|
|
11741
|
+
taskSeemsTrivial: c.route === "deterministic_only" && c.riskClass === "low",
|
|
11742
|
+
expensiveModelRequested: c.route === "deep_reasoning_required"
|
|
11743
|
+
});
|
|
11085
11744
|
const layers = [{
|
|
11086
11745
|
order: 1,
|
|
11087
11746
|
layer: "safety_and_routing",
|
|
@@ -11109,6 +11768,7 @@ function runRuntimeSession(input) {
|
|
|
11109
11768
|
safeRunDecision: c.safetyBoundary.safeRunDecision,
|
|
11110
11769
|
secretRiskCodes: c.safetyBoundary.secretRiskCodes ?? []
|
|
11111
11770
|
},
|
|
11771
|
+
workControls: toRuntimeWorkControls(taskStartControls),
|
|
11112
11772
|
layers,
|
|
11113
11773
|
redacted: true,
|
|
11114
11774
|
containsRawSecret: false,
|
|
@@ -11653,7 +12313,7 @@ function writeRuntimeSession(dir, record) {
|
|
|
11653
12313
|
}
|
|
11654
12314
|
function loadLatestRuntimeSession(dir) {
|
|
11655
12315
|
const path = join39(runtimeDir(dir), "session.latest.json");
|
|
11656
|
-
if (!
|
|
12316
|
+
if (!existsSync39(path)) return null;
|
|
11657
12317
|
try {
|
|
11658
12318
|
return JSON.parse(readFileSync23(path, "utf8"));
|
|
11659
12319
|
} catch {
|
|
@@ -11673,6 +12333,8 @@ function buildRuntimeSessionSyncMetadata(record) {
|
|
|
11673
12333
|
riskClass: record.riskClass,
|
|
11674
12334
|
proofTier: record.proofTier,
|
|
11675
12335
|
approvalPolicy: record.approvalPolicy,
|
|
12336
|
+
workControlVerdict: record.workControls.finalVerdict,
|
|
12337
|
+
workControlTriggerCount: record.workControls.triggeredControls.length,
|
|
11676
12338
|
layerStatuses,
|
|
11677
12339
|
secretRiskCodes: record.safetyBoundary.secretRiskCodes,
|
|
11678
12340
|
canShowSavings: record.proof?.canShowSavings ?? false,
|
|
@@ -11688,6 +12350,8 @@ function validateRuntimeSession(record) {
|
|
|
11688
12350
|
if (record.containsRawSecret !== false) reasons.push("contains_raw_secret");
|
|
11689
12351
|
if (record.containsRawPrompt !== false) reasons.push("contains_raw_prompt");
|
|
11690
12352
|
if (record.containsRawSourceDump !== false) reasons.push("contains_raw_source_dump");
|
|
12353
|
+
if (!record.workControls) reasons.push("work_controls_missing");
|
|
12354
|
+
else if (record.workControls.finalVerdict === "REQUIRE_PROOF" && record.gate === "allow") reasons.push("proof_required_task_started");
|
|
11691
12355
|
if (record.gate === "blocked" && (record.session || record.context || record.continuity || record.tokenCost || record.proof || record.value || record.efficiencySync)) {
|
|
11692
12356
|
reasons.push("blocked_gate_ran_downstream");
|
|
11693
12357
|
}
|
|
@@ -11778,6 +12442,18 @@ function buildControlCenter(dir, opts) {
|
|
|
11778
12442
|
} : { status: "unavailable" };
|
|
11779
12443
|
if (runtime) sources.push(avoreloPath(dir, "runtime", "session.latest.json"));
|
|
11780
12444
|
else notes.push('No runtime session yet \u2014 run `avorelo run "<task>"` to create one.');
|
|
12445
|
+
const workControlsSection = runtime?.workControls ? {
|
|
12446
|
+
status: "available",
|
|
12447
|
+
enforcementPoint: runtime.workControls.enforcementPoint,
|
|
12448
|
+
finalVerdict: runtime.workControls.finalVerdict,
|
|
12449
|
+
approvalRequired: runtime.workControls.approvalRequired,
|
|
12450
|
+
proofRequired: runtime.workControls.proofRequired,
|
|
12451
|
+
triggeredCount: runtime.workControls.triggeredControls.length,
|
|
12452
|
+
controls: runtime.workControls.triggeredControls.map((control) => ({
|
|
12453
|
+
controlId: control.controlId,
|
|
12454
|
+
verdict: control.verdict
|
|
12455
|
+
}))
|
|
12456
|
+
} : { status: "unavailable" };
|
|
11781
12457
|
const contextPackSection = runtime?.contextPack ? {
|
|
11782
12458
|
status: "available",
|
|
11783
12459
|
contextPackId: runtime.contextPack.contextPackId,
|
|
@@ -11836,7 +12512,7 @@ function buildControlCenter(dir, opts) {
|
|
|
11836
12512
|
let contextCheckSection = { status: "unavailable" };
|
|
11837
12513
|
try {
|
|
11838
12514
|
const ccPath = avoreloPath(dir, "context-check", "latest.json");
|
|
11839
|
-
if (
|
|
12515
|
+
if (existsSync40(ccPath)) {
|
|
11840
12516
|
const raw = JSON.parse(readFileSync24(ccPath, "utf8"));
|
|
11841
12517
|
contextCheckSection = {
|
|
11842
12518
|
status: "available",
|
|
@@ -11945,6 +12621,7 @@ function buildControlCenter(dir, opts) {
|
|
|
11945
12621
|
workspace: dir,
|
|
11946
12622
|
sections: {
|
|
11947
12623
|
runtimeSession: runtimeSection,
|
|
12624
|
+
workControls: workControlsSection,
|
|
11948
12625
|
contextPack: contextPackSection,
|
|
11949
12626
|
proof: proofSection,
|
|
11950
12627
|
value: valueSection,
|
|
@@ -11979,6 +12656,7 @@ function renderText2(m) {
|
|
|
11979
12656
|
} else {
|
|
11980
12657
|
lines.push(" Runtime: none yet");
|
|
11981
12658
|
}
|
|
12659
|
+
lines.push(` Controls: ${s.workControls.status === "available" ? `${s.workControls.finalVerdict} at ${s.workControls.enforcementPoint} \xB7 approval=${s.workControls.approvalRequired} \xB7 proof=${s.workControls.proofRequired} \xB7 triggers=${s.workControls.triggeredCount}` : "none"}`);
|
|
11982
12660
|
lines.push(` Ctx pack: ${s.contextPack.status === "available" ? `${s.contextPack.contextPackId} \xB7 consumer=${s.contextPack.consumer} adapter=${s.contextPack.selectedAdapter} \xB7 refs=${s.contextPack.allowedCount}/${s.contextPack.forbiddenCount} blocked \xB7 budget=${s.contextPack.budget} used=${s.contextPack.contextBudgetUsed} \xB7 tags=${s.contextPack.provenanceTagCount}` : "none"}`);
|
|
11983
12661
|
lines.push(` Proof: ${s.proof.status === "available" ? `${s.proof.reportId} \xB7 savings ${s.proof.canShowSavings ? "shown" : `not claimed (${s.proof.savingsRefusalReason ?? "no_comparative_evidence"})`}` : "none"}`);
|
|
11984
12662
|
lines.push(` Token/cost:${s.costEvidence.status === "available" ? ` ${s.costEvidence.confidence} \xB7 costSummary=${s.costEvidence.canShowCostSummary} \xB7 ${s.costEvidence.evidenceCount} item(s)` : " none"}`);
|
|
@@ -12046,6 +12724,7 @@ function renderHtml2(m) {
|
|
|
12046
12724
|
<h1>Avorelo \u2014 Local Control Center</h1>
|
|
12047
12725
|
<table>
|
|
12048
12726
|
${row("Runtime", s.runtimeSession.status === "available" ? `${esc2(s.runtimeSession.sessionStatus)} \xB7 gate=${esc2(s.runtimeSession.gate)} route=${esc2(s.runtimeSession.route)} risk=${esc2(s.runtimeSession.riskClass)} proof=${esc2(s.runtimeSession.proofTier)}<div>${layers}</div>` : '<span class="muted">none yet</span>')}
|
|
12727
|
+
${row("Controls", s.workControls.status === "available" ? `${esc2(s.workControls.finalVerdict)} \xB7 point=${esc2(s.workControls.enforcementPoint)} \xB7 approval=${esc2(s.workControls.approvalRequired)} \xB7 proof=${esc2(s.workControls.proofRequired)} \xB7 triggers=${esc2(s.workControls.triggeredCount)}${(s.workControls.controls ?? []).length ? `<div class="muted">${(s.workControls.controls ?? []).map((c) => `${esc2(c.controlId)}=${esc2(c.verdict)}`).join(" \xB7 ")}</div>` : ""}` : '<span class="muted">none</span>')}
|
|
12049
12728
|
${row("Ctx pack", s.contextPack.status === "available" ? `${esc2(s.contextPack.contextPackId)} \xB7 consumer=${esc2(s.contextPack.consumer)} adapter=${esc2(s.contextPack.selectedAdapter)} \xB7 refs=${esc2(s.contextPack.allowedCount)}/${esc2(s.contextPack.forbiddenCount)} blocked \xB7 budget=${esc2(s.contextPack.budget)} used=${esc2(s.contextPack.contextBudgetUsed)} \xB7 tags=${esc2(s.contextPack.provenanceTagCount)}` : '<span class="muted">none</span>')}
|
|
12050
12729
|
${row("Proof", s.proof.status === "available" ? `${esc2(s.proof.reportId)} \xB7 savings ${s.proof.canShowSavings ? "shown" : `<b>not claimed</b> (${esc2(s.proof.savingsRefusalReason ?? "no_comparative_evidence")})`}` : '<span class="muted">none</span>')}
|
|
12051
12730
|
${row("Token/cost", s.costEvidence.status === "available" ? `${esc2(s.costEvidence.confidence)} \xB7 costSummary=${esc2(s.costEvidence.canShowCostSummary)} \xB7 ${esc2(s.costEvidence.evidenceCount)} item(s)` : '<span class="muted">none</span>')}
|
|
@@ -12071,7 +12750,7 @@ function openControlCenter(dir, opts) {
|
|
|
12071
12750
|
|
|
12072
12751
|
// src/avorelo/capabilities/activation/init.ts
|
|
12073
12752
|
import { createHash as createHash13, randomUUID as randomUUID4 } from "node:crypto";
|
|
12074
|
-
import { existsSync as
|
|
12753
|
+
import { existsSync as existsSync41, mkdirSync as mkdirSync26, writeFileSync as writeFileSync25, readFileSync as readFileSync25, statSync as statSync4, accessSync, constants } from "node:fs";
|
|
12075
12754
|
import { join as join41 } from "node:path";
|
|
12076
12755
|
var ACTIVATION_V1_CONTRACT = "avorelo.activation.v1";
|
|
12077
12756
|
var WORKSPACE_V1_CONTRACT = "avorelo.workspace.v1";
|
|
@@ -12089,7 +12768,7 @@ function freshActivationId(seed) {
|
|
|
12089
12768
|
}
|
|
12090
12769
|
function loadWorkspace(dir) {
|
|
12091
12770
|
const p = workspacePath(dir);
|
|
12092
|
-
if (!
|
|
12771
|
+
if (!existsSync41(p)) return null;
|
|
12093
12772
|
try {
|
|
12094
12773
|
const w = JSON.parse(readFileSync25(p, "utf8"));
|
|
12095
12774
|
return w.contract === WORKSPACE_V1_CONTRACT && typeof w.workspaceId === "string" ? w : null;
|
|
@@ -12114,9 +12793,9 @@ function buildActivationContract(dir, opts) {
|
|
|
12114
12793
|
} catch {
|
|
12115
12794
|
packageManager = null;
|
|
12116
12795
|
}
|
|
12117
|
-
const packageDetected =
|
|
12796
|
+
const packageDetected = existsSync41(join41(dir, "package.json"));
|
|
12118
12797
|
const repoDetected = packageDetected || gitDetected;
|
|
12119
|
-
const avoreloDirReady =
|
|
12798
|
+
const avoreloDirReady = existsSync41(avoreloDir(dir));
|
|
12120
12799
|
const initialized = !!existing;
|
|
12121
12800
|
const firstRunRecommended = !initialized ? { command: `avorelo init --target ${dir}`, reason: "Initialize the local Avorelo workspace first." } : { command: `avorelo run "run tests" --target ${dir}`, reason: "Run your first focused task; Avorelo saves proof locally." };
|
|
12122
12801
|
const limitations = [
|
|
@@ -12151,7 +12830,7 @@ function buildActivationContract(dir, opts) {
|
|
|
12151
12830
|
function initWorkspace(dir, opts) {
|
|
12152
12831
|
const now = opts?.now ?? Date.now();
|
|
12153
12832
|
try {
|
|
12154
|
-
if (!
|
|
12833
|
+
if (!existsSync41(dir)) return { ok: false, created: false, reason: "target_does_not_exist" };
|
|
12155
12834
|
if (!statSync4(dir).isDirectory()) return { ok: false, created: false, reason: "target_not_a_directory" };
|
|
12156
12835
|
} catch {
|
|
12157
12836
|
return { ok: false, created: false, reason: "target_not_accessible" };
|
|
@@ -12291,11 +12970,11 @@ function renderDogfoodCheck(r2) {
|
|
|
12291
12970
|
|
|
12292
12971
|
// src/avorelo/capabilities/core-readiness/index.ts
|
|
12293
12972
|
import { createHash as createHash15 } from "node:crypto";
|
|
12294
|
-
import { existsSync as
|
|
12973
|
+
import { existsSync as existsSync43, readFileSync as readFileSync27 } from "node:fs";
|
|
12295
12974
|
import { join as join43 } from "node:path";
|
|
12296
12975
|
|
|
12297
12976
|
// src/avorelo/capabilities/canonical-readiness/index.ts
|
|
12298
|
-
import { existsSync as
|
|
12977
|
+
import { existsSync as existsSync42, readFileSync as readFileSync26, readdirSync as readdirSync11, statSync as statSync5 } from "node:fs";
|
|
12299
12978
|
import { join as join42 } from "node:path";
|
|
12300
12979
|
import { createHash as createHash14 } from "node:crypto";
|
|
12301
12980
|
var FORBIDDEN_CLAIM_PATTERNS = [
|
|
@@ -12380,7 +13059,7 @@ var OLD_CAP_SPECS = [
|
|
|
12380
13059
|
{ capability: "Seamless Model & Primitive Routing", evidence: ["src/avorelo/kernel/model-routing/index.ts", "src/avorelo/kernel/model-routing/resolver.ts", "src/avorelo/kernel/model-routing/verifier.ts"], status: "adapted", notes: ["Phase 10; deterministic-first cascade, upgrade-only session memory, safety-verified projections"] }
|
|
12381
13060
|
];
|
|
12382
13061
|
function has(root, rel) {
|
|
12383
|
-
return
|
|
13062
|
+
return existsSync42(join42(root, rel));
|
|
12384
13063
|
}
|
|
12385
13064
|
function read(root, rel) {
|
|
12386
13065
|
try {
|
|
@@ -12392,7 +13071,7 @@ function read(root, rel) {
|
|
|
12392
13071
|
function walkFiles(root, rel, exts) {
|
|
12393
13072
|
const out = [];
|
|
12394
13073
|
const base = join42(root, rel);
|
|
12395
|
-
if (!
|
|
13074
|
+
if (!existsSync42(base)) return out;
|
|
12396
13075
|
const rec = (dir) => {
|
|
12397
13076
|
for (const name of readdirSync11(dir)) {
|
|
12398
13077
|
const p = join42(dir, name);
|
|
@@ -12536,7 +13215,7 @@ function repoRoot() {
|
|
|
12536
13215
|
return join43(import.meta.dirname, "..", "..", "..", "..");
|
|
12537
13216
|
}
|
|
12538
13217
|
function has2(root, rel) {
|
|
12539
|
-
return
|
|
13218
|
+
return existsSync43(join43(root, rel));
|
|
12540
13219
|
}
|
|
12541
13220
|
function buildCoreReadiness(opts) {
|
|
12542
13221
|
const now = opts?.now ?? Date.now();
|
|
@@ -12843,18 +13522,18 @@ init_stop_continue_gate();
|
|
|
12843
13522
|
init_state_ledger();
|
|
12844
13523
|
init_receipts();
|
|
12845
13524
|
init_redaction();
|
|
12846
|
-
import { readFileSync as readFileSync28, existsSync as
|
|
13525
|
+
import { readFileSync as readFileSync28, existsSync as existsSync44, statSync as statSync6 } from "node:fs";
|
|
12847
13526
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
12848
13527
|
function readBack(dir, check) {
|
|
12849
13528
|
const id = check.artifactId ?? `sot_${check.kind}`;
|
|
12850
13529
|
const resolve5 = (p) => p.startsWith("/") || /^[A-Za-z]:/.test(p) ? p : `${dir}/${p}`;
|
|
12851
13530
|
try {
|
|
12852
13531
|
if (check.kind === "file_absent") {
|
|
12853
|
-
const passed2 = !
|
|
13532
|
+
const passed2 = !existsSync44(resolve5(check.path));
|
|
12854
13533
|
return { artifact: passed2 ? { artifactId: id, kind: "source_of_truth_readback", ref: `sot:absent:${check.path}` } : null, passed: passed2, reasonCode: passed2 ? "READBACK_ABSENT_OK" : "READBACK_UNEXPECTEDLY_PRESENT", check };
|
|
12855
13534
|
}
|
|
12856
13535
|
const p = resolve5(check.path);
|
|
12857
|
-
if (!
|
|
13536
|
+
if (!existsSync44(p)) return { artifact: null, passed: false, reasonCode: "READBACK_FILE_MISSING", check };
|
|
12858
13537
|
const actual = readFileSync28(p, "utf8");
|
|
12859
13538
|
const passed = check.kind === "file_equals" ? actual.trim() === check.expected.trim() : actual.includes(check.expected);
|
|
12860
13539
|
return { artifact: passed ? { artifactId: id, kind: "source_of_truth_readback", ref: `sot:${check.kind}:${check.path}` } : null, passed, reasonCode: passed ? "READBACK_MATCH" : "READBACK_MISMATCH", check };
|
|
@@ -12877,7 +13556,7 @@ function checkEnvironmentIntegrity(dir, signals) {
|
|
|
12877
13556
|
if (signals?.staleProcess) reasonCodes.push("STALE_PROCESS");
|
|
12878
13557
|
return { compromised: reasonCodes.length > 0, reasonCodes };
|
|
12879
13558
|
}
|
|
12880
|
-
function
|
|
13559
|
+
function evaluateProof2(input) {
|
|
12881
13560
|
const declared = input.artifacts ?? [];
|
|
12882
13561
|
const readbacks = (input.readbacks ?? []).map((c) => readBack(input.dir, c));
|
|
12883
13562
|
const readbackArtifacts = readbacks.map((r2) => r2.artifact).filter((a) => a !== null);
|
|
@@ -12918,7 +13597,7 @@ function evaluateProof(input) {
|
|
|
12918
13597
|
}
|
|
12919
13598
|
function loadProofInput(dir) {
|
|
12920
13599
|
const p = `${dir}/.avorelo/proof-input.json`;
|
|
12921
|
-
if (!
|
|
13600
|
+
if (!existsSync44(p)) return null;
|
|
12922
13601
|
try {
|
|
12923
13602
|
return JSON.parse(readFileSync28(p, "utf8"));
|
|
12924
13603
|
} catch {
|
|
@@ -12927,17 +13606,18 @@ function loadProofInput(dir) {
|
|
|
12927
13606
|
}
|
|
12928
13607
|
|
|
12929
13608
|
// src/avorelo/surfaces/public-web/index.ts
|
|
12930
|
-
import { mkdirSync as mkdirSync27, copyFileSync as copyFileSync2, readdirSync as readdirSync12, existsSync as
|
|
13609
|
+
import { mkdirSync as mkdirSync27, copyFileSync as copyFileSync2, readdirSync as readdirSync12, existsSync as existsSync45 } from "node:fs";
|
|
12931
13610
|
import { join as join44, dirname as dirname5 } from "node:path";
|
|
12932
13611
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
12933
13612
|
var __dirname = dirname5(fileURLToPath2(import.meta.url));
|
|
12934
13613
|
var STATIC_DIR = join44(__dirname, "static");
|
|
12935
13614
|
function buildSite(outDir) {
|
|
12936
13615
|
mkdirSync27(outDir, { recursive: true });
|
|
12937
|
-
if (!
|
|
13616
|
+
if (!existsSync45(STATIC_DIR)) {
|
|
12938
13617
|
return { ok: false, outDir, pages: [], indexPath: "" };
|
|
12939
13618
|
}
|
|
12940
|
-
const
|
|
13619
|
+
const NETLIFY_FILES = ["_redirects", "_headers"];
|
|
13620
|
+
const files = readdirSync12(STATIC_DIR).filter((f) => /\.(html|js|css|png|svg|ico|json|txt|xml|webmanifest)$/.test(f) || NETLIFY_FILES.includes(f));
|
|
12941
13621
|
for (const f of files) {
|
|
12942
13622
|
copyFileSync2(join44(STATIC_DIR, f), join44(outDir, f));
|
|
12943
13623
|
}
|
|
@@ -12951,7 +13631,7 @@ function buildSite(outDir) {
|
|
|
12951
13631
|
|
|
12952
13632
|
// src/avorelo/surfaces/preview-server/index.ts
|
|
12953
13633
|
import { createServer } from "node:http";
|
|
12954
|
-
import { readFileSync as readFileSync29, existsSync as
|
|
13634
|
+
import { readFileSync as readFileSync29, existsSync as existsSync46, statSync as statSync7 } from "node:fs";
|
|
12955
13635
|
import { join as join45, normalize, extname, sep as sep4 } from "node:path";
|
|
12956
13636
|
var MIME = {
|
|
12957
13637
|
".html": "text/html; charset=utf-8",
|
|
@@ -12971,7 +13651,7 @@ function resolveRequestPath(root, urlPath) {
|
|
|
12971
13651
|
const abs = normalize(join45(rootNorm, candidate));
|
|
12972
13652
|
if (abs !== rootNorm && !abs.startsWith(rootNorm.endsWith(sep4) ? rootNorm : rootNorm + sep4)) return null;
|
|
12973
13653
|
try {
|
|
12974
|
-
if (!
|
|
13654
|
+
if (!existsSync46(abs) || !statSync7(abs).isFile()) return null;
|
|
12975
13655
|
} catch {
|
|
12976
13656
|
return null;
|
|
12977
13657
|
}
|
|
@@ -13486,12 +14166,12 @@ init_resume_packet();
|
|
|
13486
14166
|
init_registry();
|
|
13487
14167
|
|
|
13488
14168
|
// src/avorelo/capabilities/update-notice/index.ts
|
|
13489
|
-
import { existsSync as
|
|
14169
|
+
import { existsSync as existsSync47, readFileSync as readFileSync30, writeFileSync as writeFileSync26, mkdirSync as mkdirSync28 } from "node:fs";
|
|
13490
14170
|
import { join as join46, dirname as dirname6 } from "node:path";
|
|
13491
14171
|
var STATE_PATH = ".avorelo/notice-state.json";
|
|
13492
14172
|
function readNoticeState(dir) {
|
|
13493
14173
|
const filePath = join46(dir, STATE_PATH);
|
|
13494
|
-
if (!
|
|
14174
|
+
if (!existsSync47(filePath)) {
|
|
13495
14175
|
return { lastSeenVersion: "", dismissedVersions: [], quietMode: false, lastCheckedAt: "" };
|
|
13496
14176
|
}
|
|
13497
14177
|
try {
|
|
@@ -13503,7 +14183,7 @@ function readNoticeState(dir) {
|
|
|
13503
14183
|
function writeNoticeState(dir, state) {
|
|
13504
14184
|
const filePath = join46(dir, STATE_PATH);
|
|
13505
14185
|
const d = dirname6(filePath);
|
|
13506
|
-
if (!
|
|
14186
|
+
if (!existsSync47(d)) mkdirSync28(d, { recursive: true });
|
|
13507
14187
|
writeFileSync26(filePath, JSON.stringify(state, null, 2));
|
|
13508
14188
|
}
|
|
13509
14189
|
function getCurrentVersion() {
|
|
@@ -13559,7 +14239,7 @@ function getNoticeState(dir) {
|
|
|
13559
14239
|
}
|
|
13560
14240
|
|
|
13561
14241
|
// src/avorelo/capabilities/registry-freshness/index.ts
|
|
13562
|
-
import { existsSync as
|
|
14242
|
+
import { existsSync as existsSync48, readFileSync as readFileSync31, writeFileSync as writeFileSync27, mkdirSync as mkdirSync29 } from "node:fs";
|
|
13563
14243
|
import { join as join47, dirname as dirname7 } from "node:path";
|
|
13564
14244
|
var REGISTRY_FRESHNESS_CONTRACT = "avorelo.registryFreshness.v1";
|
|
13565
14245
|
var CACHE_FILE = ".avorelo/registry-freshness-cache.json";
|
|
@@ -13591,7 +14271,7 @@ function isSuppressed() {
|
|
|
13591
14271
|
}
|
|
13592
14272
|
function readCache(dir) {
|
|
13593
14273
|
const p = join47(dir, CACHE_FILE);
|
|
13594
|
-
if (!
|
|
14274
|
+
if (!existsSync48(p)) return null;
|
|
13595
14275
|
try {
|
|
13596
14276
|
return JSON.parse(readFileSync31(p, "utf8"));
|
|
13597
14277
|
} catch {
|
|
@@ -13695,10 +14375,10 @@ init_drift_detector();
|
|
|
13695
14375
|
init_intervention();
|
|
13696
14376
|
import { readdirSync as readdirSync13, statSync as statSync9 } from "node:fs";
|
|
13697
14377
|
import { join as join48, relative as relative2 } from "node:path";
|
|
13698
|
-
import { execSync as
|
|
14378
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
13699
14379
|
function getGitChangedFiles(dir) {
|
|
13700
14380
|
try {
|
|
13701
|
-
const out =
|
|
14381
|
+
const out = execSync3("git diff --name-only", { cwd: dir, stdio: "pipe", timeout: 5e3 }).toString().trim();
|
|
13702
14382
|
if (!out) return [];
|
|
13703
14383
|
return out.split("\n").map((f) => f.trim()).filter(Boolean);
|
|
13704
14384
|
} catch {
|
|
@@ -13707,7 +14387,7 @@ function getGitChangedFiles(dir) {
|
|
|
13707
14387
|
}
|
|
13708
14388
|
function getGitUntrackedFiles(dir) {
|
|
13709
14389
|
try {
|
|
13710
|
-
const out =
|
|
14390
|
+
const out = execSync3("git ls-files --others --exclude-standard", { cwd: dir, stdio: "pipe", timeout: 5e3 }).toString().trim();
|
|
13711
14391
|
if (!out) return [];
|
|
13712
14392
|
return out.split("\n").map((f) => f.trim()).filter(Boolean);
|
|
13713
14393
|
} catch {
|
|
@@ -13833,7 +14513,7 @@ function watchWithFixture(dir, fixture) {
|
|
|
13833
14513
|
}
|
|
13834
14514
|
|
|
13835
14515
|
// src/avorelo/capabilities/workspace/monorepo.ts
|
|
13836
|
-
import { existsSync as
|
|
14516
|
+
import { existsSync as existsSync50, readFileSync as readFileSync33, readdirSync as readdirSync14, statSync as statSync10 } from "node:fs";
|
|
13837
14517
|
import { join as join49 } from "node:path";
|
|
13838
14518
|
function expandGlobDirs(dir, patterns) {
|
|
13839
14519
|
const results = [];
|
|
@@ -13841,16 +14521,16 @@ function expandGlobDirs(dir, patterns) {
|
|
|
13841
14521
|
const clean = pattern.replace(/\/\*$/, "").replace(/\*$/, "");
|
|
13842
14522
|
if (!clean) continue;
|
|
13843
14523
|
const base = join49(dir, clean);
|
|
13844
|
-
if (!
|
|
14524
|
+
if (!existsSync50(base)) continue;
|
|
13845
14525
|
if (clean.includes("*")) continue;
|
|
13846
14526
|
try {
|
|
13847
14527
|
const stat = statSync10(base);
|
|
13848
14528
|
if (stat.isDirectory()) {
|
|
13849
|
-
if (
|
|
14529
|
+
if (existsSync50(join49(base, "package.json"))) {
|
|
13850
14530
|
results.push(base);
|
|
13851
14531
|
} else {
|
|
13852
14532
|
for (const entry of readdirSync14(base, { withFileTypes: true })) {
|
|
13853
|
-
if (entry.isDirectory() &&
|
|
14533
|
+
if (entry.isDirectory() && existsSync50(join49(base, entry.name, "package.json"))) {
|
|
13854
14534
|
results.push(join49(base, entry.name));
|
|
13855
14535
|
}
|
|
13856
14536
|
}
|
|
@@ -13873,9 +14553,9 @@ function buildWorkspace(dir, wsPath) {
|
|
|
13873
14553
|
name,
|
|
13874
14554
|
path: wsPath,
|
|
13875
14555
|
relativePath: rel,
|
|
13876
|
-
hasPackageJson:
|
|
13877
|
-
hasAgentsMd:
|
|
13878
|
-
hasCursorRules:
|
|
14556
|
+
hasPackageJson: existsSync50(join49(wsPath, "package.json")),
|
|
14557
|
+
hasAgentsMd: existsSync50(join49(wsPath, "AGENTS.md")),
|
|
14558
|
+
hasCursorRules: existsSync50(join49(wsPath, ".cursor"))
|
|
13879
14559
|
};
|
|
13880
14560
|
}
|
|
13881
14561
|
function detectMonorepo(dir) {
|
|
@@ -13906,7 +14586,7 @@ function detectMonorepo(dir) {
|
|
|
13906
14586
|
} catch {
|
|
13907
14587
|
}
|
|
13908
14588
|
const pnpmPath = join49(dir, "pnpm-workspace.yaml");
|
|
13909
|
-
if (
|
|
14589
|
+
if (existsSync50(pnpmPath)) {
|
|
13910
14590
|
try {
|
|
13911
14591
|
const content = readFileSync33(pnpmPath, "utf8");
|
|
13912
14592
|
const match = content.match(/packages:\s*\n((?:\s*-\s*.+\n?)+)/);
|
|
@@ -13927,10 +14607,10 @@ function detectMonorepo(dir) {
|
|
|
13927
14607
|
}
|
|
13928
14608
|
for (const conventionDir of ["apps", "packages"]) {
|
|
13929
14609
|
const convPath = join49(dir, conventionDir);
|
|
13930
|
-
if (
|
|
14610
|
+
if (existsSync50(convPath)) {
|
|
13931
14611
|
try {
|
|
13932
14612
|
const entries = readdirSync14(convPath, { withFileTypes: true });
|
|
13933
|
-
const workspacePaths = entries.filter((e) => e.isDirectory() &&
|
|
14613
|
+
const workspacePaths = entries.filter((e) => e.isDirectory() && existsSync50(join49(convPath, e.name, "package.json"))).map((e) => join49(convPath, e.name));
|
|
13934
14614
|
if (workspacePaths.length > 0) {
|
|
13935
14615
|
return {
|
|
13936
14616
|
isMonorepo: true,
|
|
@@ -13947,7 +14627,7 @@ function detectMonorepo(dir) {
|
|
|
13947
14627
|
}
|
|
13948
14628
|
|
|
13949
14629
|
// src/avorelo/capabilities/feedback/config.ts
|
|
13950
|
-
import { existsSync as
|
|
14630
|
+
import { existsSync as existsSync51, readFileSync as readFileSync34, writeFileSync as writeFileSync28, mkdirSync as mkdirSync30 } from "node:fs";
|
|
13951
14631
|
import { join as join50, dirname as dirname8 } from "node:path";
|
|
13952
14632
|
var CONFIG_PATH = ".avorelo/config.json";
|
|
13953
14633
|
var DEFAULTS = {
|
|
@@ -13959,7 +14639,7 @@ var DEFAULTS = {
|
|
|
13959
14639
|
};
|
|
13960
14640
|
function readConfig(dir) {
|
|
13961
14641
|
const p = join50(dir, CONFIG_PATH);
|
|
13962
|
-
if (!
|
|
14642
|
+
if (!existsSync51(p)) return {};
|
|
13963
14643
|
try {
|
|
13964
14644
|
return JSON.parse(readFileSync34(p, "utf8"));
|
|
13965
14645
|
} catch {
|
|
@@ -13990,9 +14670,9 @@ function optOut(dir) {
|
|
|
13990
14670
|
|
|
13991
14671
|
// src/avorelo/capabilities/feedback/bundle.ts
|
|
13992
14672
|
init_redaction();
|
|
13993
|
-
import { existsSync as
|
|
14673
|
+
import { existsSync as existsSync52, readFileSync as readFileSync35, writeFileSync as writeFileSync29, mkdirSync as mkdirSync31, readdirSync as readdirSync15 } from "node:fs";
|
|
13994
14674
|
import { join as join51 } from "node:path";
|
|
13995
|
-
import { platform as
|
|
14675
|
+
import { platform as platform3, release, arch } from "node:os";
|
|
13996
14676
|
init_registry();
|
|
13997
14677
|
init_session_store();
|
|
13998
14678
|
function getVersion() {
|
|
@@ -14004,11 +14684,11 @@ function getVersion() {
|
|
|
14004
14684
|
}
|
|
14005
14685
|
}
|
|
14006
14686
|
function detectPackageManager(dir) {
|
|
14007
|
-
if (
|
|
14008
|
-
if (
|
|
14009
|
-
if (
|
|
14010
|
-
if (
|
|
14011
|
-
if (
|
|
14687
|
+
if (existsSync52(join51(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
14688
|
+
if (existsSync52(join51(dir, "yarn.lock"))) return "yarn";
|
|
14689
|
+
if (existsSync52(join51(dir, "bun.lockb"))) return "bun";
|
|
14690
|
+
if (existsSync52(join51(dir, "package-lock.json"))) return "npm";
|
|
14691
|
+
if (existsSync52(join51(dir, "package.json"))) return "npm";
|
|
14012
14692
|
return null;
|
|
14013
14693
|
}
|
|
14014
14694
|
function detectFramework(dir) {
|
|
@@ -14029,7 +14709,7 @@ function detectFramework(dir) {
|
|
|
14029
14709
|
}
|
|
14030
14710
|
function countReceipts(dir) {
|
|
14031
14711
|
const receiptsDir = join51(dir, ".avorelo", "receipts");
|
|
14032
|
-
if (!
|
|
14712
|
+
if (!existsSync52(receiptsDir)) return { total: 0, done: 0, blocked: 0, inProgress: 0 };
|
|
14033
14713
|
let done = 0, blocked = 0, inProgress = 0;
|
|
14034
14714
|
try {
|
|
14035
14715
|
for (const f of readdirSync15(receiptsDir).filter((f2) => f2.endsWith(".json"))) {
|
|
@@ -14056,7 +14736,7 @@ function prepareFeedbackBundle(dir) {
|
|
|
14056
14736
|
bundleId: `fb_${Date.now().toString(36)}`,
|
|
14057
14737
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14058
14738
|
avorelo: { version: getVersion() },
|
|
14059
|
-
platform: { os:
|
|
14739
|
+
platform: { os: platform3(), release: release(), arch: arch(), nodeVersion: process.version },
|
|
14060
14740
|
workspace: {
|
|
14061
14741
|
packageManager: detectPackageManager(dir),
|
|
14062
14742
|
framework: detectFramework(dir),
|
|
@@ -14294,11 +14974,11 @@ function result(classification, risk, reasonCodes, humanGateConditions) {
|
|
|
14294
14974
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
14295
14975
|
|
|
14296
14976
|
// src/avorelo/capabilities/loop-control/check-detection.ts
|
|
14297
|
-
import { readFileSync as readFileSync36, existsSync as
|
|
14977
|
+
import { readFileSync as readFileSync36, existsSync as existsSync53 } from "node:fs";
|
|
14298
14978
|
import { join as join52 } from "node:path";
|
|
14299
14979
|
function detectFromPackageJson(cwd) {
|
|
14300
14980
|
const pkgPath = join52(cwd, "package.json");
|
|
14301
|
-
if (!
|
|
14981
|
+
if (!existsSync53(pkgPath)) return [];
|
|
14302
14982
|
try {
|
|
14303
14983
|
const pkg = JSON.parse(readFileSync36(pkgPath, "utf8"));
|
|
14304
14984
|
const scripts = pkg.scripts ?? {};
|
|
@@ -14321,19 +15001,19 @@ function detectFromPackageJson(cwd) {
|
|
|
14321
15001
|
}
|
|
14322
15002
|
}
|
|
14323
15003
|
function detectFromPython(cwd) {
|
|
14324
|
-
if (
|
|
15004
|
+
if (existsSync53(join52(cwd, "pytest.ini")) || existsSync53(join52(cwd, "pyproject.toml")) || existsSync53(join52(cwd, "setup.py"))) {
|
|
14325
15005
|
return [{ checkId: "chk_pytest", label: "pytest", command: "python -m pytest", source: "python" }];
|
|
14326
15006
|
}
|
|
14327
15007
|
return [];
|
|
14328
15008
|
}
|
|
14329
15009
|
function detectFromGo(cwd) {
|
|
14330
|
-
if (
|
|
15010
|
+
if (existsSync53(join52(cwd, "go.mod"))) {
|
|
14331
15011
|
return [{ checkId: "chk_go_test", label: "go test", command: "go test ./...", source: "go.mod" }];
|
|
14332
15012
|
}
|
|
14333
15013
|
return [];
|
|
14334
15014
|
}
|
|
14335
15015
|
function detectFromRust(cwd) {
|
|
14336
|
-
if (
|
|
15016
|
+
if (existsSync53(join52(cwd, "Cargo.toml"))) {
|
|
14337
15017
|
return [{ checkId: "chk_cargo_test", label: "cargo test", command: "cargo test", source: "Cargo.toml" }];
|
|
14338
15018
|
}
|
|
14339
15019
|
return [];
|
|
@@ -14573,7 +15253,7 @@ function detectIterationDrift(input) {
|
|
|
14573
15253
|
}
|
|
14574
15254
|
|
|
14575
15255
|
// src/avorelo/capabilities/loop-control/checks-runner.ts
|
|
14576
|
-
import { execSync as
|
|
15256
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
14577
15257
|
var CHECK_TIMEOUT_MS = 12e4;
|
|
14578
15258
|
var MAX_OUTPUT_LENGTH = 200;
|
|
14579
15259
|
function truncateOutput(s) {
|
|
@@ -14589,7 +15269,7 @@ function runCheck(check, cwd) {
|
|
|
14589
15269
|
return { ...check, lastResult: "skipped", lastOutput: "no command configured" };
|
|
14590
15270
|
}
|
|
14591
15271
|
try {
|
|
14592
|
-
|
|
15272
|
+
execSync4(check.command, {
|
|
14593
15273
|
cwd,
|
|
14594
15274
|
timeout: CHECK_TIMEOUT_MS,
|
|
14595
15275
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -14606,10 +15286,10 @@ function runAllChecks(checks, cwd) {
|
|
|
14606
15286
|
}
|
|
14607
15287
|
|
|
14608
15288
|
// src/avorelo/capabilities/loop-control/git-observer.ts
|
|
14609
|
-
import { execSync as
|
|
15289
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
14610
15290
|
function getChangedFiles(cwd, since) {
|
|
14611
15291
|
try {
|
|
14612
|
-
const output =
|
|
15292
|
+
const output = execSync5(`git diff --name-only ${since}`, {
|
|
14613
15293
|
cwd,
|
|
14614
15294
|
encoding: "utf-8",
|
|
14615
15295
|
timeout: 1e4,
|
|
@@ -14622,7 +15302,7 @@ function getChangedFiles(cwd, since) {
|
|
|
14622
15302
|
}
|
|
14623
15303
|
function getCurrentHead(cwd) {
|
|
14624
15304
|
try {
|
|
14625
|
-
return
|
|
15305
|
+
return execSync5("git rev-parse HEAD", { cwd, encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
14626
15306
|
} catch {
|
|
14627
15307
|
return null;
|
|
14628
15308
|
}
|
|
@@ -14630,7 +15310,7 @@ function getCurrentHead(cwd) {
|
|
|
14630
15310
|
|
|
14631
15311
|
// src/avorelo/capabilities/loop-control/loop-metadata.ts
|
|
14632
15312
|
init_redaction();
|
|
14633
|
-
import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync30, readFileSync as readFileSync37, existsSync as
|
|
15313
|
+
import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync30, readFileSync as readFileSync37, existsSync as existsSync54, readdirSync as readdirSync16 } from "node:fs";
|
|
14634
15314
|
import { join as join53 } from "node:path";
|
|
14635
15315
|
function classifyFile(file, allowed, disallowed) {
|
|
14636
15316
|
for (const d of disallowed) {
|
|
@@ -14718,7 +15398,7 @@ function persistLoopMetadata(dir, metadata) {
|
|
|
14718
15398
|
}
|
|
14719
15399
|
function readLoopMetadata(dir, loopId) {
|
|
14720
15400
|
const path = join53(loopDir(dir), `${loopId}.json`);
|
|
14721
|
-
if (!
|
|
15401
|
+
if (!existsSync54(path)) return null;
|
|
14722
15402
|
try {
|
|
14723
15403
|
const data = JSON.parse(readFileSync37(path, "utf8"));
|
|
14724
15404
|
return data && data.contract === "avorelo.loopMetadata.v1" ? data : null;
|
|
@@ -14728,7 +15408,7 @@ function readLoopMetadata(dir, loopId) {
|
|
|
14728
15408
|
}
|
|
14729
15409
|
function readLatestLoopMetadata(dir) {
|
|
14730
15410
|
const d = loopDir(dir);
|
|
14731
|
-
if (!
|
|
15411
|
+
if (!existsSync54(d)) return null;
|
|
14732
15412
|
try {
|
|
14733
15413
|
const files = readdirSync16(d).filter((f) => f.startsWith("loop_") && f.endsWith(".json"));
|
|
14734
15414
|
if (files.length === 0) return null;
|
|
@@ -14751,7 +15431,7 @@ function readLatestLoopMetadata(dir) {
|
|
|
14751
15431
|
}
|
|
14752
15432
|
function readActiveLoop(dir) {
|
|
14753
15433
|
const path = join53(loopDir(dir), "active.json");
|
|
14754
|
-
if (!
|
|
15434
|
+
if (!existsSync54(path)) return null;
|
|
14755
15435
|
try {
|
|
14756
15436
|
return JSON.parse(readFileSync37(path, "utf8"));
|
|
14757
15437
|
} catch {
|
|
@@ -14765,7 +15445,7 @@ function writeActiveLoop(dir, loopId, status) {
|
|
|
14765
15445
|
}
|
|
14766
15446
|
function clearActiveLoop(dir) {
|
|
14767
15447
|
const path = join53(loopDir(dir), "active.json");
|
|
14768
|
-
if (
|
|
15448
|
+
if (existsSync54(path)) {
|
|
14769
15449
|
writeFileSync30(path, JSON.stringify({ loopId: null, status: "none" }));
|
|
14770
15450
|
}
|
|
14771
15451
|
}
|
|
@@ -15006,7 +15686,7 @@ async function runLoop(input) {
|
|
|
15006
15686
|
}
|
|
15007
15687
|
|
|
15008
15688
|
// src/avorelo/adapters/claude-code/loop-adapter.ts
|
|
15009
|
-
import { execSync as
|
|
15689
|
+
import { execSync as execSync6 } from "node:child_process";
|
|
15010
15690
|
var MAX_LOG_LENGTH = 200;
|
|
15011
15691
|
var ITERATION_TIMEOUT_MS = 3e5;
|
|
15012
15692
|
function truncate(s) {
|
|
@@ -15036,7 +15716,7 @@ function buildPrompt2(input) {
|
|
|
15036
15716
|
}
|
|
15037
15717
|
function detectPermissionFlag() {
|
|
15038
15718
|
try {
|
|
15039
|
-
const help2 =
|
|
15719
|
+
const help2 = execSync6("claude --help", { timeout: 5e3, stdio: ["pipe", "pipe", "pipe"], encoding: "utf-8" });
|
|
15040
15720
|
if (help2.includes("--permission-mode")) return "--permission-mode bypassPermissions";
|
|
15041
15721
|
} catch {
|
|
15042
15722
|
}
|
|
@@ -15065,7 +15745,7 @@ var claudeCodeLoopAdapter = {
|
|
|
15065
15745
|
const prompt = buildPrompt2(input);
|
|
15066
15746
|
if (!_cachedPermFlag) _cachedPermFlag = detectPermissionFlag();
|
|
15067
15747
|
try {
|
|
15068
|
-
|
|
15748
|
+
execSync6(
|
|
15069
15749
|
`claude --print ${_cachedPermFlag} "${prompt.replace(/"/g, '\\"')}"`,
|
|
15070
15750
|
{
|
|
15071
15751
|
cwd: input.cwd,
|
|
@@ -15100,7 +15780,7 @@ var claudeCodeLoopAdapter = {
|
|
|
15100
15780
|
},
|
|
15101
15781
|
isAvailable() {
|
|
15102
15782
|
try {
|
|
15103
|
-
|
|
15783
|
+
execSync6("claude --version", { timeout: 5e3, stdio: ["pipe", "pipe", "pipe"], encoding: "utf-8" });
|
|
15104
15784
|
return true;
|
|
15105
15785
|
} catch {
|
|
15106
15786
|
return false;
|
|
@@ -15109,7 +15789,7 @@ var claudeCodeLoopAdapter = {
|
|
|
15109
15789
|
};
|
|
15110
15790
|
|
|
15111
15791
|
// src/avorelo/capabilities/settings/index.ts
|
|
15112
|
-
import { existsSync as
|
|
15792
|
+
import { existsSync as existsSync55, readFileSync as readFileSync38, writeFileSync as writeFileSync31, mkdirSync as mkdirSync33 } from "node:fs";
|
|
15113
15793
|
import { join as join54, dirname as dirname9 } from "node:path";
|
|
15114
15794
|
var SETTINGS_CONTRACT = "avorelo.settings.v1";
|
|
15115
15795
|
var SETTINGS_PATH = ".avorelo/settings.json";
|
|
@@ -15176,7 +15856,7 @@ function buildDefaultSettings(opts) {
|
|
|
15176
15856
|
}
|
|
15177
15857
|
function loadSettings(dir) {
|
|
15178
15858
|
const p = join54(dir, SETTINGS_PATH);
|
|
15179
|
-
if (!
|
|
15859
|
+
if (!existsSync55(p)) return null;
|
|
15180
15860
|
try {
|
|
15181
15861
|
const s = JSON.parse(readFileSync38(p, "utf8"));
|
|
15182
15862
|
return s.contract === SETTINGS_CONTRACT ? s : null;
|
|
@@ -15283,7 +15963,7 @@ var ALPHA_NOTICE = [
|
|
|
15283
15963
|
].join("\n");
|
|
15284
15964
|
|
|
15285
15965
|
// src/avorelo/capabilities/update-channel/index.ts
|
|
15286
|
-
import { existsSync as
|
|
15966
|
+
import { existsSync as existsSync56, readFileSync as readFileSync39, writeFileSync as writeFileSync32, mkdirSync as mkdirSync34 } from "node:fs";
|
|
15287
15967
|
import { join as join55, dirname as dirname10 } from "node:path";
|
|
15288
15968
|
var UPDATE_CHANNEL_CONTRACT = "avorelo.updateChannel.v1";
|
|
15289
15969
|
var UPDATE_MANIFEST_CONTRACT = "avorelo.updateManifest.v1";
|
|
@@ -15298,10 +15978,10 @@ function getCurrentVersion4() {
|
|
|
15298
15978
|
}
|
|
15299
15979
|
function detectInstallMethod(root) {
|
|
15300
15980
|
const r2 = root ?? join55(dirname10(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/, "$1")), "../../../..");
|
|
15301
|
-
if (
|
|
15981
|
+
if (existsSync56(join55(r2, ".git"))) return "source-checkout";
|
|
15302
15982
|
try {
|
|
15303
15983
|
const p = join55(r2, "package.json");
|
|
15304
|
-
if (
|
|
15984
|
+
if (existsSync56(p)) {
|
|
15305
15985
|
const pkg = JSON.parse(readFileSync39(p, "utf8"));
|
|
15306
15986
|
if (pkg._resolved) return "npm-global";
|
|
15307
15987
|
if (pkg._where) return "npm-local";
|
|
@@ -15312,7 +15992,7 @@ function detectInstallMethod(root) {
|
|
|
15312
15992
|
}
|
|
15313
15993
|
function loadManifest(dir) {
|
|
15314
15994
|
const p = join55(dir, ".avorelo", "update-manifest.json");
|
|
15315
|
-
if (!
|
|
15995
|
+
if (!existsSync56(p)) return null;
|
|
15316
15996
|
try {
|
|
15317
15997
|
const m = JSON.parse(readFileSync39(p, "utf8"));
|
|
15318
15998
|
return m.contract === UPDATE_MANIFEST_CONTRACT ? m : null;
|
|
@@ -15454,7 +16134,7 @@ function renderUpdateApply(r2) {
|
|
|
15454
16134
|
}
|
|
15455
16135
|
|
|
15456
16136
|
// src/avorelo/capabilities/dogfood-learning/index.ts
|
|
15457
|
-
import { existsSync as
|
|
16137
|
+
import { existsSync as existsSync57, readFileSync as readFileSync40, writeFileSync as writeFileSync33, mkdirSync as mkdirSync35, readdirSync as readdirSync17, unlinkSync as unlinkSync3 } from "node:fs";
|
|
15458
16138
|
import { join as join56, dirname as dirname11 } from "node:path";
|
|
15459
16139
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
15460
16140
|
var DOGFOOD_LEARNING_CONTRACT = "avorelo.dogfoodLearning.v1";
|
|
@@ -15651,7 +16331,7 @@ function ensureQueueDir(dir) {
|
|
|
15651
16331
|
}
|
|
15652
16332
|
function countQueuedEvents(dir) {
|
|
15653
16333
|
const qd = queueDir(dir);
|
|
15654
|
-
if (!
|
|
16334
|
+
if (!existsSync57(qd)) return 0;
|
|
15655
16335
|
try {
|
|
15656
16336
|
return readdirSync17(qd).filter((f) => f.endsWith(".json")).length;
|
|
15657
16337
|
} catch {
|
|
@@ -15669,7 +16349,7 @@ function queueEvent(dir, payload) {
|
|
|
15669
16349
|
}
|
|
15670
16350
|
function loadQueuedEvents(dir) {
|
|
15671
16351
|
const qd = queueDir(dir);
|
|
15672
|
-
if (!
|
|
16352
|
+
if (!existsSync57(qd)) return [];
|
|
15673
16353
|
const files = readdirSync17(qd).filter((f) => f.endsWith(".json")).sort();
|
|
15674
16354
|
const events = [];
|
|
15675
16355
|
for (const f of files) {
|
|
@@ -15683,7 +16363,7 @@ function loadQueuedEvents(dir) {
|
|
|
15683
16363
|
}
|
|
15684
16364
|
function purgeQueue(dir) {
|
|
15685
16365
|
const qd = queueDir(dir);
|
|
15686
|
-
if (!
|
|
16366
|
+
if (!existsSync57(qd)) return { purged: 0 };
|
|
15687
16367
|
const files = readdirSync17(qd).filter((f) => f.endsWith(".json"));
|
|
15688
16368
|
for (const f of files) {
|
|
15689
16369
|
try {
|
|
@@ -15878,7 +16558,7 @@ function generateLocalFingerprint(target) {
|
|
|
15878
16558
|
var CLAIM_EXPIRY_MS = 24 * 60 * 60 * 1e3;
|
|
15879
16559
|
|
|
15880
16560
|
// src/avorelo/capabilities/cloud-sync/cli-auth-state.ts
|
|
15881
|
-
import { existsSync as
|
|
16561
|
+
import { existsSync as existsSync58, readFileSync as readFileSync41, writeFileSync as writeFileSync34, mkdirSync as mkdirSync36 } from "node:fs";
|
|
15882
16562
|
import { join as join57 } from "node:path";
|
|
15883
16563
|
function authDir(baseDir) {
|
|
15884
16564
|
return join57(baseDir, ".avorelo", "auth");
|
|
@@ -15895,7 +16575,7 @@ function writeCliAuthState(baseDir, state) {
|
|
|
15895
16575
|
}
|
|
15896
16576
|
function readCliAuthState(baseDir) {
|
|
15897
16577
|
const path = authPath(baseDir);
|
|
15898
|
-
if (!
|
|
16578
|
+
if (!existsSync58(path)) return null;
|
|
15899
16579
|
try {
|
|
15900
16580
|
const raw = JSON.parse(readFileSync41(path, "utf8"));
|
|
15901
16581
|
if (!raw || typeof raw.token !== "string" || typeof raw.workspaceId !== "string") return null;
|
|
@@ -15911,7 +16591,7 @@ function buildAuthHeaders(authState) {
|
|
|
15911
16591
|
}
|
|
15912
16592
|
|
|
15913
16593
|
// src/avorelo/capabilities/cloud-sync/claim-state.ts
|
|
15914
|
-
import { existsSync as
|
|
16594
|
+
import { existsSync as existsSync59, readFileSync as readFileSync42, writeFileSync as writeFileSync35, mkdirSync as mkdirSync37 } from "node:fs";
|
|
15915
16595
|
import { join as join58 } from "node:path";
|
|
15916
16596
|
function claimDir(baseDir) {
|
|
15917
16597
|
return join58(baseDir, ".avorelo", "claim");
|
|
@@ -15928,7 +16608,7 @@ function writeClaimState(baseDir, state) {
|
|
|
15928
16608
|
}
|
|
15929
16609
|
function readClaimState(baseDir) {
|
|
15930
16610
|
const path = claimPath(baseDir);
|
|
15931
|
-
if (!
|
|
16611
|
+
if (!existsSync59(path)) return null;
|
|
15932
16612
|
try {
|
|
15933
16613
|
const raw = JSON.parse(readFileSync42(path, "utf8"));
|
|
15934
16614
|
if (!raw || typeof raw.workspaceId !== "string" || typeof raw.claimedAt !== "string") return null;
|
|
@@ -15951,6 +16631,9 @@ var RUNTIME_ACTIONS = [
|
|
|
15951
16631
|
{ action: "cli.status", capabilityKey: "session_value_visible", minimumTier: "free", surface: "cli", fallback: "allow", reason: "Show activation status", freeFallbackExists: true },
|
|
15952
16632
|
{ action: "cli.open", capabilityKey: "session_value_visible", minimumTier: "free", surface: "cli", fallback: "allow", reason: "Local receipts dashboard", freeFallbackExists: true },
|
|
15953
16633
|
{ action: "cli.control_center", capabilityKey: "session_value_visible", minimumTier: "free", surface: "cli", fallback: "allow", reason: "Local Control Center", freeFallbackExists: true },
|
|
16634
|
+
{ action: "cli.controls", capabilityKey: "session_value_visible", minimumTier: "free", surface: "cli", fallback: "allow", reason: "Inspect built-in Work Controls", freeFallbackExists: true },
|
|
16635
|
+
{ action: "cli.receipt", capabilityKey: "session_proof_summary", minimumTier: "free", surface: "cli", fallback: "allow", reason: "Inspect latest local receipt", freeFallbackExists: true },
|
|
16636
|
+
{ action: "cli.proof", capabilityKey: "session_proof_summary", minimumTier: "free", surface: "cli", fallback: "allow", reason: "Validate latest proof status", freeFallbackExists: true },
|
|
15954
16637
|
{ action: "cli.doctor", capabilityKey: "scope_safety_check_basic", minimumTier: "free", surface: "cli", fallback: "allow", reason: "Health check", freeFallbackExists: true },
|
|
15955
16638
|
{ action: "cli.verify", capabilityKey: "session_proof_summary", minimumTier: "free", surface: "cli", fallback: "allow", reason: "Validate activation state", freeFallbackExists: true },
|
|
15956
16639
|
{ action: "cli.billing", capabilityKey: "session_value_visible", minimumTier: "free", surface: "cli", fallback: "allow", reason: "Billing readiness (read-only)", freeFallbackExists: true },
|
|
@@ -15989,6 +16672,9 @@ var FREE_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
15989
16672
|
"status",
|
|
15990
16673
|
"open",
|
|
15991
16674
|
"control-center",
|
|
16675
|
+
"controls",
|
|
16676
|
+
"receipt",
|
|
16677
|
+
"proof",
|
|
15992
16678
|
"doctor",
|
|
15993
16679
|
"verify",
|
|
15994
16680
|
"billing",
|
|
@@ -16070,7 +16756,7 @@ function formatCliGateMessage(gateResult) {
|
|
|
16070
16756
|
}
|
|
16071
16757
|
|
|
16072
16758
|
// src/avorelo/telemetry/local-store.ts
|
|
16073
|
-
import { appendFileSync as appendFileSync10, existsSync as
|
|
16759
|
+
import { appendFileSync as appendFileSync10, existsSync as existsSync60, mkdirSync as mkdirSync38, readFileSync as readFileSync44, writeFileSync as writeFileSync36 } from "node:fs";
|
|
16074
16760
|
import { dirname as dirname13 } from "node:path";
|
|
16075
16761
|
|
|
16076
16762
|
// src/avorelo/telemetry/config.ts
|
|
@@ -16084,7 +16770,7 @@ var TELEMETRY_STATE_FILE = "telemetry-state.json";
|
|
|
16084
16770
|
var TELEMETRY_BATCH_SIZE = 100;
|
|
16085
16771
|
var TELEMETRY_PERIOD_MS = 6 * 60 * 60 * 1e3;
|
|
16086
16772
|
var TELEMETRY_OPPORTUNISTIC_MS = 24 * 60 * 60 * 1e3;
|
|
16087
|
-
var TELEMETRY_TIMEOUT_MS =
|
|
16773
|
+
var TELEMETRY_TIMEOUT_MS = 2e3;
|
|
16088
16774
|
function getPackageVersion() {
|
|
16089
16775
|
for (const rel of ["../../../package.json", "../../../../package.json", "../../../../../package.json"]) {
|
|
16090
16776
|
try {
|
|
@@ -16392,7 +17078,7 @@ function safeParseJson(text) {
|
|
|
16392
17078
|
}
|
|
16393
17079
|
}
|
|
16394
17080
|
function readJsonl(path) {
|
|
16395
|
-
if (!
|
|
17081
|
+
if (!existsSync60(path)) return [];
|
|
16396
17082
|
const lines = readFileSync44(path, "utf8").split(/\r?\n/);
|
|
16397
17083
|
const values = [];
|
|
16398
17084
|
for (const line of lines) {
|
|
@@ -16415,7 +17101,7 @@ function writeJsonl(path, values) {
|
|
|
16415
17101
|
}
|
|
16416
17102
|
function ensureTelemetryState(dir, now = Date.now()) {
|
|
16417
17103
|
const paths = getTelemetryConfig(dir, buildTelemetryState(now));
|
|
16418
|
-
if (
|
|
17104
|
+
if (existsSync60(paths.statePath)) {
|
|
16419
17105
|
const parsed = safeParseJson(readFileSync44(paths.statePath, "utf8"));
|
|
16420
17106
|
if (parsed?.contract === "avorelo.telemetry.state.v1") return parsed;
|
|
16421
17107
|
}
|
|
@@ -16903,11 +17589,11 @@ function renderTelemetryPreview(preview) {
|
|
|
16903
17589
|
}
|
|
16904
17590
|
|
|
16905
17591
|
// src/avorelo/telemetry/integration-detection.ts
|
|
16906
|
-
import { existsSync as
|
|
17592
|
+
import { existsSync as existsSync61, readFileSync as readFileSync45 } from "node:fs";
|
|
16907
17593
|
import { join as join60 } from "node:path";
|
|
16908
17594
|
function detectGitProviderFromConfig(dir) {
|
|
16909
17595
|
const configPath = join60(dir, ".git", "config");
|
|
16910
|
-
if (!
|
|
17596
|
+
if (!existsSync61(configPath)) return "unknown";
|
|
16911
17597
|
try {
|
|
16912
17598
|
const content = readFileSync45(configPath, "utf8").toLowerCase();
|
|
16913
17599
|
if (content.includes("github.com")) return "github";
|
|
@@ -16919,15 +17605,15 @@ function detectGitProviderFromConfig(dir) {
|
|
|
16919
17605
|
}
|
|
16920
17606
|
}
|
|
16921
17607
|
function detectCiProvider(dir) {
|
|
16922
|
-
if (
|
|
16923
|
-
if (
|
|
16924
|
-
if (
|
|
16925
|
-
if (
|
|
17608
|
+
if (existsSync61(join60(dir, ".github", "workflows"))) return "github_actions";
|
|
17609
|
+
if (existsSync61(join60(dir, ".gitlab-ci.yml"))) return "gitlab_ci";
|
|
17610
|
+
if (existsSync61(join60(dir, ".circleci", "config.yml"))) return "circle";
|
|
17611
|
+
if (existsSync61(join60(dir, "Jenkinsfile"))) return "jenkins";
|
|
16926
17612
|
return "unknown";
|
|
16927
17613
|
}
|
|
16928
17614
|
function detectRepoVisibility(dir) {
|
|
16929
17615
|
const configPath = join60(dir, ".git", "config");
|
|
16930
|
-
if (!
|
|
17616
|
+
if (!existsSync61(configPath)) return "unknown";
|
|
16931
17617
|
try {
|
|
16932
17618
|
const content = readFileSync45(configPath, "utf8").toLowerCase();
|
|
16933
17619
|
if (content.includes("github.com")) {
|
|
@@ -17104,6 +17790,10 @@ function help() {
|
|
|
17104
17790
|
" status [--target <dir>] Show activation and session status",
|
|
17105
17791
|
" open [--target <dir>] [--format html|json|text] Local receipts dashboard",
|
|
17106
17792
|
" control-center [--target <dir>] [--format html|json|text] Local Control Center (read-only, all local state)",
|
|
17793
|
+
" controls list [--json] List built-in Work Controls",
|
|
17794
|
+
" controls explain <control> [--json] Explain one built-in Work Control",
|
|
17795
|
+
" receipt latest [--target <dir>] [--json] Show the latest local receipt",
|
|
17796
|
+
" proof check [--target <dir>] [--json] Validate the latest proof status",
|
|
17107
17797
|
" doctor [--target <dir>] Health check (adapters, hooks, session)",
|
|
17108
17798
|
" verify [--target <dir>] Validate activation state invariants",
|
|
17109
17799
|
" uninstall [--target <dir>] Remove all Avorelo-managed content",
|
|
@@ -17175,10 +17865,12 @@ function cmdRun(args) {
|
|
|
17175
17865
|
process.stdout.write(JSON.stringify({ fixture: name, decision: gate.decision, confidence: gate.confidence, reasonCodes: gate.reasonCodes, receipt }, null, 2) + "\n");
|
|
17176
17866
|
return gate.decision === "STOP_DONE" ? 0 : 1;
|
|
17177
17867
|
}
|
|
17178
|
-
function cmdActivate(args) {
|
|
17868
|
+
async function cmdActivate(args) {
|
|
17179
17869
|
const target = arg(args, "--target", process.cwd());
|
|
17180
17870
|
const installHooksFlag = args.includes("--install-hooks");
|
|
17181
17871
|
const approve = args.includes("--approve");
|
|
17872
|
+
const claimToken = arg(args, "--claim");
|
|
17873
|
+
const scope = arg(args, "--scope") ?? "project-wide";
|
|
17182
17874
|
if (installHooksFlag) {
|
|
17183
17875
|
if (!approve) {
|
|
17184
17876
|
process.stderr.write("Hook installation requires explicit approval. Add --approve to confirm.\n");
|
|
@@ -17199,6 +17891,18 @@ function cmdActivate(args) {
|
|
|
17199
17891
|
return 2;
|
|
17200
17892
|
}
|
|
17201
17893
|
}
|
|
17894
|
+
const preflight = runPreflight(target);
|
|
17895
|
+
if (!preflight.canStart) {
|
|
17896
|
+
process.stderr.write(formatPreflightReport(preflight));
|
|
17897
|
+
process.stderr.write(`
|
|
17898
|
+
Activation taxonomy: ${preflight.taxonomy}
|
|
17899
|
+
`);
|
|
17900
|
+
return 2;
|
|
17901
|
+
}
|
|
17902
|
+
if (!preflight.ok) {
|
|
17903
|
+
process.stderr.write(formatPreflightReport(preflight));
|
|
17904
|
+
process.stderr.write("Continuing with activation despite warnings...\n\n");
|
|
17905
|
+
}
|
|
17202
17906
|
const state = runFullActivation(target);
|
|
17203
17907
|
const contract = createWorkContract({ contractId: "canonical-activate", objective: "full local-first activation", allowedPaths: [join61(target, ".avorelo")], planTier: "Free" });
|
|
17204
17908
|
const ledger = new StateLedger();
|
|
@@ -17218,12 +17922,15 @@ function cmdActivate(args) {
|
|
|
17218
17922
|
state.receipts.push({ id: receipt.receiptId, path: join61(target, ".avorelo", "receipts", `${receipt.receiptId}.json`), type: "canonical_activation" });
|
|
17219
17923
|
persistActivationV2(target, state);
|
|
17220
17924
|
persistReceipt(target, receipt);
|
|
17925
|
+
const detection = runFullDetection(target);
|
|
17926
|
+
const fingerprint = generateLocalFingerprint(target);
|
|
17221
17927
|
const fv = state.firstValue;
|
|
17222
17928
|
const lines = [
|
|
17223
17929
|
"",
|
|
17224
17930
|
"Avorelo activated.",
|
|
17225
17931
|
"",
|
|
17226
17932
|
` Mode: ${state.activationMode}`,
|
|
17933
|
+
` Scope: ${scope}`,
|
|
17227
17934
|
` Status: ${state.activationStatus}`,
|
|
17228
17935
|
` State: ${join61(target, ACTIVATION_STATE_DIR, ACTIVATION_STATE_FILE)}`
|
|
17229
17936
|
];
|
|
@@ -17232,6 +17939,10 @@ function cmdActivate(args) {
|
|
|
17232
17939
|
for (const f of fv.found.slice(0, 8)) lines.push(` ${f}`);
|
|
17233
17940
|
if (fv.found.length > 8) lines.push(` ... and ${fv.found.length - 8} more`);
|
|
17234
17941
|
}
|
|
17942
|
+
if (detection.summary.toolsDetected.length > 0) {
|
|
17943
|
+
lines.push("", " Coding tools detected:");
|
|
17944
|
+
for (const t of detection.summary.toolsDetected) lines.push(` ${t}`);
|
|
17945
|
+
}
|
|
17235
17946
|
if (fv.fixed.length > 0) {
|
|
17236
17947
|
lines.push("", " Fixed:");
|
|
17237
17948
|
for (const f of fv.fixed) lines.push(` ${f}`);
|
|
@@ -17245,7 +17956,38 @@ function cmdActivate(args) {
|
|
|
17245
17956
|
` Run entry: ${state.runEntry.installed ? "installed" : "not installed"}`,
|
|
17246
17957
|
` Billing: ${state.billing.status}`,
|
|
17247
17958
|
` Auth: ${state.auth.status}`,
|
|
17248
|
-
` Production: not ready
|
|
17959
|
+
` Production: not ready`
|
|
17960
|
+
);
|
|
17961
|
+
let linkResult = "no claim provided";
|
|
17962
|
+
if (claimToken) {
|
|
17963
|
+
const baseUrl = process.env.APP_BASE_URL ?? "https://app.avorelo.com";
|
|
17964
|
+
try {
|
|
17965
|
+
const resp = await fetch(`${baseUrl}/api/activation/link`, {
|
|
17966
|
+
method: "POST",
|
|
17967
|
+
headers: { "Content-Type": "application/json" },
|
|
17968
|
+
body: JSON.stringify({
|
|
17969
|
+
token: claimToken,
|
|
17970
|
+
fingerprint,
|
|
17971
|
+
version: avoreloVersion(),
|
|
17972
|
+
toolsDetected: detection.summary.toolsDetected,
|
|
17973
|
+
osFamily: detection.environment.os,
|
|
17974
|
+
nodeVersion: detection.environment.nodeVersion ?? null,
|
|
17975
|
+
taxonomy: "ACTIVATION_SUCCEEDED_LOCALLY"
|
|
17976
|
+
})
|
|
17977
|
+
});
|
|
17978
|
+
if (resp.ok) {
|
|
17979
|
+
const data = await resp.json();
|
|
17980
|
+
linkResult = data.linked ? "linked" : data.error ?? "unknown";
|
|
17981
|
+
} else {
|
|
17982
|
+
const err = await resp.json().catch(() => ({ error: resp.statusText }));
|
|
17983
|
+
linkResult = `failed: ${err.error ?? resp.statusText}`;
|
|
17984
|
+
}
|
|
17985
|
+
} catch (e) {
|
|
17986
|
+
linkResult = `error: ${e.message}`;
|
|
17987
|
+
}
|
|
17988
|
+
lines.push(` Dashboard: ${linkResult === "linked" ? "linked to account" : linkResult}`);
|
|
17989
|
+
}
|
|
17990
|
+
lines.push(
|
|
17249
17991
|
"",
|
|
17250
17992
|
` Next: ${fv.nextAction}`,
|
|
17251
17993
|
""
|
|
@@ -17253,6 +17995,14 @@ function cmdActivate(args) {
|
|
|
17253
17995
|
process.stdout.write(lines.join("\n"));
|
|
17254
17996
|
return 0;
|
|
17255
17997
|
}
|
|
17998
|
+
function cmdPreflight(args) {
|
|
17999
|
+
const target = arg(args, "--target", process.cwd());
|
|
18000
|
+
const result3 = runPreflight(target);
|
|
18001
|
+
process.stdout.write(formatPreflightReport(result3));
|
|
18002
|
+
process.stdout.write(`Taxonomy: ${result3.taxonomy}
|
|
18003
|
+
`);
|
|
18004
|
+
return result3.canStart ? 0 : 2;
|
|
18005
|
+
}
|
|
17256
18006
|
async function cmdDoctor(args) {
|
|
17257
18007
|
const target = arg(args, "--target", process.cwd());
|
|
17258
18008
|
const r2 = doctor(target);
|
|
@@ -17524,6 +18274,140 @@ function cmdControlCenter(args) {
|
|
|
17524
18274
|
process.stdout.write(JSON.stringify({ ok: true, htmlPath, runtime: model.sections.runtimeSession.status, sources: model.sources.length }, null, 2) + "\n");
|
|
17525
18275
|
return 0;
|
|
17526
18276
|
}
|
|
18277
|
+
function cmdControls(args) {
|
|
18278
|
+
const sub = args[0] && !args[0].startsWith("--") ? args[0] : "list";
|
|
18279
|
+
const asJson = args.includes("--json");
|
|
18280
|
+
if (sub === "list") {
|
|
18281
|
+
const controls = listWorkControls();
|
|
18282
|
+
if (asJson) {
|
|
18283
|
+
process.stdout.write(JSON.stringify(controls, null, 2) + "\n");
|
|
18284
|
+
return 0;
|
|
18285
|
+
}
|
|
18286
|
+
process.stdout.write([
|
|
18287
|
+
"",
|
|
18288
|
+
"Avorelo Work Controls",
|
|
18289
|
+
...controls.map((control) => ` ${control.controlId}: ${control.uiCopy} [${control.defaultState}]`),
|
|
18290
|
+
""
|
|
18291
|
+
].join("\n"));
|
|
18292
|
+
return 0;
|
|
18293
|
+
}
|
|
18294
|
+
if (sub === "explain") {
|
|
18295
|
+
const controlId = args.find((value, index) => index > 0 && !value.startsWith("--"));
|
|
18296
|
+
if (!controlId) {
|
|
18297
|
+
process.stderr.write("Usage: avorelo controls explain <control> [--json]\n");
|
|
18298
|
+
return 2;
|
|
18299
|
+
}
|
|
18300
|
+
const control = getWorkControl(controlId);
|
|
18301
|
+
if (!control) {
|
|
18302
|
+
process.stderr.write(`Unknown Work Control: ${controlId}
|
|
18303
|
+
`);
|
|
18304
|
+
return 1;
|
|
18305
|
+
}
|
|
18306
|
+
if (asJson) {
|
|
18307
|
+
process.stdout.write(JSON.stringify(control, null, 2) + "\n");
|
|
18308
|
+
return 0;
|
|
18309
|
+
}
|
|
18310
|
+
process.stdout.write([
|
|
18311
|
+
"",
|
|
18312
|
+
`${control.title} (${control.controlId})`,
|
|
18313
|
+
` Purpose: ${control.purpose}`,
|
|
18314
|
+
` Points: ${control.enforcementPoints.join(", ")}`,
|
|
18315
|
+
` Default: ${control.defaultState}`,
|
|
18316
|
+
` Packaging: Free=${control.packaging.free} Pro=${control.packaging.pro} Teams=${control.packaging.teams}`,
|
|
18317
|
+
` Local: ${control.localOnlyBehavior}`,
|
|
18318
|
+
` Cloud: ${control.cloudBehavior}`,
|
|
18319
|
+
` Persisted: ${control.dataPersisted.join(", ")}`,
|
|
18320
|
+
` Tests: ${control.testsRequired.join(", ")}`,
|
|
18321
|
+
` UI copy: ${control.uiCopy}`,
|
|
18322
|
+
""
|
|
18323
|
+
].join("\n"));
|
|
18324
|
+
return 0;
|
|
18325
|
+
}
|
|
18326
|
+
process.stderr.write("Usage: avorelo controls <list|explain> [<control>] [--json]\n");
|
|
18327
|
+
return 2;
|
|
18328
|
+
}
|
|
18329
|
+
function latestReceiptFor(dir) {
|
|
18330
|
+
return listReceipts(dir).sort((a, b) => {
|
|
18331
|
+
const aw = typeof a.writtenAt === "number" ? a.writtenAt : -1;
|
|
18332
|
+
const bw = typeof b.writtenAt === "number" ? b.writtenAt : -1;
|
|
18333
|
+
if (aw !== bw) return bw - aw;
|
|
18334
|
+
return b.receiptId.localeCompare(a.receiptId);
|
|
18335
|
+
})[0] ?? null;
|
|
18336
|
+
}
|
|
18337
|
+
function cmdReceipt(args) {
|
|
18338
|
+
const sub = args[0] && !args[0].startsWith("--") ? args[0] : "latest";
|
|
18339
|
+
const target = arg(args, "--target", process.cwd());
|
|
18340
|
+
const asJson = args.includes("--json");
|
|
18341
|
+
if (sub !== "latest") {
|
|
18342
|
+
process.stderr.write("Usage: avorelo receipt latest [--target <dir>] [--json]\n");
|
|
18343
|
+
return 2;
|
|
18344
|
+
}
|
|
18345
|
+
const latest = latestReceiptFor(target);
|
|
18346
|
+
if (!latest) {
|
|
18347
|
+
if (asJson) {
|
|
18348
|
+
process.stdout.write(JSON.stringify({ status: "none", message: "no receipts found" }, null, 2) + "\n");
|
|
18349
|
+
return 0;
|
|
18350
|
+
}
|
|
18351
|
+
process.stdout.write("\nNo receipts found yet. Run a controlled session first.\n\n");
|
|
18352
|
+
return 0;
|
|
18353
|
+
}
|
|
18354
|
+
const full = readReceipt(target, latest.receiptId) ?? latest;
|
|
18355
|
+
if (asJson) {
|
|
18356
|
+
process.stdout.write(JSON.stringify(full, null, 2) + "\n");
|
|
18357
|
+
return 0;
|
|
18358
|
+
}
|
|
18359
|
+
process.stdout.write([
|
|
18360
|
+
"",
|
|
18361
|
+
`Latest receipt: ${full.receiptId}`,
|
|
18362
|
+
` Contract: ${full.contractId}`,
|
|
18363
|
+
` Decision: ${full.decision}`,
|
|
18364
|
+
` Evidence: ${full.evidenceLevels.join(", ") || "none"}`,
|
|
18365
|
+
` Reasons: ${full.decisionBasis.reasonCodes.join(", ") || "none"}`,
|
|
18366
|
+
` Next: ${full.safeNextActions.join("; ") || "none"}`,
|
|
18367
|
+
""
|
|
18368
|
+
].join("\n"));
|
|
18369
|
+
return 0;
|
|
18370
|
+
}
|
|
18371
|
+
function cmdProof(args) {
|
|
18372
|
+
const sub = args[0] && !args[0].startsWith("--") ? args[0] : "check";
|
|
18373
|
+
const target = arg(args, "--target", process.cwd());
|
|
18374
|
+
const asJson = args.includes("--json");
|
|
18375
|
+
if (sub !== "check") {
|
|
18376
|
+
process.stderr.write("Usage: avorelo proof check [--target <dir>] [--json]\n");
|
|
18377
|
+
return 2;
|
|
18378
|
+
}
|
|
18379
|
+
const report = loadLatestProofReport(target) ?? buildProofReportFromLocalEvidence(target);
|
|
18380
|
+
const summary = summarizeProofReport(report);
|
|
18381
|
+
const validation = validateProofReport(report);
|
|
18382
|
+
const payload = {
|
|
18383
|
+
reportId: report.reportId,
|
|
18384
|
+
valid: validation.valid,
|
|
18385
|
+
reasons: validation.reasons,
|
|
18386
|
+
canShowCostSummary: summary.canShowCostSummary,
|
|
18387
|
+
canShowSavings: summary.canShowSavings,
|
|
18388
|
+
savingsRefusalReason: summary.savingsRefusalReason,
|
|
18389
|
+
sections: summary.sections
|
|
18390
|
+
};
|
|
18391
|
+
if (asJson) {
|
|
18392
|
+
process.stdout.write(JSON.stringify(payload, null, 2) + "\n");
|
|
18393
|
+
return validation.valid ? 0 : 1;
|
|
18394
|
+
}
|
|
18395
|
+
process.stdout.write([
|
|
18396
|
+
"",
|
|
18397
|
+
`Proof check: ${report.reportId}`,
|
|
18398
|
+
` Valid: ${validation.valid}`,
|
|
18399
|
+
` Found: ${summary.sections.found}`,
|
|
18400
|
+
` Protected: ${summary.sections.protected}`,
|
|
18401
|
+
` Verified: ${summary.sections.verified}`,
|
|
18402
|
+
` Attention: ${summary.sections.needsAttention}`,
|
|
18403
|
+
` Next: ${summary.sections.next}`,
|
|
18404
|
+
` Cost: ${summary.canShowCostSummary ? "available" : "unavailable"}`,
|
|
18405
|
+
` Savings: ${summary.canShowSavings ? "shown" : "not claimed"}${summary.savingsRefusalReason ? ` (${summary.savingsRefusalReason})` : ""}`,
|
|
18406
|
+
validation.reasons.length ? ` Issues: ${validation.reasons.join(", ")}` : " Issues: none",
|
|
18407
|
+
""
|
|
18408
|
+
].join("\n"));
|
|
18409
|
+
return validation.valid ? 0 : 1;
|
|
18410
|
+
}
|
|
17527
18411
|
function cmdVerify(args) {
|
|
17528
18412
|
const target = arg(args, "--target", process.cwd());
|
|
17529
18413
|
const stateVerify = verifyActivationState(target);
|
|
@@ -17537,7 +18421,7 @@ function cmdVerify(args) {
|
|
|
17537
18421
|
const input = loadProofInput(target);
|
|
17538
18422
|
if (input) {
|
|
17539
18423
|
const contract = createWorkContract({ contractId: "verify", objective: input.objective ?? "verify real-workflow proof", allowedPaths: [join61(target, "src")], planTier: "Free" });
|
|
17540
|
-
const r2 =
|
|
18424
|
+
const r2 = evaluateProof2({ contract, artifacts: input.artifacts, readbacks: input.readbacks, dir: target, sampleSize: input.sampleSize, receiptId: "rcpt_verify" });
|
|
17541
18425
|
process.stdout.write(JSON.stringify({ scope: "full", activationState: { valid: true }, proof: { decision: r2.decision, confidence: r2.confidence } }, null, 2) + "\n");
|
|
17542
18426
|
return r2.decision === "STOP_DONE" ? 0 : 1;
|
|
17543
18427
|
}
|
|
@@ -18039,7 +18923,7 @@ function cmdTokenCost(args) {
|
|
|
18039
18923
|
}
|
|
18040
18924
|
if (sub === "import" || sub === "validate") {
|
|
18041
18925
|
const file = arg(args, "--file");
|
|
18042
|
-
if (!file || !
|
|
18926
|
+
if (!file || !existsSync62(file)) {
|
|
18043
18927
|
process.stderr.write("Usage: avorelo token-cost " + sub + " --file <path> [--json]\n");
|
|
18044
18928
|
return 2;
|
|
18045
18929
|
}
|
|
@@ -18186,7 +19070,7 @@ function cmdContextCheck(args) {
|
|
|
18186
19070
|
const ci = args.includes("--ci");
|
|
18187
19071
|
const wcPath = arg(args, "--work-contract");
|
|
18188
19072
|
let workContract;
|
|
18189
|
-
if (wcPath &&
|
|
19073
|
+
if (wcPath && existsSync62(wcPath)) {
|
|
18190
19074
|
try {
|
|
18191
19075
|
workContract = JSON.parse(readFileSync46(wcPath, "utf8"));
|
|
18192
19076
|
} catch {
|
|
@@ -18251,7 +19135,7 @@ function cmdSecretBoundary(args) {
|
|
|
18251
19135
|
const asJson = args.includes("--json");
|
|
18252
19136
|
let content = arg(args, "--content");
|
|
18253
19137
|
const file = arg(args, "--file");
|
|
18254
|
-
if (file &&
|
|
19138
|
+
if (file && existsSync62(file)) content = readFileSync46(file, "utf8");
|
|
18255
19139
|
if (content === void 0) content = "";
|
|
18256
19140
|
if (sub === "scan" || sub === void 0) {
|
|
18257
19141
|
const r2 = scanContent({ content, sourceKind: file ? "file" : "tool_output" });
|
|
@@ -18318,7 +19202,7 @@ function cmdExplain(args) {
|
|
|
18318
19202
|
const changedFiles = [];
|
|
18319
19203
|
for (const { adapter } of detected) {
|
|
18320
19204
|
const surface = adapter.getInstructionSurface(target);
|
|
18321
|
-
if (surface &&
|
|
19205
|
+
if (surface && existsSync62(surface)) changedFiles.push(surface);
|
|
18322
19206
|
}
|
|
18323
19207
|
if (changedFiles.length > 0) {
|
|
18324
19208
|
lines.push(" Changed:");
|
|
@@ -18492,7 +19376,7 @@ function cmdFeedback(args) {
|
|
|
18492
19376
|
}
|
|
18493
19377
|
if (sub === "share") {
|
|
18494
19378
|
const file = arg(args, "--file");
|
|
18495
|
-
if (!file || !
|
|
19379
|
+
if (!file || !existsSync62(file)) {
|
|
18496
19380
|
process.stderr.write("Usage: avorelo feedback share --file <bundle-path>\n");
|
|
18497
19381
|
return 2;
|
|
18498
19382
|
}
|
|
@@ -18796,7 +19680,7 @@ No loop metadata found for ${loopId}.
|
|
|
18796
19680
|
if (sub === "doctor") {
|
|
18797
19681
|
const issues = [];
|
|
18798
19682
|
const ok = [];
|
|
18799
|
-
if (
|
|
19683
|
+
if (existsSync62(join61(target, ".git"))) {
|
|
18800
19684
|
ok.push("Git repository detected");
|
|
18801
19685
|
} else {
|
|
18802
19686
|
issues.push("Not a git repository \u2014 loop needs git for drift detection");
|
|
@@ -18856,7 +19740,7 @@ function cmdUninstallAll(args) {
|
|
|
18856
19740
|
const preserved = adapterResult.preserved;
|
|
18857
19741
|
const avoreloDir2 = join61(target, ".avorelo");
|
|
18858
19742
|
try {
|
|
18859
|
-
if (
|
|
19743
|
+
if (existsSync62(avoreloDir2)) {
|
|
18860
19744
|
rmSync3(avoreloDir2, { recursive: true, force: true });
|
|
18861
19745
|
removed.push(avoreloDir2);
|
|
18862
19746
|
}
|
|
@@ -19505,6 +20389,8 @@ function main(argv) {
|
|
|
19505
20389
|
return cmdSupport(rest);
|
|
19506
20390
|
case "activate":
|
|
19507
20391
|
return cmdActivate(rest);
|
|
20392
|
+
case "preflight":
|
|
20393
|
+
return cmdPreflight(rest);
|
|
19508
20394
|
case "doctor":
|
|
19509
20395
|
return cmdDoctor(rest);
|
|
19510
20396
|
case "uninstall":
|
|
@@ -19523,6 +20409,12 @@ function main(argv) {
|
|
|
19523
20409
|
return cmdOpen(rest);
|
|
19524
20410
|
case "control-center":
|
|
19525
20411
|
return cmdControlCenter(rest);
|
|
20412
|
+
case "controls":
|
|
20413
|
+
return cmdControls(rest);
|
|
20414
|
+
case "receipt":
|
|
20415
|
+
return cmdReceipt(rest);
|
|
20416
|
+
case "proof":
|
|
20417
|
+
return cmdProof(rest);
|
|
19526
20418
|
case "verify":
|
|
19527
20419
|
return cmdVerify(rest);
|
|
19528
20420
|
case "site":
|
|
@@ -19722,14 +20614,21 @@ async function finalize(exitCode) {
|
|
|
19722
20614
|
recordCliTelemetry(exitCode);
|
|
19723
20615
|
} catch {
|
|
19724
20616
|
}
|
|
19725
|
-
sendDueTelemetry(CLI_TELEMETRY_SNAPSHOT.target).catch(() => {
|
|
19726
|
-
});
|
|
19727
20617
|
if (_cmd && LEARNING_COMMANDS.has(_cmd)) {
|
|
19728
20618
|
try {
|
|
19729
20619
|
emitLearningEvent(process.cwd(), { commandName: _cmd, commandStatus: exitCode === 0 ? "ok" : "error", eventType: "command" });
|
|
19730
20620
|
} catch {
|
|
19731
20621
|
}
|
|
19732
20622
|
}
|
|
20623
|
+
try {
|
|
20624
|
+
const telemetryDone = sendDueTelemetry(CLI_TELEMETRY_SNAPSHOT.target).catch(() => {
|
|
20625
|
+
});
|
|
20626
|
+
await Promise.race([telemetryDone, new Promise((r2) => {
|
|
20627
|
+
const t = setTimeout(r2, 2e3);
|
|
20628
|
+
if (typeof t.unref === "function") t.unref();
|
|
20629
|
+
})]);
|
|
20630
|
+
} catch {
|
|
20631
|
+
}
|
|
19733
20632
|
if (_cmd !== "serve" && _cmd !== "webhook" && _cmd !== "sync") {
|
|
19734
20633
|
setTimeout(() => process.exit(exitCode), 50).unref();
|
|
19735
20634
|
}
|