@topolo/cli 0.13.17 → 0.13.21
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 +18 -4
- package/agent-packs/README.md +469 -1
- package/agent-packs/coverage_changed.py +1 -1
- package/agent-packs/docs/selected-artifacts.md +47 -0
- package/agent-packs/documentation/cloud-task-state.md +56 -0
- package/agent-packs/domain-contexts/README.md +25 -0
- package/agent-packs/domain-contexts/cicd.json +8 -0
- package/agent-packs/gui/feed-adapter.js +4 -0
- package/agent-packs/gui/index.html +9 -0
- package/agent-packs/gui/studio.css +14 -0
- package/agent-packs/gui/studio.js +121 -0
- package/agent-packs/gui/studio_server.py +355 -0
- package/agent-packs/roles/cicd/CLAUDE.md +24 -0
- package/agent-packs/specializations/cicd--cicd.json +5 -0
- package/agent-packs/specializations/cicd--pipeline-engineering.json +5 -0
- package/agent-packs/specializations/cicd--promotion-deployment.json +5 -0
- package/agent-packs/specializations/cicd--queue-recovery.json +5 -0
- package/agent-packs/specializations/cicd--release-verification.json +5 -0
- package/agent-packs/specializations/cicd--runner-capacity.json +5 -0
- package/agent-packs/specializations/intakes--engineering-02.json +5 -0
- package/agent-packs/specializations/intakes--engineering-03.json +5 -0
- package/agent-packs/specializations/intakes--engineering.json +5 -0
- package/agent-packs/specializations/intakes--operator-01.json +5 -0
- package/agent-packs/specializations/intakes--operator-02.json +5 -0
- package/agent-packs/specializations/operator-skills--audio-and-narration-specialist.json +5 -0
- package/agent-packs/specializations/operator-skills--brand-and-copywriting-specialist.json +5 -0
- package/agent-packs/specializations/operator-skills--capability-research-specialist.json +5 -0
- package/agent-packs/specializations/operator-skills--data-analysis-and-visualization.json +5 -0
- package/agent-packs/specializations/operator-skills--financial-evidence-specialist.json +5 -0
- package/agent-packs/specializations/operator-skills--operating-template-specialist.json +5 -0
- package/agent-packs/specializations/operator-skills--operator-skill-library.json +5 -0
- package/agent-packs/specializations/operator-skills--operator-skills.json +5 -0
- package/agent-packs/specializations/operator-skills--operator-workflow-evaluation.json +5 -0
- package/agent-packs/specializations/operator-skills--privacy-and-agreement-review.json +5 -0
- package/agent-packs/specializations/operator-skills--storytelling-specialist.json +5 -0
- package/agent-packs/specializations/operator-skills--ux-and-accessibility-specialist.json +5 -0
- package/agent-packs/specializations/operator-skills--video-production-specialist.json +5 -0
- package/agent-packs/specializations/operator-skills--visual-design-specialist.json +5 -0
- package/agent-packs/specializations/operator-skills--workflow-integration-specialist.json +5 -0
- package/agent-packs/specializations/operators--access-and-privacy.json +5 -0
- package/agent-packs/specializations/operators--accounting-evidence-review.json +5 -0
- package/agent-packs/specializations/operators--agreement-operations.json +5 -0
- package/agent-packs/specializations/operators--books-operator.json +5 -0
- package/agent-packs/specializations/operators--brand-operator.json +5 -0
- package/agent-packs/specializations/operators--commerce-operations.json +5 -0
- package/agent-packs/specializations/operators--communications-operator.json +5 -0
- package/agent-packs/specializations/operators--content-and-assets-operator.json +5 -0
- package/agent-packs/specializations/operators--customer-operations.json +5 -0
- package/agent-packs/specializations/operators--design-operator.json +5 -0
- package/agent-packs/specializations/operators--design-production-02.json +5 -0
- package/agent-packs/specializations/operators--design-production-03.json +5 -0
- package/agent-packs/specializations/operators--design-production-04.json +5 -0
- package/agent-packs/specializations/operators--device-and-feed-operator.json +5 -0
- package/agent-packs/specializations/operators--director-operator.json +5 -0
- package/agent-packs/specializations/operators--experience-review.json +5 -0
- package/agent-packs/specializations/operators--growth-operations.json +5 -0
- package/agent-packs/specializations/operators--learn-operator.json +5 -0
- package/agent-packs/specializations/operators--localization-operator.json +5 -0
- package/agent-packs/specializations/operators--operators.json +5 -0
- package/agent-packs/specializations/operators--pay-operator.json +5 -0
- package/agent-packs/specializations/operators--research-and-intelligence.json +5 -0
- package/agent-packs/specializations/operators--roadmap-operator.json +5 -0
- package/agent-packs/specializations/operators--social-content-operator.json +5 -0
- package/agent-packs/specializations/operators--talent-operations.json +5 -0
- package/agent-packs/specializations/operators--web-operator.json +5 -0
- package/agent-packs/specializations/operators--workflow-operator.json +5 -0
- package/agent-packs/specializations/specialists--adversarial-qa.json +5 -0
- package/agent-packs/specializations/specialists--backlog-dispatch.json +5 -0
- package/agent-packs/specializations/specialists--build-01.json +5 -0
- package/agent-packs/specializations/specialists--build-02.json +5 -0
- package/agent-packs/specializations/specialists--build-03.json +5 -0
- package/agent-packs/specializations/specialists--developer-environment-steward.json +5 -0
- package/agent-packs/specializations/specialists--documentation-knowledge-steward.json +5 -0
- package/agent-packs/specializations/specialists--execution-readiness.json +5 -0
- package/agent-packs/specializations/specialists--incident-triage.json +5 -0
- package/agent-packs/specializations/specialists--platform-package-steward.json +5 -0
- package/agent-packs/specializations/specialists--product-direction-01.json +5 -0
- package/agent-packs/specializations/specialists--product-direction-02.json +5 -0
- package/agent-packs/specializations/specialists--release-recovery.json +5 -0
- package/agent-packs/specializations/specialists--release-watch.json +5 -0
- package/agent-packs/specializations/specialists--roadmap-planning-01.json +5 -0
- package/agent-packs/specializations/specialists--roadmap-planning-02.json +5 -0
- package/agent-packs/specializations/specialists--security-permissions-review.json +5 -0
- package/agent-packs/specializations/specialists--system-architecture-01.json +5 -0
- package/agent-packs/specializations/specialists--system-architecture-02.json +5 -0
- package/agent-packs/specializations/specialists--translation.json +5 -0
- package/agent-packs/specializations/specialists--ux-consistency-review.json +5 -0
- package/agent-packs/specializations/specialists--workflow-improvement.json +5 -0
- package/agent-packs/specializations/specialists--worktree-retirement.json +5 -0
- package/agent-packs/src/topolo_agent_pack/cicd.py +101 -0
- package/agent-packs/src/topolo_agent_pack/claude.py +22 -7
- package/agent-packs/src/topolo_agent_pack/claude_activation.py +157 -0
- package/agent-packs/src/topolo_agent_pack/claude_completion_recovery.py +216 -0
- package/agent-packs/src/topolo_agent_pack/claude_desktop.py +181 -0
- package/agent-packs/src/topolo_agent_pack/claude_dispatch.py +240 -0
- package/agent-packs/src/topolo_agent_pack/claude_prompt.py +74 -0
- package/agent-packs/src/topolo_agent_pack/claude_runner.py +207 -0
- package/agent-packs/src/topolo_agent_pack/claude_service.py +397 -0
- package/agent-packs/src/topolo_agent_pack/cli.py +188 -18
- package/agent-packs/src/topolo_agent_pack/closed_ledger_fence.py +118 -0
- package/agent-packs/src/topolo_agent_pack/cloud_attach.py +128 -0
- package/agent-packs/src/topolo_agent_pack/cloud_cutover.py +134 -0
- package/agent-packs/src/topolo_agent_pack/cloud_delta.py +162 -0
- package/agent-packs/src/topolo_agent_pack/cloud_migrate.py +142 -0
- package/agent-packs/src/topolo_agent_pack/cloud_recovery.py +42 -0
- package/agent-packs/src/topolo_agent_pack/cloud_work.py +126 -0
- package/agent-packs/src/topolo_agent_pack/coordinator_activity.py +27 -0
- package/agent-packs/src/topolo_agent_pack/coordinator_context.py +91 -0
- package/agent-packs/src/topolo_agent_pack/coordinator_refresh.py +116 -0
- package/agent-packs/src/topolo_agent_pack/desktop_acceptance.py +45 -0
- package/agent-packs/src/topolo_agent_pack/desktop_launcher.py +114 -0
- package/agent-packs/src/topolo_agent_pack/domain_context.py +38 -0
- package/agent-packs/src/topolo_agent_pack/execution.py +104 -7
- package/agent-packs/src/topolo_agent_pack/fresh.py +1 -1
- package/agent-packs/src/topolo_agent_pack/frontdoor.py +23 -0
- package/agent-packs/src/topolo_agent_pack/linked_task_context.py +80 -0
- package/agent-packs/src/topolo_agent_pack/live.py +285 -18
- package/agent-packs/src/topolo_agent_pack/native.py +160 -4
- package/agent-packs/src/topolo_agent_pack/policy.py +8 -0
- package/agent-packs/src/topolo_agent_pack/review_context.py +33 -0
- package/agent-packs/src/topolo_agent_pack/role_catalog.py +137 -0
- package/agent-packs/src/topolo_agent_pack/role_context.py +63 -0
- package/agent-packs/src/topolo_agent_pack/role_refresh.py +50 -0
- package/agent-packs/src/topolo_agent_pack/task_models.py +11 -7
- package/agent-packs/src/topolo_agent_pack/throughput.py +149 -0
- package/agent-packs/src/topolo_agent_pack/topolo.py +7 -1
- package/agent-packs/src/topolo_agent_pack/work.py +322 -0
- package/agent-packs/src/topolo_agent_pack/work_adoption.py +122 -0
- package/agent-packs/src/topolo_agent_pack/work_artifacts.py +84 -0
- package/agent-packs/src/topolo_agent_pack/work_context.py +77 -0
- package/agent-packs/src/topolo_agent_pack/work_gui.py +51 -0
- package/agent-packs/src/topolo_agent_pack/work_native.py +414 -0
- package/agent-packs/src/topolo_agent_pack/work_wait.py +151 -0
- package/agent-packs/templates/topolo-coordinators/AGENTS.md +7 -0
- package/agent-packs/templates/topolo-coordinators/agents/intakes/cicd/AGENTS.md +6 -0
- package/agent-packs/templates/topolo-coordinators/agents/intakes/cicd/config.json +4 -0
- package/agent-packs/templates/topolo-coordinators/agents/intakes/engineering/AGENTS.md +3 -0
- package/agent-packs/templates/topolo-coordinators/agents/intakes/engineering/config.json +4 -0
- package/agent-packs/templates/topolo-coordinators/agents/intakes/operator-01/AGENTS.md +3 -0
- package/agent-packs/templates/topolo-coordinators/agents/intakes/operator-01/config.json +4 -0
- package/agent-packs/templates/topolo-coordinators/pack.json +56 -0
- package/dist/chunk-NYDIAYVY.js +144 -0
- package/dist/{claude-pack-backend-YEVPAOID.js → chunk-UY5LEU5C.js} +1659 -21
- package/dist/claude-desktop-profile-JCQKSY3K.js +13 -0
- package/dist/claude-pack-activation-Q25MCEPU.js +506 -0
- package/dist/claude-pack-backend-HUTKGIDS.js +90 -0
- package/dist/index.js +408 -164
- package/package.json +8 -6
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "topolo-coordinators",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"name": "Topolo task coordinators",
|
|
6
|
+
"purpose": "Three human front doors; specialists are cloud definitions and single-use task workers, not precreated chats.",
|
|
7
|
+
"agents": [
|
|
8
|
+
{
|
|
9
|
+
"set": "intakes",
|
|
10
|
+
"id": "engineering",
|
|
11
|
+
"title": "Topolo Engineering",
|
|
12
|
+
"pinned": true,
|
|
13
|
+
"position": 0,
|
|
14
|
+
"sectionName": "Pinned",
|
|
15
|
+
"aliases": [
|
|
16
|
+
"engineering"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"set": "intakes",
|
|
21
|
+
"id": "operator-01",
|
|
22
|
+
"title": "Topolo Operator",
|
|
23
|
+
"pinned": true,
|
|
24
|
+
"position": 1,
|
|
25
|
+
"sectionName": "Pinned",
|
|
26
|
+
"aliases": [
|
|
27
|
+
"operator-01"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"set": "intakes",
|
|
32
|
+
"id": "cicd",
|
|
33
|
+
"title": "Topolo CI/CD",
|
|
34
|
+
"pinned": true,
|
|
35
|
+
"position": 2,
|
|
36
|
+
"sectionName": "Pinned",
|
|
37
|
+
"aliases": [
|
|
38
|
+
"cicd"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"applications": [
|
|
44
|
+
"app_topolo_agent",
|
|
45
|
+
"app_topolo_docs",
|
|
46
|
+
"app_topolo_bytes"
|
|
47
|
+
],
|
|
48
|
+
"capabilities": [
|
|
49
|
+
"production credential-scoped Topolo CLI or MCP",
|
|
50
|
+
"conditional canonical task ownership before dispatch"
|
|
51
|
+
],
|
|
52
|
+
"integrationNotes": [
|
|
53
|
+
"Authenticate on the new machine, install the cloud role catalog and bind the existing activated task dataset. Never restore conversation history or adopt old workers implicitly."
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lib/claude-desktop-profile.ts
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import { createHash, randomUUID } from "crypto";
|
|
7
|
+
import { spawnSync } from "child_process";
|
|
8
|
+
function launchClaudeDesktopProfile(options, run = spawnSync) {
|
|
9
|
+
const root = fs.realpathSync(options.root), uid = process.getuid?.();
|
|
10
|
+
const ownedDirectory = (value) => {
|
|
11
|
+
const s = fs.lstatSync(value);
|
|
12
|
+
if (!path.isAbsolute(value) || fs.realpathSync(value) !== value || !s.isDirectory() || s.isSymbolicLink() || s.uid !== uid || s.mode & 18) throw Error("Exact owned private Desktop profile directories required.");
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
15
|
+
ownedDirectory(root);
|
|
16
|
+
const lock = path.join(root, ".claude-profile-launch.lock");
|
|
17
|
+
let lockfd;
|
|
18
|
+
if (options.apply) {
|
|
19
|
+
try {
|
|
20
|
+
lockfd = fs.openSync(lock, "wx", 384);
|
|
21
|
+
fs.writeFileSync(lockfd, JSON.stringify({ pid: process.pid }) + "\n");
|
|
22
|
+
fs.fsyncSync(lockfd);
|
|
23
|
+
} catch {
|
|
24
|
+
throw Error("Managed Desktop launch already has an owner; reconcile without duplicate launch.");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const userData = ownedDirectory(options.userData), codeConfig = ownedDirectory(options.codeConfig);
|
|
29
|
+
if (userData === codeConfig || userData.startsWith(codeConfig + path.sep) || codeConfig.startsWith(userData + path.sep)) throw Error("Desktop and SDK profile directories must be distinct.");
|
|
30
|
+
const policy = JSON.parse(fs.readFileSync(options.policy, "utf8"));
|
|
31
|
+
if (policy.format !== "topolo-agent-execution-policy" || policy.pack !== options.pack || policy.installationConsent?.profile !== "full-access" || policy.installationConsent?.principalId === void 0) throw Error("Current reviewed full-access installation policy required for managed Desktop launch.");
|
|
32
|
+
const app = options.app ?? "/Applications/Claude.app", binary = path.join(app, "Contents/MacOS/Claude");
|
|
33
|
+
if (!path.isAbsolute(app) || fs.realpathSync(app) !== app || !fs.lstatSync(app).isDirectory() || !fs.lstatSync(binary).isFile()) throw Error("Installed physical Claude application required.");
|
|
34
|
+
const config = {
|
|
35
|
+
format: "topolo-claude-desktop-profile",
|
|
36
|
+
schemaVersion: 1,
|
|
37
|
+
root,
|
|
38
|
+
pack: options.pack,
|
|
39
|
+
userData,
|
|
40
|
+
codeConfig,
|
|
41
|
+
app,
|
|
42
|
+
consentDigest: createHash("sha256").update(JSON.stringify(policy.installationConsent)).digest("hex")
|
|
43
|
+
};
|
|
44
|
+
const directory = path.join(root, "claude");
|
|
45
|
+
fs.mkdirSync(directory, { recursive: true, mode: 448 });
|
|
46
|
+
ownedDirectory(directory);
|
|
47
|
+
const file = path.join(directory, "desktop-profile.json");
|
|
48
|
+
const read = () => {
|
|
49
|
+
const s = fs.lstatSync(file);
|
|
50
|
+
if (!s.isFile() || s.isSymbolicLink() || s.uid !== uid || s.mode & 63 || s.nlink !== 1) throw Error("Private owned Desktop profile receipt required.");
|
|
51
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
52
|
+
};
|
|
53
|
+
const before = fs.existsSync(file) ? read() : null;
|
|
54
|
+
if (before && JSON.stringify(before.profile) !== JSON.stringify(config)) throw Error("Managed Desktop profile identity or installation consent changed.");
|
|
55
|
+
const observed = run("/bin/ps", ["-axo", "pid=,uid=,command="], { encoding: "utf8", timeout: 1e4, maxBuffer: 1048576 });
|
|
56
|
+
if (observed.error || observed.status !== 0) throw Error("Desktop process ownership observation unavailable.");
|
|
57
|
+
const matches = String(observed.stdout).split("\n").map((line) => /^\s*(\d+)\s+(\d+)\s+(.+)$/.exec(line)).filter(Boolean).filter((m) => m[3].startsWith(binary + " ") && (m[3].endsWith(" --user-data-dir=" + userData) || m[3].includes(" --user-data-dir=" + userData + " --")));
|
|
58
|
+
if (matches.length > 1 || matches.some((m) => Number(m[2]) !== uid)) throw Error("Managed Desktop process ownership is ambiguous.");
|
|
59
|
+
const pid = matches.length ? Number(matches[0][1]) : null;
|
|
60
|
+
if (!options.apply) return { state: "desktop-profile-launch-preflight", profile: config, pid, nativeStartup: false };
|
|
61
|
+
if (before?.state === "launch-may-have-effects" && !pid) throw Error("Unacknowledged Desktop launch requires reconciliation; never launch a duplicate.");
|
|
62
|
+
if (before?.state && !["launch-may-have-effects", "native-profile-verified"].includes(before.state)) throw Error("Unknown Desktop profile launch state.");
|
|
63
|
+
if (pid && before) return { state: "desktop-profile-existing-unverified", profile: config, pid, nativeStartup: false };
|
|
64
|
+
if (!pid && before?.pid) {
|
|
65
|
+
try {
|
|
66
|
+
process.kill(before.pid, 0);
|
|
67
|
+
throw Error("Previous managed process is alive.");
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (error.code !== "ESRCH") throw Error("Previous managed Desktop process is not independently proven dead.");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const help = pid ? null : run("/usr/bin/open", ["-h"], { encoding: "utf8", timeout: 1e4, maxBuffer: 65536 });
|
|
73
|
+
if (help && (help.error || !String(help.stdout ?? "").concat(String(help.stderr ?? "")).includes("--env"))) throw Error("LaunchServices per-application environment capability unavailable.");
|
|
74
|
+
const record = { profile: config, operationId: randomUUID(), state: "launch-may-have-effects", history: before ? [...before.history ?? [], { operationId: before.operationId, state: before.state, pid: before.pid ?? null }] : [] };
|
|
75
|
+
const temporary = file + "." + record.operationId + ".tmp";
|
|
76
|
+
const fd = fs.openSync(temporary, "wx", 384);
|
|
77
|
+
try {
|
|
78
|
+
fs.writeFileSync(fd, JSON.stringify(record) + "\n");
|
|
79
|
+
fs.fsyncSync(fd);
|
|
80
|
+
} finally {
|
|
81
|
+
fs.closeSync(fd);
|
|
82
|
+
}
|
|
83
|
+
if (before && JSON.stringify(read()) !== JSON.stringify(before)) throw Error("Desktop profile receipt changed before launch.");
|
|
84
|
+
fs.renameSync(temporary, file);
|
|
85
|
+
const dirfd = fs.openSync(directory, "r");
|
|
86
|
+
try {
|
|
87
|
+
fs.fsyncSync(dirfd);
|
|
88
|
+
} finally {
|
|
89
|
+
fs.closeSync(dirfd);
|
|
90
|
+
}
|
|
91
|
+
if (pid) return { state: "desktop-profile-existing-unverified", profile: config, pid, nativeStartup: false };
|
|
92
|
+
const launched = run("/usr/bin/open", ["-n", "-a", app, "--env", "CLAUDE_CONFIG_DIR=" + codeConfig, "--args", "--user-data-dir=" + userData], { encoding: "utf8", timeout: 2e4, maxBuffer: 65536 });
|
|
93
|
+
if (launched.error || launched.status !== 0) throw Error("Desktop LaunchServices acknowledgement missing; preserve launch receipt without replay.");
|
|
94
|
+
return { state: "desktop-profile-launch-requested", profile: config, operationId: record.operationId, nativeStartup: false };
|
|
95
|
+
} finally {
|
|
96
|
+
if (lockfd !== void 0) {
|
|
97
|
+
fs.closeSync(lockfd);
|
|
98
|
+
fs.unlinkSync(lock);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function verifyClaudeDesktopProfileNative(expected, pid, app, manager, env) {
|
|
103
|
+
if (!expected || expected.format !== "topolo-claude-desktop-profile" || expected.schemaVersion !== 1 || app.getName() !== "Claude" || app.getPath("userData") !== expected.userData || manager.userDataPath !== expected.userData || env.CLAUDE_CONFIG_DIR !== expected.codeConfig)
|
|
104
|
+
throw Error("Native Desktop profile or SDK history root differs; do not import or recreate identities.");
|
|
105
|
+
return { state: "native-profile-verified", pid, userData: expected.userData, codeConfig: expected.codeConfig };
|
|
106
|
+
}
|
|
107
|
+
function readClaudeDesktopProfile(root) {
|
|
108
|
+
const file = path.join(root, "claude/desktop-profile.json");
|
|
109
|
+
if (!fs.existsSync(file)) return null;
|
|
110
|
+
const s = fs.lstatSync(file);
|
|
111
|
+
if (!s.isFile() || s.isSymbolicLink() || s.uid !== process.getuid?.() || s.mode & 63 || s.nlink !== 1 || s.size > 1048576) throw Error("Private owned Desktop profile receipt required.");
|
|
112
|
+
const record = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
113
|
+
if (record.profile?.root !== root || !["launch-may-have-effects", "native-profile-verified"].includes(record.state)) throw Error("Desktop profile receipt differs.");
|
|
114
|
+
return record;
|
|
115
|
+
}
|
|
116
|
+
function acknowledgeClaudeDesktopProfile(root, before, proof) {
|
|
117
|
+
const file = path.join(root, "claude/desktop-profile.json");
|
|
118
|
+
if (JSON.stringify(readClaudeDesktopProfile(root)) !== JSON.stringify(before) || proof?.state !== "native-profile-verified" || !Number.isSafeInteger(proof.pid) || proof.pid < 1 || proof.userData !== before.profile.userData || proof.codeConfig !== before.profile.codeConfig) throw Error("Native profile acknowledgement or durable custody changed.");
|
|
119
|
+
if (before.state === "native-profile-verified" && before.pid === proof.pid) return before;
|
|
120
|
+
const row = { ...before, state: "native-profile-verified", pid: proof.pid, history: [...before.history ?? [], { operationId: before.operationId, state: before.state, pid: before.pid ?? null }] }, temporary = file + "." + randomUUID() + ".tmp";
|
|
121
|
+
const fd = fs.openSync(temporary, "wx", 384);
|
|
122
|
+
try {
|
|
123
|
+
fs.writeFileSync(fd, JSON.stringify(row) + "\n");
|
|
124
|
+
fs.fsyncSync(fd);
|
|
125
|
+
} finally {
|
|
126
|
+
fs.closeSync(fd);
|
|
127
|
+
}
|
|
128
|
+
if (JSON.stringify(readClaudeDesktopProfile(root)) !== JSON.stringify(before)) throw Error("Desktop profile changed during acknowledgement.");
|
|
129
|
+
fs.renameSync(temporary, file);
|
|
130
|
+
const dir = fs.openSync(path.dirname(file), "r");
|
|
131
|
+
try {
|
|
132
|
+
fs.fsyncSync(dir);
|
|
133
|
+
} finally {
|
|
134
|
+
fs.closeSync(dir);
|
|
135
|
+
}
|
|
136
|
+
return row;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export {
|
|
140
|
+
launchClaudeDesktopProfile,
|
|
141
|
+
verifyClaudeDesktopProfileNative,
|
|
142
|
+
readClaudeDesktopProfile,
|
|
143
|
+
acknowledgeClaudeDesktopProfile
|
|
144
|
+
};
|