mancode 0.3.16 → 0.3.17
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.en.md +3 -3
- package/README.md +3 -3
- package/dist/cli.js +1127 -765
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2651,8 +2651,10 @@ function isNotFound4(error) {
|
|
|
2651
2651
|
}
|
|
2652
2652
|
|
|
2653
2653
|
// src/runtime/task-operation.ts
|
|
2654
|
+
import { execFile as execFileCallback2 } from "child_process";
|
|
2654
2655
|
import { lstat as lstat4, mkdir as mkdir10, readFile as readFile11, rm as rm4, writeFile as writeFile10 } from "fs/promises";
|
|
2655
2656
|
import path11 from "path";
|
|
2657
|
+
import { promisify as promisify2 } from "util";
|
|
2656
2658
|
|
|
2657
2659
|
// src/context/compatibility.ts
|
|
2658
2660
|
function evaluateCompatibilityGate(input) {
|
|
@@ -4420,6 +4422,7 @@ function isNotFound10(error) {
|
|
|
4420
4422
|
}
|
|
4421
4423
|
|
|
4422
4424
|
// src/runtime/task-operation.ts
|
|
4425
|
+
var execFile2 = promisify2(execFileCallback2);
|
|
4423
4426
|
var TASK_AUTHORITY_FILES = new Set(TASK_AUTHORITY_FILE_NAMES);
|
|
4424
4427
|
async function openV3TaskOperation(input) {
|
|
4425
4428
|
const projectRoot = path11.resolve(requireProjectRoot(input.projectRoot));
|
|
@@ -4493,11 +4496,22 @@ async function openV3TaskOperation(input) {
|
|
|
4493
4496
|
throw new Error("MANCODE_TASK_HEAD_FENCE_MISSING");
|
|
4494
4497
|
}
|
|
4495
4498
|
if (input.allowTaskHeadFenceMismatch !== true) {
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4499
|
+
try {
|
|
4500
|
+
assertTaskHeadFenceMatchesAggregate(
|
|
4501
|
+
coordination.taskHeadFence,
|
|
4502
|
+
task.aggregate,
|
|
4503
|
+
codeHead
|
|
4504
|
+
);
|
|
4505
|
+
} catch (error) {
|
|
4506
|
+
await assertOwnerCodeHeadAdvance({
|
|
4507
|
+
projectRoot,
|
|
4508
|
+
task,
|
|
4509
|
+
fence: coordination.taskHeadFence,
|
|
4510
|
+
codeHead,
|
|
4511
|
+
actorId: session.actorId,
|
|
4512
|
+
originalError: error
|
|
4513
|
+
});
|
|
4514
|
+
}
|
|
4501
4515
|
}
|
|
4502
4516
|
}
|
|
4503
4517
|
return {
|
|
@@ -4527,6 +4541,21 @@ async function openV3TaskOperation(input) {
|
|
|
4527
4541
|
throw error;
|
|
4528
4542
|
}
|
|
4529
4543
|
}
|
|
4544
|
+
async function assertOwnerCodeHeadAdvance(input) {
|
|
4545
|
+
const { task, fence } = input;
|
|
4546
|
+
if (task.aggregate === null || task.metadata.ownerActorId !== input.actorId || fence.taskRevision !== task.metadata.revision || fence.ownershipEpoch !== task.metadata.ownershipEpoch || fence.aggregateDigest !== taskAggregateDigest(task.aggregate)) {
|
|
4547
|
+
throw input.originalError;
|
|
4548
|
+
}
|
|
4549
|
+
try {
|
|
4550
|
+
await execFile2(
|
|
4551
|
+
"git",
|
|
4552
|
+
["merge-base", "--is-ancestor", fence.codeRef.head, input.codeHead],
|
|
4553
|
+
{ cwd: input.projectRoot, windowsHide: true }
|
|
4554
|
+
);
|
|
4555
|
+
} catch {
|
|
4556
|
+
throw input.originalError;
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4530
4559
|
async function assertTaskParentIsWritable(store, task) {
|
|
4531
4560
|
if (task.metadata.parent === null) return;
|
|
4532
4561
|
try {
|
|
@@ -7638,9 +7667,9 @@ function compareUtf83(left, right) {
|
|
|
7638
7667
|
}
|
|
7639
7668
|
|
|
7640
7669
|
// src/context/task-head-reconcile.ts
|
|
7641
|
-
import { execFile as
|
|
7670
|
+
import { execFile as execFileCallback4 } from "child_process";
|
|
7642
7671
|
import path15 from "path";
|
|
7643
|
-
import { promisify as
|
|
7672
|
+
import { promisify as promisify4 } from "util";
|
|
7644
7673
|
|
|
7645
7674
|
// src/team/conflicts.ts
|
|
7646
7675
|
function deriveClaimValidity(claim, context) {
|
|
@@ -7838,12 +7867,12 @@ function unique(values) {
|
|
|
7838
7867
|
}
|
|
7839
7868
|
|
|
7840
7869
|
// src/team/git-ref-transport.ts
|
|
7841
|
-
import { execFile as
|
|
7870
|
+
import { execFile as execFileCallback3 } from "child_process";
|
|
7842
7871
|
import { mkdtemp, rm as rm6, writeFile as writeFile12 } from "fs/promises";
|
|
7843
7872
|
import { tmpdir } from "os";
|
|
7844
7873
|
import path14 from "path";
|
|
7845
|
-
import { promisify as
|
|
7846
|
-
var
|
|
7874
|
+
import { promisify as promisify3 } from "util";
|
|
7875
|
+
var execFile3 = promisify3(execFileCallback3);
|
|
7847
7876
|
var TEAM_REF = "refs/mancode/team";
|
|
7848
7877
|
var MAX_MANIFEST_BYTES = 1e6;
|
|
7849
7878
|
var MAX_ACTOR_PROFILES = 256;
|
|
@@ -8057,6 +8086,12 @@ var GitRefTeamManifestStore = class {
|
|
|
8057
8086
|
const previousFence = base.ownershipFences.find(
|
|
8058
8087
|
(candidate) => sameTaskRef(candidate.taskRef, taskRef)
|
|
8059
8088
|
);
|
|
8089
|
+
const previousTaskBundle = base.taskBundles.find(
|
|
8090
|
+
(bundle) => sameTaskRef(bundle.taskRef, taskRef)
|
|
8091
|
+
);
|
|
8092
|
+
if ((previousTaskBundle?.bundleDigest ?? null) !== input.expectedTaskBundleDigest) {
|
|
8093
|
+
throw new Error("MANCODE_TASK_BUNDLE_DIVERGED");
|
|
8094
|
+
}
|
|
8060
8095
|
if (!base.actorProfiles.some((profile) => profile.actorId === input.actorId)) {
|
|
8061
8096
|
throw new Error("MANCODE_TRANSPORT_ACTOR_NOT_JOINED");
|
|
8062
8097
|
}
|
|
@@ -8088,9 +8123,7 @@ var GitRefTeamManifestStore = class {
|
|
|
8088
8123
|
previousHandoffs: base.handoffs.filter(
|
|
8089
8124
|
(handoff) => sameTaskRef(handoff.taskRef, taskRef)
|
|
8090
8125
|
),
|
|
8091
|
-
previousTaskBundle
|
|
8092
|
-
(bundle) => sameTaskRef(bundle.taskRef, taskRef)
|
|
8093
|
-
),
|
|
8126
|
+
previousTaskBundle,
|
|
8094
8127
|
expectedOwnershipEpoch,
|
|
8095
8128
|
nextRevision,
|
|
8096
8129
|
fence,
|
|
@@ -9690,7 +9723,7 @@ async function gitShow(projectRoot, revision) {
|
|
|
9690
9723
|
}
|
|
9691
9724
|
}
|
|
9692
9725
|
async function runGit2(projectRoot, arguments_, env = process.env) {
|
|
9693
|
-
const result2 = await
|
|
9726
|
+
const result2 = await execFile3("git", arguments_, {
|
|
9694
9727
|
cwd: projectRoot,
|
|
9695
9728
|
env,
|
|
9696
9729
|
windowsHide: true,
|
|
@@ -9904,7 +9937,7 @@ function createGitRefTeamManifestStore(projectRoot, config, manifest) {
|
|
|
9904
9937
|
}
|
|
9905
9938
|
|
|
9906
9939
|
// src/context/task-head-reconcile.ts
|
|
9907
|
-
var
|
|
9940
|
+
var execFile4 = promisify4(execFileCallback4);
|
|
9908
9941
|
async function previewV3TaskHeadReconcile(input) {
|
|
9909
9942
|
const taskRef = parseTaskRefValue(input.taskRef);
|
|
9910
9943
|
if (taskRef.namespace !== "shared") {
|
|
@@ -10125,13 +10158,13 @@ async function assertGitSourcedTaskAggregate(projectRoot, taskRoot2) {
|
|
|
10125
10158
|
"verification-ledger.json"
|
|
10126
10159
|
].map((file) => path15.join(relativeTaskRoot, file));
|
|
10127
10160
|
try {
|
|
10128
|
-
await
|
|
10161
|
+
await execFile4("git", ["rev-parse", "--verify", "HEAD^{commit}"], {
|
|
10129
10162
|
cwd: projectRoot,
|
|
10130
10163
|
encoding: "utf8",
|
|
10131
10164
|
timeout: 5e3,
|
|
10132
10165
|
maxBuffer: 64 * 1024
|
|
10133
10166
|
});
|
|
10134
|
-
await
|
|
10167
|
+
await execFile4(
|
|
10135
10168
|
"git",
|
|
10136
10169
|
["ls-files", "--error-unmatch", "--", ...authorityFiles],
|
|
10137
10170
|
{
|
|
@@ -10141,13 +10174,13 @@ async function assertGitSourcedTaskAggregate(projectRoot, taskRoot2) {
|
|
|
10141
10174
|
maxBuffer: 64 * 1024
|
|
10142
10175
|
}
|
|
10143
10176
|
);
|
|
10144
|
-
await
|
|
10177
|
+
await execFile4("git", ["diff", "--quiet", "HEAD", "--", relativeTaskRoot], {
|
|
10145
10178
|
cwd: projectRoot,
|
|
10146
10179
|
encoding: "utf8",
|
|
10147
10180
|
timeout: 5e3,
|
|
10148
10181
|
maxBuffer: 64 * 1024
|
|
10149
10182
|
});
|
|
10150
|
-
await
|
|
10183
|
+
await execFile4(
|
|
10151
10184
|
"git",
|
|
10152
10185
|
["diff", "--cached", "--quiet", "--", relativeTaskRoot],
|
|
10153
10186
|
{
|
|
@@ -10157,7 +10190,7 @@ async function assertGitSourcedTaskAggregate(projectRoot, taskRoot2) {
|
|
|
10157
10190
|
maxBuffer: 64 * 1024
|
|
10158
10191
|
}
|
|
10159
10192
|
);
|
|
10160
|
-
const { stdout: status2 } = await
|
|
10193
|
+
const { stdout: status2 } = await execFile4(
|
|
10161
10194
|
"git",
|
|
10162
10195
|
[
|
|
10163
10196
|
"status",
|
|
@@ -18533,22 +18566,376 @@ function isAlreadyExists17(error) {
|
|
|
18533
18566
|
}
|
|
18534
18567
|
|
|
18535
18568
|
// src/team/git-ref-workflow-repair.ts
|
|
18536
|
-
import { lstat as
|
|
18537
|
-
import
|
|
18569
|
+
import { lstat as lstat17, mkdir as mkdir26, readFile as readFile29, readdir as readdir14, writeFile as writeFile29 } from "fs/promises";
|
|
18570
|
+
import path33 from "path";
|
|
18538
18571
|
|
|
18539
18572
|
// src/team/git-ref-materialization.ts
|
|
18540
18573
|
import {
|
|
18541
|
-
lstat as
|
|
18542
|
-
mkdir as
|
|
18543
|
-
readFile as
|
|
18544
|
-
readdir as
|
|
18574
|
+
lstat as lstat16,
|
|
18575
|
+
mkdir as mkdir25,
|
|
18576
|
+
readFile as readFile28,
|
|
18577
|
+
readdir as readdir13,
|
|
18545
18578
|
unlink as unlink2,
|
|
18546
|
-
writeFile as
|
|
18579
|
+
writeFile as writeFile28
|
|
18547
18580
|
} from "fs/promises";
|
|
18581
|
+
import path32 from "path";
|
|
18582
|
+
|
|
18583
|
+
// src/team/git-ref-bundle.ts
|
|
18584
|
+
import { execFile as execFileCallback5 } from "child_process";
|
|
18585
|
+
import { lstat as lstat14, mkdir as mkdir23, readFile as readFile26, readdir as readdir12, writeFile as writeFile26 } from "fs/promises";
|
|
18548
18586
|
import path30 from "path";
|
|
18587
|
+
import { promisify as promisify5 } from "util";
|
|
18588
|
+
var execFile5 = promisify5(execFileCallback5);
|
|
18589
|
+
function createGitRefTaskBundle(input) {
|
|
18590
|
+
const { task } = input;
|
|
18591
|
+
if (task.metadata.taskRef.namespace !== "shared") {
|
|
18592
|
+
throw new Error("MANCODE_REMOTE_COORDINATION_REQUIRES_SHARED_TASK");
|
|
18593
|
+
}
|
|
18594
|
+
if (task.aggregate === null) {
|
|
18595
|
+
throw new Error("MANCODE_TASK_UNAVAILABLE");
|
|
18596
|
+
}
|
|
18597
|
+
const artifacts = [
|
|
18598
|
+
artifact("metadata", "metadata.json", task.metadata),
|
|
18599
|
+
artifact("requirements", "requirements.json", task.requirements),
|
|
18600
|
+
artifact("review", "review-ledger.json", task.review),
|
|
18601
|
+
artifact("verification", "verification-ledger.json", task.verification)
|
|
18602
|
+
];
|
|
18603
|
+
if (task.latestCheckpoint !== null) {
|
|
18604
|
+
artifacts.push(
|
|
18605
|
+
artifact(
|
|
18606
|
+
"checkpoint",
|
|
18607
|
+
`checkpoints/${task.latestCheckpoint.checkpointId}.json`,
|
|
18608
|
+
task.latestCheckpoint
|
|
18609
|
+
)
|
|
18610
|
+
);
|
|
18611
|
+
}
|
|
18612
|
+
if (task.plan !== null) {
|
|
18613
|
+
artifacts.push(artifact("plan", "plan.md", task.plan.content));
|
|
18614
|
+
} else {
|
|
18615
|
+
artifacts.push(
|
|
18616
|
+
artifact(
|
|
18617
|
+
"summary",
|
|
18618
|
+
"summary.md",
|
|
18619
|
+
task.latestCheckpoint?.summary ?? `Task ${formatTaskRef(task.metadata.taskRef)} revision ${task.metadata.revision}.`
|
|
18620
|
+
)
|
|
18621
|
+
);
|
|
18622
|
+
}
|
|
18623
|
+
artifacts.sort(
|
|
18624
|
+
(left, right) => left.kind < right.kind ? -1 : left.kind > right.kind ? 1 : 0
|
|
18625
|
+
);
|
|
18626
|
+
const body = {
|
|
18627
|
+
schemaVersion: 1,
|
|
18628
|
+
taskRef: task.metadata.taskRef,
|
|
18629
|
+
taskRevision: task.metadata.revision,
|
|
18630
|
+
ownershipEpoch: task.metadata.ownershipEpoch,
|
|
18631
|
+
aggregate: task.aggregate,
|
|
18632
|
+
aggregateDigest: digestCanonicalJson(task.aggregate),
|
|
18633
|
+
codeRef: parseCodeRef(input.codeRef),
|
|
18634
|
+
artifacts,
|
|
18635
|
+
createdAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString()
|
|
18636
|
+
};
|
|
18637
|
+
return parseGitRefTaskBundle({
|
|
18638
|
+
...body,
|
|
18639
|
+
bundleDigest: gitRefTaskBundleDigest(body)
|
|
18640
|
+
});
|
|
18641
|
+
}
|
|
18642
|
+
async function assertGitRefBundleCodeReachable(projectRoot, bundle) {
|
|
18643
|
+
const parsed = parseGitRefTaskBundle(bundle);
|
|
18644
|
+
try {
|
|
18645
|
+
await execFile5(
|
|
18646
|
+
"git",
|
|
18647
|
+
["cat-file", "-e", `${parsed.codeRef.head}^{commit}`],
|
|
18648
|
+
{
|
|
18649
|
+
cwd: path30.resolve(projectRoot),
|
|
18650
|
+
windowsHide: true
|
|
18651
|
+
}
|
|
18652
|
+
);
|
|
18653
|
+
} catch {
|
|
18654
|
+
throw new Error("MANCODE_TASK_BUNDLE_CODE_UNREACHABLE");
|
|
18655
|
+
}
|
|
18656
|
+
}
|
|
18657
|
+
async function quarantineGitRefTaskBundle(projectRoot, remoteRevision, bundle) {
|
|
18658
|
+
if (!Number.isSafeInteger(remoteRevision) || remoteRevision < 1) {
|
|
18659
|
+
throw new Error("MANCODE_TRANSPORT_REVISION_INVALID");
|
|
18660
|
+
}
|
|
18661
|
+
const parsed = parseGitRefTaskBundle(bundle);
|
|
18662
|
+
const directory = path30.join(
|
|
18663
|
+
path30.resolve(projectRoot),
|
|
18664
|
+
".mancode",
|
|
18665
|
+
"local",
|
|
18666
|
+
"quarantine",
|
|
18667
|
+
"git-ref",
|
|
18668
|
+
parsed.taskRef.taskId,
|
|
18669
|
+
String(remoteRevision)
|
|
18670
|
+
);
|
|
18671
|
+
await ensureFixedDirectory(projectRoot, [
|
|
18672
|
+
".mancode",
|
|
18673
|
+
"local",
|
|
18674
|
+
"quarantine",
|
|
18675
|
+
"git-ref",
|
|
18676
|
+
parsed.taskRef.taskId,
|
|
18677
|
+
String(remoteRevision)
|
|
18678
|
+
]);
|
|
18679
|
+
const target = path30.join(directory, `${parsed.bundleDigest.slice(7)}.json`);
|
|
18680
|
+
try {
|
|
18681
|
+
await writeFile26(target, `${JSON.stringify(parsed, null, 2)}
|
|
18682
|
+
`, {
|
|
18683
|
+
encoding: "utf8",
|
|
18684
|
+
flag: "wx"
|
|
18685
|
+
});
|
|
18686
|
+
} catch (error) {
|
|
18687
|
+
if (!isAlreadyExists18(error)) throw error;
|
|
18688
|
+
}
|
|
18689
|
+
return target;
|
|
18690
|
+
}
|
|
18691
|
+
async function readQuarantinedGitRefTaskBundle(projectRoot, remoteRevision, taskRef, expected) {
|
|
18692
|
+
if (!Number.isSafeInteger(remoteRevision) || remoteRevision < 1) {
|
|
18693
|
+
throw new Error("MANCODE_TRANSPORT_REVISION_INVALID");
|
|
18694
|
+
}
|
|
18695
|
+
const parsedTaskRef = parseTaskRefValue(taskRef);
|
|
18696
|
+
const directory = path30.join(
|
|
18697
|
+
path30.resolve(projectRoot),
|
|
18698
|
+
".mancode",
|
|
18699
|
+
"local",
|
|
18700
|
+
"quarantine",
|
|
18701
|
+
"git-ref",
|
|
18702
|
+
parsedTaskRef.taskId,
|
|
18703
|
+
String(remoteRevision)
|
|
18704
|
+
);
|
|
18705
|
+
let entries;
|
|
18706
|
+
try {
|
|
18707
|
+
await assertFixedDirectory(projectRoot, [
|
|
18708
|
+
".mancode",
|
|
18709
|
+
"local",
|
|
18710
|
+
"quarantine",
|
|
18711
|
+
"git-ref",
|
|
18712
|
+
parsedTaskRef.taskId,
|
|
18713
|
+
String(remoteRevision)
|
|
18714
|
+
]);
|
|
18715
|
+
entries = await readdir12(directory);
|
|
18716
|
+
} catch (error) {
|
|
18717
|
+
if (isNotFound22(error)) return null;
|
|
18718
|
+
throw error;
|
|
18719
|
+
}
|
|
18720
|
+
const matches = [];
|
|
18721
|
+
for (const entry of entries.sort()) {
|
|
18722
|
+
if (!/^[a-f0-9]{64}\.json$/.test(entry)) continue;
|
|
18723
|
+
const target = path30.join(directory, entry);
|
|
18724
|
+
const before = await lstat14(target);
|
|
18725
|
+
if (!before.isFile() || before.isSymbolicLink()) {
|
|
18726
|
+
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18727
|
+
}
|
|
18728
|
+
const bundle = parseGitRefTaskBundle(
|
|
18729
|
+
JSON.parse(await readFile26(target, "utf8"))
|
|
18730
|
+
);
|
|
18731
|
+
const after = await lstat14(target);
|
|
18732
|
+
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
18733
|
+
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18734
|
+
}
|
|
18735
|
+
if (sameTaskRef(bundle.taskRef, parsedTaskRef) && bundle.taskRevision === expected.taskRevision && bundle.aggregateDigest === expected.aggregateDigest && bundle.ownershipEpoch === expected.ownershipEpoch && bundle.codeRef.head === expected.codeRefHead) {
|
|
18736
|
+
matches.push(bundle);
|
|
18737
|
+
}
|
|
18738
|
+
}
|
|
18739
|
+
if (matches.length > 1) {
|
|
18740
|
+
throw new Error("MANCODE_TRANSPORT_CACHE_CORRUPT");
|
|
18741
|
+
}
|
|
18742
|
+
return matches[0] ?? null;
|
|
18743
|
+
}
|
|
18744
|
+
function artifact(kind, relativePath, value) {
|
|
18745
|
+
const content = JSON.parse(JSON.stringify(value));
|
|
18746
|
+
return {
|
|
18747
|
+
kind,
|
|
18748
|
+
relativePath,
|
|
18749
|
+
content,
|
|
18750
|
+
contentDigest: digestCanonicalJson(content)
|
|
18751
|
+
};
|
|
18752
|
+
}
|
|
18753
|
+
function parseCodeRef(value) {
|
|
18754
|
+
if (typeof value.branch !== "string" || !value.branch.trim() || value.branch.includes("\0") || typeof value.head !== "string" || !/^[0-9a-f]{40,64}$/.test(value.head)) {
|
|
18755
|
+
throw new Error("MANCODE_TASK_BUNDLE_CODE_REF_INVALID");
|
|
18756
|
+
}
|
|
18757
|
+
return { branch: value.branch, head: value.head };
|
|
18758
|
+
}
|
|
18759
|
+
async function ensureFixedDirectory(projectRoot, segments) {
|
|
18760
|
+
let current = path30.resolve(projectRoot);
|
|
18761
|
+
for (const segment of segments) {
|
|
18762
|
+
current = path30.join(current, segment);
|
|
18763
|
+
try {
|
|
18764
|
+
await mkdir23(current);
|
|
18765
|
+
} catch (error) {
|
|
18766
|
+
if (!isAlreadyExists18(error)) throw error;
|
|
18767
|
+
}
|
|
18768
|
+
const entry = await lstat14(current);
|
|
18769
|
+
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
18770
|
+
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18771
|
+
}
|
|
18772
|
+
}
|
|
18773
|
+
}
|
|
18774
|
+
async function assertFixedDirectory(projectRoot, segments) {
|
|
18775
|
+
let current = path30.resolve(projectRoot);
|
|
18776
|
+
for (const segment of segments) {
|
|
18777
|
+
current = path30.join(current, segment);
|
|
18778
|
+
const entry = await lstat14(current);
|
|
18779
|
+
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
18780
|
+
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18781
|
+
}
|
|
18782
|
+
}
|
|
18783
|
+
}
|
|
18784
|
+
function isAlreadyExists18(error) {
|
|
18785
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
18786
|
+
}
|
|
18787
|
+
function isNotFound22(error) {
|
|
18788
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
18789
|
+
}
|
|
18790
|
+
|
|
18791
|
+
// src/team/git-ref-task-base.ts
|
|
18792
|
+
import { lstat as lstat15, mkdir as mkdir24, readFile as readFile27, writeFile as writeFile27 } from "fs/promises";
|
|
18793
|
+
import path31 from "path";
|
|
18794
|
+
async function readGitRefTaskRemoteBase(projectRoot, taskRef) {
|
|
18795
|
+
const parsedTaskRef = parseTaskRefValue(taskRef);
|
|
18796
|
+
const runtime = await readProjectRuntimeContext(projectRoot);
|
|
18797
|
+
const target = remoteBasePath(projectRoot, parsedTaskRef);
|
|
18798
|
+
try {
|
|
18799
|
+
await assertRemoteBaseDirectory(projectRoot);
|
|
18800
|
+
const before = await lstat15(target);
|
|
18801
|
+
if (!before.isFile() || before.isSymbolicLink()) {
|
|
18802
|
+
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18803
|
+
}
|
|
18804
|
+
const state = parseGitRefTaskRemoteBase(
|
|
18805
|
+
JSON.parse(await readFile27(target, "utf8"))
|
|
18806
|
+
);
|
|
18807
|
+
const after = await lstat15(target);
|
|
18808
|
+
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
18809
|
+
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18810
|
+
}
|
|
18811
|
+
if (state.workspaceId !== runtime.workspaceId || !sameTaskRef(state.taskRef, parsedTaskRef)) {
|
|
18812
|
+
return null;
|
|
18813
|
+
}
|
|
18814
|
+
return state;
|
|
18815
|
+
} catch (error) {
|
|
18816
|
+
if (isNotFound23(error)) return null;
|
|
18817
|
+
if (error instanceof SyntaxError) {
|
|
18818
|
+
throw new Error("MANCODE_TRANSPORT_CACHE_CORRUPT");
|
|
18819
|
+
}
|
|
18820
|
+
throw error;
|
|
18821
|
+
}
|
|
18822
|
+
}
|
|
18823
|
+
async function recordGitRefTaskRemoteBase(projectRoot, remoteRevision, bundle) {
|
|
18824
|
+
const parsedBundle = parseGitRefTaskBundle(bundle);
|
|
18825
|
+
const revision = positiveInteger2(remoteRevision);
|
|
18826
|
+
const runtime = await readProjectRuntimeContext(projectRoot);
|
|
18827
|
+
const state = parseGitRefTaskRemoteBase({
|
|
18828
|
+
schemaVersion: 1,
|
|
18829
|
+
workspaceId: runtime.workspaceId,
|
|
18830
|
+
taskRef: parsedBundle.taskRef,
|
|
18831
|
+
remoteRevision: revision,
|
|
18832
|
+
bundle: parsedBundle
|
|
18833
|
+
});
|
|
18834
|
+
const directory = await ensureRemoteBaseDirectory(projectRoot);
|
|
18835
|
+
const target = remoteBasePath(projectRoot, parsedBundle.taskRef);
|
|
18836
|
+
const temporary = path31.join(
|
|
18837
|
+
directory,
|
|
18838
|
+
`.${parsedBundle.taskRef.taskId}.${process.pid}.${Date.now()}.tmp`
|
|
18839
|
+
);
|
|
18840
|
+
await writeFile27(temporary, `${JSON.stringify(state, null, 2)}
|
|
18841
|
+
`, {
|
|
18842
|
+
encoding: "utf8",
|
|
18843
|
+
flag: "wx"
|
|
18844
|
+
});
|
|
18845
|
+
await replaceFileAtomically(temporary, target);
|
|
18846
|
+
return state;
|
|
18847
|
+
}
|
|
18848
|
+
function parseGitRefTaskRemoteBase(value) {
|
|
18849
|
+
assertRecord(value, "git-ref task remote base");
|
|
18850
|
+
assertKnownKeys(
|
|
18851
|
+
value,
|
|
18852
|
+
["schemaVersion", "workspaceId", "taskRef", "remoteRevision", "bundle"],
|
|
18853
|
+
"git-ref task remote base"
|
|
18854
|
+
);
|
|
18855
|
+
if (value.schemaVersion !== 1) {
|
|
18856
|
+
throw new Error("git-ref task remote base schemaVersion must be 1");
|
|
18857
|
+
}
|
|
18858
|
+
assertUlid(value.workspaceId, "git-ref task remote base workspaceId");
|
|
18859
|
+
const taskRef = parseTaskRefValue(value.taskRef);
|
|
18860
|
+
const bundle = parseGitRefTaskBundle(value.bundle);
|
|
18861
|
+
if (!sameTaskRef(taskRef, bundle.taskRef)) {
|
|
18862
|
+
throw new Error("MANCODE_TRANSPORT_CACHE_IDENTITY_MISMATCH");
|
|
18863
|
+
}
|
|
18864
|
+
return {
|
|
18865
|
+
schemaVersion: 1,
|
|
18866
|
+
workspaceId: value.workspaceId,
|
|
18867
|
+
taskRef,
|
|
18868
|
+
remoteRevision: positiveInteger2(value.remoteRevision),
|
|
18869
|
+
bundle
|
|
18870
|
+
};
|
|
18871
|
+
}
|
|
18872
|
+
async function ensureRemoteBaseDirectory(projectRoot) {
|
|
18873
|
+
let current = path31.resolve(projectRoot);
|
|
18874
|
+
for (const segment of [
|
|
18875
|
+
".mancode",
|
|
18876
|
+
"local",
|
|
18877
|
+
"cache",
|
|
18878
|
+
"git-ref",
|
|
18879
|
+
"remote-bases"
|
|
18880
|
+
]) {
|
|
18881
|
+
current = path31.join(current, segment);
|
|
18882
|
+
try {
|
|
18883
|
+
await mkdir24(current);
|
|
18884
|
+
} catch (error) {
|
|
18885
|
+
if (!isAlreadyExists19(error)) throw error;
|
|
18886
|
+
}
|
|
18887
|
+
const entry = await lstat15(current);
|
|
18888
|
+
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
18889
|
+
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18890
|
+
}
|
|
18891
|
+
}
|
|
18892
|
+
return current;
|
|
18893
|
+
}
|
|
18894
|
+
async function assertRemoteBaseDirectory(projectRoot) {
|
|
18895
|
+
let current = path31.resolve(projectRoot);
|
|
18896
|
+
for (const segment of [
|
|
18897
|
+
".mancode",
|
|
18898
|
+
"local",
|
|
18899
|
+
"cache",
|
|
18900
|
+
"git-ref",
|
|
18901
|
+
"remote-bases"
|
|
18902
|
+
]) {
|
|
18903
|
+
current = path31.join(current, segment);
|
|
18904
|
+
const entry = await lstat15(current);
|
|
18905
|
+
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
18906
|
+
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18907
|
+
}
|
|
18908
|
+
}
|
|
18909
|
+
}
|
|
18910
|
+
function remoteBasePath(projectRoot, taskRef) {
|
|
18911
|
+
const parsed = parseTaskRefValue(taskRef);
|
|
18912
|
+
return path31.join(
|
|
18913
|
+
path31.resolve(projectRoot),
|
|
18914
|
+
".mancode",
|
|
18915
|
+
"local",
|
|
18916
|
+
"cache",
|
|
18917
|
+
"git-ref",
|
|
18918
|
+
"remote-bases",
|
|
18919
|
+
`${parsed.taskId}.json`
|
|
18920
|
+
);
|
|
18921
|
+
}
|
|
18922
|
+
function positiveInteger2(value) {
|
|
18923
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1) {
|
|
18924
|
+
throw new Error("MANCODE_TRANSPORT_REVISION_INVALID");
|
|
18925
|
+
}
|
|
18926
|
+
return value;
|
|
18927
|
+
}
|
|
18928
|
+
function isAlreadyExists19(error) {
|
|
18929
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
18930
|
+
}
|
|
18931
|
+
function isNotFound23(error) {
|
|
18932
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
18933
|
+
}
|
|
18934
|
+
|
|
18935
|
+
// src/team/git-ref-materialization.ts
|
|
18549
18936
|
async function materializeGitRefTaskBundle(input) {
|
|
18550
|
-
const projectRoot =
|
|
18551
|
-
const remoteRevision =
|
|
18937
|
+
const projectRoot = path32.resolve(input.projectRoot);
|
|
18938
|
+
const remoteRevision = positiveInteger3(
|
|
18552
18939
|
input.remoteRevision,
|
|
18553
18940
|
"git-ref materialization remoteRevision"
|
|
18554
18941
|
);
|
|
@@ -18580,16 +18967,32 @@ async function materializeGitRefTaskBundle(input) {
|
|
|
18580
18967
|
);
|
|
18581
18968
|
const current = await readLocalTaskOrNull(projectRoot, bundle);
|
|
18582
18969
|
const currentFence = await readTaskHeadFence(store, bundle.taskRef);
|
|
18970
|
+
const recordedBase = await readGitRefTaskRemoteBase(
|
|
18971
|
+
projectRoot,
|
|
18972
|
+
bundle.taskRef
|
|
18973
|
+
);
|
|
18974
|
+
const quarantinedBase = recordedBase === null && currentFence !== null && currentFence.remoteRevision !== null ? await readQuarantinedGitRefTaskBundle(
|
|
18975
|
+
projectRoot,
|
|
18976
|
+
currentFence.remoteRevision,
|
|
18977
|
+
bundle.taskRef,
|
|
18978
|
+
{
|
|
18979
|
+
taskRevision: currentFence.taskRevision,
|
|
18980
|
+
aggregateDigest: currentFence.aggregateDigest,
|
|
18981
|
+
ownershipEpoch: currentFence.ownershipEpoch,
|
|
18982
|
+
codeRefHead: currentFence.codeRef.head
|
|
18983
|
+
}
|
|
18984
|
+
) : null;
|
|
18985
|
+
const effectivePredecessor = recordedBase?.bundle ?? quarantinedBase ?? predecessor;
|
|
18583
18986
|
const status2 = classifyMaterialization(
|
|
18584
18987
|
current,
|
|
18585
18988
|
bundle,
|
|
18586
|
-
|
|
18989
|
+
effectivePredecessor,
|
|
18587
18990
|
pendingMetadata
|
|
18588
18991
|
);
|
|
18589
18992
|
if (status2 === "created" && currentFence !== null) {
|
|
18590
18993
|
throw new Error("MANCODE_SPLIT_BRAIN");
|
|
18591
18994
|
}
|
|
18592
|
-
const materializedPredecessor = status2 === "created" ? null :
|
|
18995
|
+
const materializedPredecessor = status2 === "created" ? null : effectivePredecessor;
|
|
18593
18996
|
const targetFence = buildTargetFence({
|
|
18594
18997
|
runtime,
|
|
18595
18998
|
remoteRevision,
|
|
@@ -18601,6 +19004,7 @@ async function materializeGitRefTaskBundle(input) {
|
|
|
18601
19004
|
});
|
|
18602
19005
|
if (status2 === "unchanged") {
|
|
18603
19006
|
await writeTargetFence(store, currentFence, targetFence, predecessor);
|
|
19007
|
+
await recordGitRefTaskRemoteBase(projectRoot, remoteRevision, bundle);
|
|
18604
19008
|
return result(status2, bundle, null, targetFence);
|
|
18605
19009
|
}
|
|
18606
19010
|
const timestamp4 = now.toISOString();
|
|
@@ -18621,6 +19025,7 @@ async function materializeGitRefTaskBundle(input) {
|
|
|
18621
19025
|
journal = { ...journal, state: "applying", updatedAt: timestamp4 };
|
|
18622
19026
|
await replaceJournal(projectRoot, journal);
|
|
18623
19027
|
await applyJournal(projectRoot, journal);
|
|
19028
|
+
await recordGitRefTaskRemoteBase(projectRoot, remoteRevision, bundle);
|
|
18624
19029
|
journal = {
|
|
18625
19030
|
...journal,
|
|
18626
19031
|
state: "committed",
|
|
@@ -18646,6 +19051,11 @@ async function recoverTaskMaterializationsWhileLocked(projectRoot, taskId) {
|
|
|
18646
19051
|
continue;
|
|
18647
19052
|
}
|
|
18648
19053
|
await applyJournal(projectRoot, journal);
|
|
19054
|
+
await recordGitRefTaskRemoteBase(
|
|
19055
|
+
projectRoot,
|
|
19056
|
+
journal.remoteRevision,
|
|
19057
|
+
journal.targetBundle
|
|
19058
|
+
);
|
|
18649
19059
|
await replaceJournal(projectRoot, {
|
|
18650
19060
|
...journal,
|
|
18651
19061
|
state: "committed",
|
|
@@ -18812,7 +19222,7 @@ async function replaceVerifiedFile(taskRoot2, relativePath, targetContent, prede
|
|
|
18812
19222
|
const target = safeTaskPath(taskRoot2, relativePath);
|
|
18813
19223
|
await ensureSafeDirectory(
|
|
18814
19224
|
taskRoot2,
|
|
18815
|
-
|
|
19225
|
+
path32.dirname(relativePath).split(path32.sep)
|
|
18816
19226
|
);
|
|
18817
19227
|
const current = await readSafeFileOrNull(target);
|
|
18818
19228
|
if (contentMatches(relativePath, current, targetContent)) return;
|
|
@@ -18822,11 +19232,11 @@ async function replaceVerifiedFile(taskRoot2, relativePath, targetContent, prede
|
|
|
18822
19232
|
if (current === null && (predecessorContent !== null || alternatePredecessorContent !== null) && relativePath !== "summary.md") {
|
|
18823
19233
|
throw new Error("MANCODE_SPLIT_BRAIN");
|
|
18824
19234
|
}
|
|
18825
|
-
const temporary =
|
|
18826
|
-
|
|
18827
|
-
`.${
|
|
19235
|
+
const temporary = path32.join(
|
|
19236
|
+
path32.dirname(target),
|
|
19237
|
+
`.${path32.basename(target)}.${process.pid}.${Date.now()}.tmp`
|
|
18828
19238
|
);
|
|
18829
|
-
await
|
|
19239
|
+
await writeFile28(temporary, targetContent, { encoding: "utf8", flag: "wx" });
|
|
18830
19240
|
await replaceFileAtomically(temporary, target);
|
|
18831
19241
|
}
|
|
18832
19242
|
function contentMatches(relativePath, current, expected) {
|
|
@@ -18876,44 +19286,44 @@ async function removeVerifiedFile(taskRoot2, relativePath, predecessorContent) {
|
|
|
18876
19286
|
}
|
|
18877
19287
|
async function readSafeFileOrNull(target) {
|
|
18878
19288
|
try {
|
|
18879
|
-
const before = await
|
|
19289
|
+
const before = await lstat16(target);
|
|
18880
19290
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
18881
19291
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18882
19292
|
}
|
|
18883
|
-
const content = await
|
|
18884
|
-
const after = await
|
|
19293
|
+
const content = await readFile28(target, "utf8");
|
|
19294
|
+
const after = await lstat16(target);
|
|
18885
19295
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
18886
19296
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18887
19297
|
}
|
|
18888
19298
|
return content;
|
|
18889
19299
|
} catch (error) {
|
|
18890
|
-
if (
|
|
19300
|
+
if (isNotFound24(error)) return null;
|
|
18891
19301
|
throw error;
|
|
18892
19302
|
}
|
|
18893
19303
|
}
|
|
18894
19304
|
async function ensureSafeDirectory(root, segments) {
|
|
18895
|
-
let current =
|
|
19305
|
+
let current = path32.resolve(root);
|
|
18896
19306
|
for (const segment of segments) {
|
|
18897
19307
|
if (!segment || segment === ".") continue;
|
|
18898
19308
|
if (segment === ".." || segment.includes("/") || segment.includes("\\")) {
|
|
18899
19309
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18900
19310
|
}
|
|
18901
|
-
current =
|
|
19311
|
+
current = path32.join(current, segment);
|
|
18902
19312
|
try {
|
|
18903
|
-
await
|
|
19313
|
+
await mkdir25(current);
|
|
18904
19314
|
} catch (error) {
|
|
18905
|
-
if (!
|
|
19315
|
+
if (!isAlreadyExists20(error)) throw error;
|
|
18906
19316
|
}
|
|
18907
|
-
const entry = await
|
|
19317
|
+
const entry = await lstat16(current);
|
|
18908
19318
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
18909
19319
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18910
19320
|
}
|
|
18911
19321
|
}
|
|
18912
19322
|
}
|
|
18913
19323
|
function safeTaskPath(taskRoot2, relativePath) {
|
|
18914
|
-
const target =
|
|
18915
|
-
const relative =
|
|
18916
|
-
if (!relative || relative.startsWith("..") ||
|
|
19324
|
+
const target = path32.resolve(taskRoot2, relativePath);
|
|
19325
|
+
const relative = path32.relative(taskRoot2, target);
|
|
19326
|
+
if (!relative || relative.startsWith("..") || path32.isAbsolute(relative)) {
|
|
18917
19327
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18918
19328
|
}
|
|
18919
19329
|
return target;
|
|
@@ -18925,7 +19335,7 @@ async function createJournal(projectRoot, journal) {
|
|
|
18925
19335
|
"journals",
|
|
18926
19336
|
"git-ref-materialize"
|
|
18927
19337
|
]);
|
|
18928
|
-
await
|
|
19338
|
+
await writeFile28(
|
|
18929
19339
|
journalPath(projectRoot, journal.operationId),
|
|
18930
19340
|
serialize11(journal),
|
|
18931
19341
|
{
|
|
@@ -18936,11 +19346,11 @@ async function createJournal(projectRoot, journal) {
|
|
|
18936
19346
|
}
|
|
18937
19347
|
async function replaceJournal(projectRoot, journal) {
|
|
18938
19348
|
const target = journalPath(projectRoot, journal.operationId);
|
|
18939
|
-
const temporary =
|
|
18940
|
-
|
|
19349
|
+
const temporary = path32.join(
|
|
19350
|
+
path32.dirname(target),
|
|
18941
19351
|
`.${journal.operationId}.${process.pid}.${Date.now()}.tmp`
|
|
18942
19352
|
);
|
|
18943
|
-
await
|
|
19353
|
+
await writeFile28(temporary, serialize11(journal), {
|
|
18944
19354
|
encoding: "utf8",
|
|
18945
19355
|
flag: "wx"
|
|
18946
19356
|
});
|
|
@@ -18948,7 +19358,7 @@ async function replaceJournal(projectRoot, journal) {
|
|
|
18948
19358
|
}
|
|
18949
19359
|
async function readJournal(target) {
|
|
18950
19360
|
try {
|
|
18951
|
-
const raw = JSON.parse(await
|
|
19361
|
+
const raw = JSON.parse(await readFile28(target, "utf8"));
|
|
18952
19362
|
return parseJournal(raw);
|
|
18953
19363
|
} catch (error) {
|
|
18954
19364
|
if (error instanceof SyntaxError) {
|
|
@@ -18961,15 +19371,15 @@ async function listJournals(projectRoot) {
|
|
|
18961
19371
|
const directory = journalDirectory(projectRoot);
|
|
18962
19372
|
let entries;
|
|
18963
19373
|
try {
|
|
18964
|
-
entries = await
|
|
19374
|
+
entries = await readdir13(directory);
|
|
18965
19375
|
} catch (error) {
|
|
18966
|
-
if (
|
|
19376
|
+
if (isNotFound24(error)) return [];
|
|
18967
19377
|
throw error;
|
|
18968
19378
|
}
|
|
18969
19379
|
const journals = [];
|
|
18970
19380
|
for (const entry of entries.sort()) {
|
|
18971
19381
|
if (!entry.endsWith(".json")) continue;
|
|
18972
|
-
journals.push(await readJournal(
|
|
19382
|
+
journals.push(await readJournal(path32.join(directory, entry)));
|
|
18973
19383
|
}
|
|
18974
19384
|
return journals;
|
|
18975
19385
|
}
|
|
@@ -19012,7 +19422,7 @@ function parseJournal(value) {
|
|
|
19012
19422
|
schemaVersion: 1,
|
|
19013
19423
|
operationId: value.operationId,
|
|
19014
19424
|
workspaceId: value.workspaceId,
|
|
19015
|
-
remoteRevision:
|
|
19425
|
+
remoteRevision: positiveInteger3(
|
|
19016
19426
|
value.remoteRevision,
|
|
19017
19427
|
"git-ref materialization remoteRevision"
|
|
19018
19428
|
),
|
|
@@ -19035,8 +19445,8 @@ function result(status2, bundle, localJournalPath, taskHeadFence) {
|
|
|
19035
19445
|
};
|
|
19036
19446
|
}
|
|
19037
19447
|
function journalDirectory(projectRoot) {
|
|
19038
|
-
return
|
|
19039
|
-
|
|
19448
|
+
return path32.join(
|
|
19449
|
+
path32.resolve(projectRoot),
|
|
19040
19450
|
".mancode",
|
|
19041
19451
|
"local",
|
|
19042
19452
|
"journals",
|
|
@@ -19045,13 +19455,13 @@ function journalDirectory(projectRoot) {
|
|
|
19045
19455
|
}
|
|
19046
19456
|
function journalPath(projectRoot, operationId) {
|
|
19047
19457
|
assertUlid(operationId, "git-ref materialization operationId");
|
|
19048
|
-
return
|
|
19458
|
+
return path32.join(journalDirectory(projectRoot), `${operationId}.json`);
|
|
19049
19459
|
}
|
|
19050
19460
|
function serialize11(value) {
|
|
19051
19461
|
return `${JSON.stringify(value, null, 2)}
|
|
19052
19462
|
`;
|
|
19053
19463
|
}
|
|
19054
|
-
function
|
|
19464
|
+
function positiveInteger3(value, label) {
|
|
19055
19465
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1) {
|
|
19056
19466
|
throw new Error(`${label} must be a positive integer`);
|
|
19057
19467
|
}
|
|
@@ -19065,23 +19475,23 @@ function timestamp2(value) {
|
|
|
19065
19475
|
}
|
|
19066
19476
|
async function pathExists2(target) {
|
|
19067
19477
|
try {
|
|
19068
|
-
await
|
|
19478
|
+
await lstat16(target);
|
|
19069
19479
|
return true;
|
|
19070
19480
|
} catch (error) {
|
|
19071
|
-
if (
|
|
19481
|
+
if (isNotFound24(error)) return false;
|
|
19072
19482
|
throw error;
|
|
19073
19483
|
}
|
|
19074
19484
|
}
|
|
19075
|
-
function
|
|
19485
|
+
function isAlreadyExists20(error) {
|
|
19076
19486
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
19077
19487
|
}
|
|
19078
|
-
function
|
|
19488
|
+
function isNotFound24(error) {
|
|
19079
19489
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
19080
19490
|
}
|
|
19081
19491
|
|
|
19082
19492
|
// src/team/git-ref-workflow-repair.ts
|
|
19083
19493
|
async function prepareGitRefWorkflowRepair(input) {
|
|
19084
|
-
const root =
|
|
19494
|
+
const root = path33.resolve(input.projectRoot);
|
|
19085
19495
|
const prepared2 = parsePrepared(input.prepared);
|
|
19086
19496
|
const pendingMetadata = parseWorkflowMetadata(input.pendingMetadata);
|
|
19087
19497
|
assertPendingMetadata2(prepared2, pendingMetadata);
|
|
@@ -19116,7 +19526,7 @@ async function prepareGitRefWorkflowRepair(input) {
|
|
|
19116
19526
|
}
|
|
19117
19527
|
async function recoverGitRefWorkflowRepair(projectRoot, operationId, transportReceipt = null, options = {}) {
|
|
19118
19528
|
assertUlid(operationId, "git-ref workflow repair operationId");
|
|
19119
|
-
const root =
|
|
19529
|
+
const root = path33.resolve(projectRoot);
|
|
19120
19530
|
let journal = await requireJournal(root, operationId);
|
|
19121
19531
|
await assertRecoveryAuthorized(root, journal, options);
|
|
19122
19532
|
if (journal.state === "committed" || journal.state === "aborted") {
|
|
@@ -19348,21 +19758,21 @@ function parsePrepared(value) {
|
|
|
19348
19758
|
throw new Error("MANCODE_REMOTE_WORKFLOW_REPAIR_JOURNAL_CORRUPT");
|
|
19349
19759
|
}
|
|
19350
19760
|
assertUlid(value.operationId, "git-ref workflow prepared operationId");
|
|
19351
|
-
const expectedRemoteRevision =
|
|
19761
|
+
const expectedRemoteRevision = positiveInteger4(
|
|
19352
19762
|
value.expectedRemoteRevision,
|
|
19353
19763
|
"git-ref workflow expectedRemoteRevision",
|
|
19354
19764
|
true
|
|
19355
19765
|
);
|
|
19356
|
-
const expectedOwnershipEpoch =
|
|
19766
|
+
const expectedOwnershipEpoch = positiveInteger4(
|
|
19357
19767
|
value.expectedOwnershipEpoch,
|
|
19358
19768
|
"git-ref workflow expectedOwnershipEpoch",
|
|
19359
19769
|
true
|
|
19360
19770
|
);
|
|
19361
|
-
const targetRemoteRevision =
|
|
19771
|
+
const targetRemoteRevision = positiveInteger4(
|
|
19362
19772
|
value.targetRemoteRevision,
|
|
19363
19773
|
"git-ref workflow targetRemoteRevision"
|
|
19364
19774
|
);
|
|
19365
|
-
const targetOwnershipEpoch =
|
|
19775
|
+
const targetOwnershipEpoch = positiveInteger4(
|
|
19366
19776
|
value.targetOwnershipEpoch,
|
|
19367
19777
|
"git-ref workflow targetOwnershipEpoch",
|
|
19368
19778
|
true
|
|
@@ -19482,12 +19892,12 @@ async function createJournal2(projectRoot, journal) {
|
|
|
19482
19892
|
await ensureJournalDirectory(projectRoot);
|
|
19483
19893
|
const target = gitRefWorkflowRepairJournalPath(projectRoot, journal.operationId);
|
|
19484
19894
|
try {
|
|
19485
|
-
await
|
|
19895
|
+
await writeFile29(target, serialize12(journal), {
|
|
19486
19896
|
encoding: "utf8",
|
|
19487
19897
|
flag: "wx"
|
|
19488
19898
|
});
|
|
19489
19899
|
} catch (error) {
|
|
19490
|
-
if (!
|
|
19900
|
+
if (!isAlreadyExists21(error)) throw error;
|
|
19491
19901
|
const existing = await requireJournal(projectRoot, journal.operationId);
|
|
19492
19902
|
if (digestCanonicalJson(existing) !== digestCanonicalJson(journal)) {
|
|
19493
19903
|
throw new Error("MANCODE_REMOTE_WORKFLOW_REPAIR_JOURNAL_CONFLICT");
|
|
@@ -19503,10 +19913,10 @@ async function replaceJournal2(projectRoot, journal) {
|
|
|
19503
19913
|
async function requireJournal(projectRoot, operationId) {
|
|
19504
19914
|
try {
|
|
19505
19915
|
return parseJournal2(
|
|
19506
|
-
JSON.parse(await
|
|
19916
|
+
JSON.parse(await readFile29(gitRefWorkflowRepairJournalPath(projectRoot, operationId), "utf8"))
|
|
19507
19917
|
);
|
|
19508
19918
|
} catch (error) {
|
|
19509
|
-
if (error instanceof SyntaxError ||
|
|
19919
|
+
if (error instanceof SyntaxError || isNotFound25(error)) {
|
|
19510
19920
|
throw new Error("MANCODE_REMOTE_WORKFLOW_REPAIR_JOURNAL_NOT_FOUND");
|
|
19511
19921
|
}
|
|
19512
19922
|
throw error;
|
|
@@ -19522,44 +19932,44 @@ function metadataFromBundle(bundle) {
|
|
|
19522
19932
|
return parseWorkflowMetadata(artifact2.content);
|
|
19523
19933
|
}
|
|
19524
19934
|
function metadataPath2(projectRoot, taskRef) {
|
|
19525
|
-
return
|
|
19935
|
+
return path33.join(taskRootPath(projectRoot, taskRef), "metadata.json");
|
|
19526
19936
|
}
|
|
19527
19937
|
async function readSafeFile(target) {
|
|
19528
|
-
const before = await
|
|
19938
|
+
const before = await lstat17(target);
|
|
19529
19939
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
19530
19940
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
19531
19941
|
}
|
|
19532
|
-
const content = await
|
|
19533
|
-
const after = await
|
|
19942
|
+
const content = await readFile29(target, "utf8");
|
|
19943
|
+
const after = await lstat17(target);
|
|
19534
19944
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
19535
19945
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
19536
19946
|
}
|
|
19537
19947
|
return content;
|
|
19538
19948
|
}
|
|
19539
19949
|
async function atomicWrite(target, content) {
|
|
19540
|
-
const temporary =
|
|
19541
|
-
|
|
19542
|
-
`.${
|
|
19950
|
+
const temporary = path33.join(
|
|
19951
|
+
path33.dirname(target),
|
|
19952
|
+
`.${path33.basename(target)}.${process.pid}.${Date.now()}.tmp`
|
|
19543
19953
|
);
|
|
19544
|
-
await
|
|
19954
|
+
await writeFile29(temporary, content, { encoding: "utf8", flag: "wx" });
|
|
19545
19955
|
await replaceFileAtomically(temporary, target);
|
|
19546
19956
|
}
|
|
19547
19957
|
async function ensureJournalDirectory(projectRoot) {
|
|
19548
|
-
let current =
|
|
19958
|
+
let current = path33.resolve(projectRoot);
|
|
19549
19959
|
for (const segment of [".mancode", "local", "journals", "git-ref-workflow"]) {
|
|
19550
|
-
current =
|
|
19960
|
+
current = path33.join(current, segment);
|
|
19551
19961
|
try {
|
|
19552
|
-
await
|
|
19962
|
+
await mkdir26(current);
|
|
19553
19963
|
} catch (error) {
|
|
19554
|
-
if (!
|
|
19964
|
+
if (!isAlreadyExists21(error)) throw error;
|
|
19555
19965
|
}
|
|
19556
|
-
const entry = await
|
|
19966
|
+
const entry = await lstat17(current);
|
|
19557
19967
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
19558
19968
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
19559
19969
|
}
|
|
19560
19970
|
}
|
|
19561
19971
|
}
|
|
19562
|
-
function
|
|
19972
|
+
function positiveInteger4(value, label, allowZero = false) {
|
|
19563
19973
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < (allowZero ? 0 : 1)) {
|
|
19564
19974
|
throw new Error(`${label} is invalid`);
|
|
19565
19975
|
}
|
|
@@ -19578,15 +19988,15 @@ function serialize12(value) {
|
|
|
19578
19988
|
return `${JSON.stringify(value, null, 2)}
|
|
19579
19989
|
`;
|
|
19580
19990
|
}
|
|
19581
|
-
function
|
|
19991
|
+
function isAlreadyExists21(error) {
|
|
19582
19992
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
19583
19993
|
}
|
|
19584
|
-
function
|
|
19994
|
+
function isNotFound25(error) {
|
|
19585
19995
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
19586
19996
|
}
|
|
19587
19997
|
|
|
19588
19998
|
// src/commands/v3-support.ts
|
|
19589
|
-
import
|
|
19999
|
+
import path34 from "path";
|
|
19590
20000
|
|
|
19591
20001
|
// src/runtime/session-identity.ts
|
|
19592
20002
|
import { createHash as createHash7 } from "crypto";
|
|
@@ -19673,7 +20083,7 @@ var EXIT_V3_OK = 0;
|
|
|
19673
20083
|
var EXIT_V3_INVALID_ARGUMENT = 2;
|
|
19674
20084
|
var EXIT_V3_BLOCKED = 3;
|
|
19675
20085
|
async function readV3CommandProject(projectRoot) {
|
|
19676
|
-
const root =
|
|
20086
|
+
const root = path34.resolve(projectRoot);
|
|
19677
20087
|
const runtime = await readProjectRuntimeContext(root);
|
|
19678
20088
|
const store = new V3ContextStore(root);
|
|
19679
20089
|
return {
|
|
@@ -20381,19 +20791,19 @@ function parseExpectedRevision2(value) {
|
|
|
20381
20791
|
// src/commands/init.ts
|
|
20382
20792
|
import { promises as fs4 } from "fs";
|
|
20383
20793
|
import os from "os";
|
|
20384
|
-
import
|
|
20794
|
+
import path48 from "path";
|
|
20385
20795
|
import process5 from "process";
|
|
20386
20796
|
|
|
20387
20797
|
// src/installers/claude-code.ts
|
|
20388
20798
|
import {
|
|
20389
20799
|
access,
|
|
20390
|
-
mkdir as
|
|
20391
|
-
readFile as
|
|
20392
|
-
readdir as
|
|
20800
|
+
mkdir as mkdir28,
|
|
20801
|
+
readFile as readFile31,
|
|
20802
|
+
readdir as readdir15,
|
|
20393
20803
|
rm as rm13,
|
|
20394
|
-
writeFile as
|
|
20804
|
+
writeFile as writeFile31
|
|
20395
20805
|
} from "fs/promises";
|
|
20396
|
-
import
|
|
20806
|
+
import path36 from "path";
|
|
20397
20807
|
|
|
20398
20808
|
// src/templates/agents/scout.ts
|
|
20399
20809
|
var SCOUT_AGENT = {
|
|
@@ -21714,8 +22124,8 @@ ${spec.body}
|
|
|
21714
22124
|
}
|
|
21715
22125
|
|
|
21716
22126
|
// src/installers/common.ts
|
|
21717
|
-
import { mkdir as
|
|
21718
|
-
import
|
|
22127
|
+
import { mkdir as mkdir27, readFile as readFile30, stat as stat3, writeFile as writeFile30 } from "fs/promises";
|
|
22128
|
+
import path35 from "path";
|
|
21719
22129
|
|
|
21720
22130
|
// src/templates/defaults.ts
|
|
21721
22131
|
var DEFAULT_CONFIG = {
|
|
@@ -21750,50 +22160,50 @@ var EMPTY_STYLE_TOKENS = {
|
|
|
21750
22160
|
|
|
21751
22161
|
// src/installers/common.ts
|
|
21752
22162
|
async function installMancodeCore(projectRoot) {
|
|
21753
|
-
const mancodeDir =
|
|
21754
|
-
await
|
|
21755
|
-
await
|
|
21756
|
-
await
|
|
21757
|
-
await
|
|
22163
|
+
const mancodeDir = path35.join(projectRoot, ".mancode");
|
|
22164
|
+
await mkdir27(path35.join(mancodeDir, "hooks"), { recursive: true });
|
|
22165
|
+
await mkdir27(path35.join(mancodeDir, "aesthetics"), { recursive: true });
|
|
22166
|
+
await mkdir27(path35.join(mancodeDir, "logs"), { recursive: true });
|
|
22167
|
+
await mkdir27(path35.join(mancodeDir, "workflows"), { recursive: true });
|
|
21758
22168
|
await ensureTeamMemory(projectRoot);
|
|
21759
|
-
await
|
|
21760
|
-
const configPath =
|
|
22169
|
+
await mkdir27(path35.join(mancodeDir, "preseason-reports"), { recursive: true });
|
|
22170
|
+
const configPath = path35.join(mancodeDir, "config.json");
|
|
21761
22171
|
if (!await pathExists3(configPath)) {
|
|
21762
|
-
await
|
|
22172
|
+
await writeFile30(
|
|
21763
22173
|
configPath,
|
|
21764
22174
|
`${JSON.stringify(DEFAULT_CONFIG, null, 2)}
|
|
21765
22175
|
`,
|
|
21766
22176
|
"utf-8"
|
|
21767
22177
|
);
|
|
21768
22178
|
}
|
|
21769
|
-
await installHooks(
|
|
21770
|
-
const tokensPath =
|
|
22179
|
+
await installHooks(path35.join(mancodeDir, "hooks"));
|
|
22180
|
+
const tokensPath = path35.join(mancodeDir, "aesthetics", "style-tokens.json");
|
|
21771
22181
|
if (!await pathExists3(tokensPath)) {
|
|
21772
|
-
await
|
|
22182
|
+
await writeFile30(
|
|
21773
22183
|
tokensPath,
|
|
21774
22184
|
`${JSON.stringify(EMPTY_STYLE_TOKENS, null, 2)}
|
|
21775
22185
|
`,
|
|
21776
22186
|
"utf-8"
|
|
21777
22187
|
);
|
|
21778
22188
|
}
|
|
21779
|
-
const logPath =
|
|
22189
|
+
const logPath = path35.join(mancodeDir, "logs", "hooks.log");
|
|
21780
22190
|
if (!await pathExists3(logPath)) {
|
|
21781
|
-
await
|
|
22191
|
+
await writeFile30(logPath, "", "utf-8");
|
|
21782
22192
|
}
|
|
21783
22193
|
}
|
|
21784
22194
|
async function readTextIfExists(filePath) {
|
|
21785
22195
|
try {
|
|
21786
|
-
return await
|
|
22196
|
+
return await readFile30(filePath, "utf-8");
|
|
21787
22197
|
} catch (err) {
|
|
21788
22198
|
if (isNodeError2(err) && err.code === "ENOENT") return "";
|
|
21789
22199
|
throw err;
|
|
21790
22200
|
}
|
|
21791
22201
|
}
|
|
21792
22202
|
async function installHooks(hooksDir) {
|
|
21793
|
-
const sessionStartDst =
|
|
21794
|
-
await
|
|
21795
|
-
const userPromptDst =
|
|
21796
|
-
await
|
|
22203
|
+
const sessionStartDst = path35.join(hooksDir, "session-start.mjs");
|
|
22204
|
+
await writeFile30(sessionStartDst, SESSION_START_HOOK, "utf-8");
|
|
22205
|
+
const userPromptDst = path35.join(hooksDir, "user-prompt-submit.mjs");
|
|
22206
|
+
await writeFile30(userPromptDst, USER_PROMPT_SUBMIT_HOOK, "utf-8");
|
|
21797
22207
|
}
|
|
21798
22208
|
async function pathExists3(p) {
|
|
21799
22209
|
try {
|
|
@@ -21832,39 +22242,39 @@ var LEGACY_CLAUDE_SKILL_SETTINGS = {
|
|
|
21832
22242
|
};
|
|
21833
22243
|
var LEGACY_MVP2_SKILL_NAMES = ["mamba", "man8"];
|
|
21834
22244
|
async function validateClaudeCodeSettings(projectRoot) {
|
|
21835
|
-
await readClaudeSettings(
|
|
22245
|
+
await readClaudeSettings(path36.join(projectRoot, ".claude"));
|
|
21836
22246
|
}
|
|
21837
22247
|
async function installClaudeCode(projectRoot, options) {
|
|
21838
|
-
const claudeDir =
|
|
22248
|
+
const claudeDir = path36.join(projectRoot, ".claude");
|
|
21839
22249
|
const settings = await readClaudeSettings(claudeDir);
|
|
21840
22250
|
const force = options.force ?? false;
|
|
21841
22251
|
await validateClaudeWriteTargets(claudeDir, options.minimal ?? false, force);
|
|
21842
22252
|
await installMancodeCore(projectRoot);
|
|
21843
|
-
await
|
|
21844
|
-
await installSoloSkill(
|
|
22253
|
+
await mkdir28(path36.join(claudeDir, "skills"), { recursive: true });
|
|
22254
|
+
await installSoloSkill(path36.join(claudeDir, "skills"), force);
|
|
21845
22255
|
if (options.minimal) {
|
|
21846
|
-
await uninstallMvp2Skills(
|
|
22256
|
+
await uninstallMvp2Skills(path36.join(claudeDir, "skills"));
|
|
21847
22257
|
} else {
|
|
21848
|
-
await installMvp2Skills(
|
|
22258
|
+
await installMvp2Skills(path36.join(claudeDir, "skills"), force);
|
|
21849
22259
|
}
|
|
21850
22260
|
if (options.minimal) {
|
|
21851
|
-
await uninstallAgents(
|
|
22261
|
+
await uninstallAgents(path36.join(claudeDir, "agents"));
|
|
21852
22262
|
} else {
|
|
21853
|
-
await installAgents(
|
|
22263
|
+
await installAgents(path36.join(claudeDir, "agents"), force);
|
|
21854
22264
|
}
|
|
21855
22265
|
await updateClaudeSettings(claudeDir, settings);
|
|
21856
22266
|
await removeLegacyHookFiles(projectRoot);
|
|
21857
22267
|
}
|
|
21858
22268
|
async function validateClaudeWriteTargets(claudeDir, minimal, force) {
|
|
21859
22269
|
if (!force) return;
|
|
21860
|
-
const skillsDir =
|
|
22270
|
+
const skillsDir = path36.join(claudeDir, "skills");
|
|
21861
22271
|
await assertWritableClaudeSkill(skillsDir, "solo");
|
|
21862
22272
|
if (minimal) return;
|
|
21863
22273
|
for (const skill of MVP2_SKILLS) {
|
|
21864
22274
|
await assertWritableClaudeSkill(skillsDir, skill.name);
|
|
21865
22275
|
}
|
|
21866
22276
|
for (const agent of ALL_AGENTS) {
|
|
21867
|
-
const agentPath =
|
|
22277
|
+
const agentPath = path36.join(claudeDir, "agents", `${agent.name}.md`);
|
|
21868
22278
|
const existing = await readTextIfExists2(agentPath);
|
|
21869
22279
|
if (existing !== null && !isGeneratedClaudeAgent(existing, agent.name)) {
|
|
21870
22280
|
throw new Error(
|
|
@@ -21874,7 +22284,7 @@ async function validateClaudeWriteTargets(claudeDir, minimal, force) {
|
|
|
21874
22284
|
}
|
|
21875
22285
|
}
|
|
21876
22286
|
async function assertWritableClaudeSkill(skillsDir, modeName) {
|
|
21877
|
-
const skillPath =
|
|
22287
|
+
const skillPath = path36.join(skillsDir, modeName, "SKILL.md");
|
|
21878
22288
|
const existing = await readTextIfExists2(skillPath);
|
|
21879
22289
|
if (existing !== null && !isGeneratedClaudeSkill(existing, modeName)) {
|
|
21880
22290
|
throw new Error(
|
|
@@ -21883,10 +22293,10 @@ async function assertWritableClaudeSkill(skillsDir, modeName) {
|
|
|
21883
22293
|
}
|
|
21884
22294
|
}
|
|
21885
22295
|
async function removeLegacyHookFiles(projectRoot) {
|
|
21886
|
-
const hooksDir =
|
|
22296
|
+
const hooksDir = path36.join(projectRoot, ".mancode", "hooks");
|
|
21887
22297
|
await Promise.all([
|
|
21888
|
-
rm13(
|
|
21889
|
-
rm13(
|
|
22298
|
+
rm13(path36.join(hooksDir, "session-start.sh"), { force: true }),
|
|
22299
|
+
rm13(path36.join(hooksDir, "user-prompt-submit.sh"), { force: true })
|
|
21890
22300
|
]);
|
|
21891
22301
|
}
|
|
21892
22302
|
async function installSoloSkill(skillsDir, force) {
|
|
@@ -21922,8 +22332,8 @@ async function uninstallMvp2Skills(skillsDir) {
|
|
|
21922
22332
|
await removeManagedLegacyMvp2Skills(skillsDir);
|
|
21923
22333
|
}
|
|
21924
22334
|
async function installProjectSkill(skillsDir, skill, force = true) {
|
|
21925
|
-
const skillDir =
|
|
21926
|
-
const skillPath =
|
|
22335
|
+
const skillDir = path36.join(skillsDir, skill.name);
|
|
22336
|
+
const skillPath = path36.join(skillDir, "SKILL.md");
|
|
21927
22337
|
const existing = await readTextIfExists2(skillPath);
|
|
21928
22338
|
if (existing !== null && !force) {
|
|
21929
22339
|
return;
|
|
@@ -21933,24 +22343,24 @@ async function installProjectSkill(skillsDir, skill, force = true) {
|
|
|
21933
22343
|
`refusing to overwrite user-authored Claude Code skill: ${skillPath}`
|
|
21934
22344
|
);
|
|
21935
22345
|
}
|
|
21936
|
-
await
|
|
21937
|
-
await
|
|
22346
|
+
await mkdir28(skillDir, { recursive: true });
|
|
22347
|
+
await writeFile31(
|
|
21938
22348
|
skillPath,
|
|
21939
22349
|
addManagedMarker(renderSkill(skill), CLAUDE_SKILL_MANAGED_MARKER),
|
|
21940
22350
|
"utf-8"
|
|
21941
22351
|
);
|
|
21942
22352
|
}
|
|
21943
22353
|
async function removeLegacyFlatSkill(skillsDir, legacyName, modeName) {
|
|
21944
|
-
const legacyPath =
|
|
22354
|
+
const legacyPath = path36.join(skillsDir, `${legacyName}.md`);
|
|
21945
22355
|
const content = await readTextIfExists2(legacyPath);
|
|
21946
22356
|
if (content && isGeneratedClaudeSkill(content, modeName)) {
|
|
21947
22357
|
await rm13(legacyPath, { force: true });
|
|
21948
22358
|
}
|
|
21949
22359
|
}
|
|
21950
22360
|
async function installAgents(agentsDir, force) {
|
|
21951
|
-
await
|
|
22361
|
+
await mkdir28(agentsDir, { recursive: true });
|
|
21952
22362
|
for (const agent of ALL_AGENTS) {
|
|
21953
|
-
const agentPath =
|
|
22363
|
+
const agentPath = path36.join(agentsDir, `${agent.name}.md`);
|
|
21954
22364
|
if (!force) {
|
|
21955
22365
|
try {
|
|
21956
22366
|
await access(agentPath);
|
|
@@ -21968,12 +22378,12 @@ async function installAgents(agentsDir, force) {
|
|
|
21968
22378
|
renderAgent(agent),
|
|
21969
22379
|
CLAUDE_AGENT_MANAGED_MARKER
|
|
21970
22380
|
);
|
|
21971
|
-
await
|
|
22381
|
+
await writeFile31(agentPath, content, "utf-8");
|
|
21972
22382
|
}
|
|
21973
22383
|
}
|
|
21974
22384
|
async function uninstallAgents(agentsDir) {
|
|
21975
22385
|
for (const agent of ALL_AGENTS) {
|
|
21976
|
-
const agentPath =
|
|
22386
|
+
const agentPath = path36.join(agentsDir, `${agent.name}.md`);
|
|
21977
22387
|
const content = await readTextIfExists2(agentPath);
|
|
21978
22388
|
if (content && isGeneratedClaudeAgent(content, agent.name)) {
|
|
21979
22389
|
await rm13(agentPath, { force: true });
|
|
@@ -21981,8 +22391,8 @@ async function uninstallAgents(agentsDir) {
|
|
|
21981
22391
|
}
|
|
21982
22392
|
}
|
|
21983
22393
|
async function removeClaudeGeneratedContent(projectRoot) {
|
|
21984
|
-
const claudeDir =
|
|
21985
|
-
const skillsDir =
|
|
22394
|
+
const claudeDir = path36.join(projectRoot, ".claude");
|
|
22395
|
+
const skillsDir = path36.join(claudeDir, "skills");
|
|
21986
22396
|
for (const modeName of [
|
|
21987
22397
|
"solo",
|
|
21988
22398
|
...LEGACY_MVP2_SKILL_NAMES,
|
|
@@ -21991,11 +22401,11 @@ async function removeClaudeGeneratedContent(projectRoot) {
|
|
|
21991
22401
|
await removeGeneratedSkillDir(skillsDir, modeName);
|
|
21992
22402
|
await removeLegacyFlatSkill(skillsDir, `mancode-${modeName}`, modeName);
|
|
21993
22403
|
}
|
|
21994
|
-
await uninstallAgents(
|
|
22404
|
+
await uninstallAgents(path36.join(claudeDir, "agents"));
|
|
21995
22405
|
}
|
|
21996
22406
|
async function removeGeneratedSkillDir(skillsDir, modeName) {
|
|
21997
|
-
const skillDir =
|
|
21998
|
-
const skillPath =
|
|
22407
|
+
const skillDir = path36.join(skillsDir, modeName);
|
|
22408
|
+
const skillPath = path36.join(skillDir, "SKILL.md");
|
|
21999
22409
|
const content = await readTextIfExists2(skillPath);
|
|
22000
22410
|
if (!content || !isGeneratedClaudeSkill(content, modeName)) return;
|
|
22001
22411
|
await rm13(skillPath, { force: true });
|
|
@@ -22019,7 +22429,7 @@ ${marker}
|
|
|
22019
22429
|
}
|
|
22020
22430
|
async function readTextIfExists2(filePath) {
|
|
22021
22431
|
try {
|
|
22022
|
-
return await
|
|
22432
|
+
return await readFile31(filePath, "utf-8");
|
|
22023
22433
|
} catch (error) {
|
|
22024
22434
|
if (isNodeError3(error) && error.code === "ENOENT") return null;
|
|
22025
22435
|
throw error;
|
|
@@ -22027,16 +22437,16 @@ async function readTextIfExists2(filePath) {
|
|
|
22027
22437
|
}
|
|
22028
22438
|
async function removeIfEmpty(dir) {
|
|
22029
22439
|
try {
|
|
22030
|
-
if ((await
|
|
22440
|
+
if ((await readdir15(dir)).length === 0) {
|
|
22031
22441
|
await rm13(dir, { recursive: true, force: true });
|
|
22032
22442
|
}
|
|
22033
22443
|
} catch {
|
|
22034
22444
|
}
|
|
22035
22445
|
}
|
|
22036
22446
|
async function readClaudeSettings(claudeDir) {
|
|
22037
|
-
const settingsPath =
|
|
22447
|
+
const settingsPath = path36.join(claudeDir, "settings.json");
|
|
22038
22448
|
try {
|
|
22039
|
-
const raw = await
|
|
22449
|
+
const raw = await readFile31(settingsPath, "utf-8");
|
|
22040
22450
|
return JSON.parse(raw);
|
|
22041
22451
|
} catch (err) {
|
|
22042
22452
|
if (isNodeError3(err) && err.code === "ENOENT") {
|
|
@@ -22049,7 +22459,7 @@ async function readClaudeSettings(claudeDir) {
|
|
|
22049
22459
|
}
|
|
22050
22460
|
}
|
|
22051
22461
|
async function updateClaudeSettings(claudeDir, settings) {
|
|
22052
|
-
const settingsPath =
|
|
22462
|
+
const settingsPath = path36.join(claudeDir, "settings.json");
|
|
22053
22463
|
settings.hooks = settings.hooks || {};
|
|
22054
22464
|
settings.hooks.SessionStart = [
|
|
22055
22465
|
...normalizeHookGroups(settings.hooks.SessionStart),
|
|
@@ -22062,7 +22472,7 @@ async function updateClaudeSettings(claudeDir, settings) {
|
|
|
22062
22472
|
removeLegacyMancodeSkillSettings(settings);
|
|
22063
22473
|
const content = `${JSON.stringify(settings, null, 2)}
|
|
22064
22474
|
`;
|
|
22065
|
-
await
|
|
22475
|
+
await writeFile31(settingsPath, content, "utf-8");
|
|
22066
22476
|
}
|
|
22067
22477
|
function removeLegacyMancodeSkillSettings(settings) {
|
|
22068
22478
|
if (!settings.skills) return;
|
|
@@ -22147,12 +22557,12 @@ function isNodeError3(err) {
|
|
|
22147
22557
|
}
|
|
22148
22558
|
|
|
22149
22559
|
// src/installers/cursor.ts
|
|
22150
|
-
import { mkdir as
|
|
22151
|
-
import
|
|
22560
|
+
import { mkdir as mkdir30, readFile as readFile34, rm as rm15, writeFile as writeFile33 } from "fs/promises";
|
|
22561
|
+
import path39 from "path";
|
|
22152
22562
|
|
|
22153
22563
|
// src/installers/mode-skills.ts
|
|
22154
|
-
import { mkdir as
|
|
22155
|
-
import
|
|
22564
|
+
import { mkdir as mkdir29, readFile as readFile32, readdir as readdir16, rm as rm14, writeFile as writeFile32 } from "fs/promises";
|
|
22565
|
+
import path37 from "path";
|
|
22156
22566
|
var MODE_NAMES = [
|
|
22157
22567
|
"manba",
|
|
22158
22568
|
"man",
|
|
@@ -22210,10 +22620,10 @@ async function installCodexSkills(projectRoot, minimal) {
|
|
|
22210
22620
|
await removeCodexSkills(projectRoot);
|
|
22211
22621
|
return;
|
|
22212
22622
|
}
|
|
22213
|
-
const skillsDir =
|
|
22623
|
+
const skillsDir = path37.join(projectRoot, ".agents", "skills");
|
|
22214
22624
|
for (const mode of MODE_NAMES) {
|
|
22215
|
-
const modeDir =
|
|
22216
|
-
await
|
|
22625
|
+
const modeDir = path37.join(skillsDir, mode);
|
|
22626
|
+
await mkdir29(modeDir, { recursive: true });
|
|
22217
22627
|
const meta = MODE_META[mode];
|
|
22218
22628
|
const content = [
|
|
22219
22629
|
"---",
|
|
@@ -22227,7 +22637,7 @@ async function installCodexSkills(projectRoot, minimal) {
|
|
|
22227
22637
|
""
|
|
22228
22638
|
].join("\n");
|
|
22229
22639
|
await writeManagedSkill(
|
|
22230
|
-
|
|
22640
|
+
path37.join(modeDir, "SKILL.md"),
|
|
22231
22641
|
content,
|
|
22232
22642
|
CODEX_SKILL_MANAGED_MARKER,
|
|
22233
22643
|
"Codex",
|
|
@@ -22241,10 +22651,10 @@ async function installZcodeSkills(projectRoot, minimal) {
|
|
|
22241
22651
|
await removeZcodeSkills(projectRoot);
|
|
22242
22652
|
return;
|
|
22243
22653
|
}
|
|
22244
|
-
const skillsDir =
|
|
22654
|
+
const skillsDir = path37.join(projectRoot, ".agents", "skills");
|
|
22245
22655
|
for (const mode of MODE_NAMES) {
|
|
22246
|
-
const modeDir =
|
|
22247
|
-
await
|
|
22656
|
+
const modeDir = path37.join(skillsDir, mode);
|
|
22657
|
+
await mkdir29(modeDir, { recursive: true });
|
|
22248
22658
|
const meta = MODE_META[mode];
|
|
22249
22659
|
const content = [
|
|
22250
22660
|
"---",
|
|
@@ -22258,7 +22668,7 @@ async function installZcodeSkills(projectRoot, minimal) {
|
|
|
22258
22668
|
""
|
|
22259
22669
|
].join("\n");
|
|
22260
22670
|
await writeManagedSkill(
|
|
22261
|
-
|
|
22671
|
+
path37.join(modeDir, "SKILL.md"),
|
|
22262
22672
|
content,
|
|
22263
22673
|
ZCODE_SKILL_MANAGED_MARKER,
|
|
22264
22674
|
"ZCode",
|
|
@@ -22272,8 +22682,8 @@ async function installCursorCommands(projectRoot, minimal) {
|
|
|
22272
22682
|
await removeCursorCommands(projectRoot);
|
|
22273
22683
|
return;
|
|
22274
22684
|
}
|
|
22275
|
-
const commandsDir =
|
|
22276
|
-
await
|
|
22685
|
+
const commandsDir = path37.join(projectRoot, ".cursor", "commands");
|
|
22686
|
+
await mkdir29(commandsDir, { recursive: true });
|
|
22277
22687
|
for (const mode of MODE_NAMES) {
|
|
22278
22688
|
const meta = MODE_META[mode];
|
|
22279
22689
|
const content = [
|
|
@@ -22287,22 +22697,22 @@ async function installCursorCommands(projectRoot, minimal) {
|
|
|
22287
22697
|
""
|
|
22288
22698
|
].join("\n");
|
|
22289
22699
|
await writeManagedModeFile(
|
|
22290
|
-
|
|
22700
|
+
path37.join(commandsDir, `${mode}.md`),
|
|
22291
22701
|
content,
|
|
22292
22702
|
mode,
|
|
22293
22703
|
"Cursor"
|
|
22294
22704
|
);
|
|
22295
22705
|
}
|
|
22296
|
-
await removeManagedModeFile(
|
|
22297
|
-
await removeLegacyGeneratedModeFile(
|
|
22706
|
+
await removeManagedModeFile(path37.join(commandsDir, "mamba.md"), "mamba");
|
|
22707
|
+
await removeLegacyGeneratedModeFile(path37.join(commandsDir, "man8.md"));
|
|
22298
22708
|
}
|
|
22299
22709
|
async function installCopilotPrompts(projectRoot, minimal) {
|
|
22300
22710
|
if (minimal) {
|
|
22301
22711
|
await removeCopilotPrompts(projectRoot);
|
|
22302
22712
|
return;
|
|
22303
22713
|
}
|
|
22304
|
-
const promptsDir =
|
|
22305
|
-
await
|
|
22714
|
+
const promptsDir = path37.join(projectRoot, ".github", "prompts");
|
|
22715
|
+
await mkdir29(promptsDir, { recursive: true });
|
|
22306
22716
|
for (const mode of MODE_NAMES) {
|
|
22307
22717
|
const meta = MODE_META[mode];
|
|
22308
22718
|
const content = [
|
|
@@ -22317,33 +22727,33 @@ async function installCopilotPrompts(projectRoot, minimal) {
|
|
|
22317
22727
|
""
|
|
22318
22728
|
].join("\n");
|
|
22319
22729
|
await writeManagedModeFile(
|
|
22320
|
-
|
|
22730
|
+
path37.join(promptsDir, `${mode}.prompt.md`),
|
|
22321
22731
|
content,
|
|
22322
22732
|
mode,
|
|
22323
22733
|
"GitHub Copilot"
|
|
22324
22734
|
);
|
|
22325
22735
|
}
|
|
22326
22736
|
await removeManagedModeFile(
|
|
22327
|
-
|
|
22737
|
+
path37.join(promptsDir, "mamba.prompt.md"),
|
|
22328
22738
|
"mamba"
|
|
22329
22739
|
);
|
|
22330
|
-
await removeLegacyGeneratedModeFile(
|
|
22740
|
+
await removeLegacyGeneratedModeFile(path37.join(promptsDir, "man8.prompt.md"));
|
|
22331
22741
|
}
|
|
22332
22742
|
async function removeCodexSkills(projectRoot) {
|
|
22333
22743
|
if (!await platformNeedsSharedSkills(projectRoot, "zcode")) {
|
|
22334
22744
|
await cleanManagedSkills(
|
|
22335
|
-
|
|
22745
|
+
path37.join(projectRoot, ".agents", "skills"),
|
|
22336
22746
|
MANCODE_AGENT_SKILL_MARKERS
|
|
22337
22747
|
);
|
|
22338
22748
|
}
|
|
22339
|
-
await cleanManagedSkills(
|
|
22749
|
+
await cleanManagedSkills(path37.join(projectRoot, ".codex", "skills"), [
|
|
22340
22750
|
CODEX_SKILL_MANAGED_MARKER
|
|
22341
22751
|
]);
|
|
22342
22752
|
}
|
|
22343
22753
|
async function cleanManagedSkills(skillsDir, markers) {
|
|
22344
22754
|
for (const mode of [...MODE_NAMES, ...LEGACY_MODE_NAMES]) {
|
|
22345
|
-
const modeDir =
|
|
22346
|
-
const skillPath =
|
|
22755
|
+
const modeDir = path37.join(skillsDir, mode);
|
|
22756
|
+
const skillPath = path37.join(modeDir, "SKILL.md");
|
|
22347
22757
|
if (await isManagedByAnyMarker(skillPath, markers)) {
|
|
22348
22758
|
await rm14(skillPath, { force: true });
|
|
22349
22759
|
await removeIfEmpty2(modeDir);
|
|
@@ -22354,17 +22764,17 @@ async function cleanManagedSkills(skillsDir, markers) {
|
|
|
22354
22764
|
async function removeZcodeSkills(projectRoot) {
|
|
22355
22765
|
if (!await platformNeedsSharedSkills(projectRoot, "codex")) {
|
|
22356
22766
|
await cleanManagedSkills(
|
|
22357
|
-
|
|
22767
|
+
path37.join(projectRoot, ".agents", "skills"),
|
|
22358
22768
|
MANCODE_AGENT_SKILL_MARKERS
|
|
22359
22769
|
);
|
|
22360
22770
|
}
|
|
22361
|
-
await cleanManagedSkills(
|
|
22771
|
+
await cleanManagedSkills(path37.join(projectRoot, ".zcode", "skills"), [
|
|
22362
22772
|
ZCODE_SKILL_MANAGED_MARKER
|
|
22363
22773
|
]);
|
|
22364
22774
|
}
|
|
22365
22775
|
async function removeCursorCommands(projectRoot) {
|
|
22366
22776
|
for (const mode of [...MODE_NAMES, ...LEGACY_MODE_NAMES]) {
|
|
22367
|
-
const filePath =
|
|
22777
|
+
const filePath = path37.join(
|
|
22368
22778
|
projectRoot,
|
|
22369
22779
|
".cursor",
|
|
22370
22780
|
"commands",
|
|
@@ -22376,7 +22786,7 @@ async function removeCursorCommands(projectRoot) {
|
|
|
22376
22786
|
}
|
|
22377
22787
|
async function removeCopilotPrompts(projectRoot) {
|
|
22378
22788
|
for (const mode of [...MODE_NAMES, ...LEGACY_MODE_NAMES]) {
|
|
22379
|
-
const filePath =
|
|
22789
|
+
const filePath = path37.join(
|
|
22380
22790
|
projectRoot,
|
|
22381
22791
|
".github",
|
|
22382
22792
|
"prompts",
|
|
@@ -22393,7 +22803,7 @@ async function writeManagedModeFile(filePath, content, mode, platformLabel) {
|
|
|
22393
22803
|
`refusing to overwrite user-authored ${platformLabel} mode file: ${filePath}`
|
|
22394
22804
|
);
|
|
22395
22805
|
}
|
|
22396
|
-
await
|
|
22806
|
+
await writeFile32(filePath, content, "utf-8");
|
|
22397
22807
|
}
|
|
22398
22808
|
async function removeManagedModeFile(filePath, mode) {
|
|
22399
22809
|
const content = await readTextIfExists3(filePath);
|
|
@@ -22412,8 +22822,8 @@ function isGeneratedModeFile(content, mode) {
|
|
|
22412
22822
|
}
|
|
22413
22823
|
async function removeLegacyManagedSkills(skillsDir, markers) {
|
|
22414
22824
|
for (const mode of LEGACY_MODE_NAMES) {
|
|
22415
|
-
const modeDir =
|
|
22416
|
-
const skillPath =
|
|
22825
|
+
const modeDir = path37.join(skillsDir, mode);
|
|
22826
|
+
const skillPath = path37.join(modeDir, "SKILL.md");
|
|
22417
22827
|
const content = await readTextIfExists3(skillPath);
|
|
22418
22828
|
if (content && markers.some((marker) => content.includes(marker))) {
|
|
22419
22829
|
await rm14(skillPath, { force: true });
|
|
@@ -22423,7 +22833,7 @@ async function removeLegacyManagedSkills(skillsDir, markers) {
|
|
|
22423
22833
|
}
|
|
22424
22834
|
async function removeIfEmpty2(dir) {
|
|
22425
22835
|
try {
|
|
22426
|
-
const entries = await
|
|
22836
|
+
const entries = await readdir16(dir);
|
|
22427
22837
|
if (entries.length === 0) {
|
|
22428
22838
|
await rm14(dir, { recursive: true, force: true });
|
|
22429
22839
|
}
|
|
@@ -22437,7 +22847,7 @@ async function writeManagedSkill(skillPath, content, marker, platformLabel, reco
|
|
|
22437
22847
|
`refusing to overwrite user-authored ${platformLabel} skill: ${skillPath}`
|
|
22438
22848
|
);
|
|
22439
22849
|
}
|
|
22440
|
-
await
|
|
22850
|
+
await writeFile32(skillPath, content, "utf-8");
|
|
22441
22851
|
}
|
|
22442
22852
|
async function isManagedByAnyMarker(skillPath, markers) {
|
|
22443
22853
|
const content = await readTextIfExists3(skillPath);
|
|
@@ -22445,8 +22855,8 @@ async function isManagedByAnyMarker(skillPath, markers) {
|
|
|
22445
22855
|
}
|
|
22446
22856
|
async function platformNeedsSharedSkills(projectRoot, platform) {
|
|
22447
22857
|
try {
|
|
22448
|
-
const raw = await
|
|
22449
|
-
|
|
22858
|
+
const raw = await readFile32(
|
|
22859
|
+
path37.join(projectRoot, ".mancode", "config.json"),
|
|
22450
22860
|
"utf-8"
|
|
22451
22861
|
);
|
|
22452
22862
|
const config = JSON.parse(raw);
|
|
@@ -22465,7 +22875,7 @@ function isRecord5(value) {
|
|
|
22465
22875
|
}
|
|
22466
22876
|
async function readTextIfExists3(filePath) {
|
|
22467
22877
|
try {
|
|
22468
|
-
return await
|
|
22878
|
+
return await readFile32(filePath, "utf-8");
|
|
22469
22879
|
} catch (error) {
|
|
22470
22880
|
if (isNodeError4(error) && error.code === "ENOENT") return null;
|
|
22471
22881
|
throw error;
|
|
@@ -22584,18 +22994,18 @@ var MODE_META = {
|
|
|
22584
22994
|
};
|
|
22585
22995
|
|
|
22586
22996
|
// src/installers/shared-content.ts
|
|
22587
|
-
import { readFile as
|
|
22588
|
-
import
|
|
22997
|
+
import { readFile as readFile33 } from "fs/promises";
|
|
22998
|
+
import path38 from "path";
|
|
22589
22999
|
async function generateSharedContent(projectRoot, options) {
|
|
22590
23000
|
const [state, tokens, profile] = await Promise.all([
|
|
22591
23001
|
readJson(
|
|
22592
|
-
|
|
23002
|
+
path38.join(projectRoot, ".mancode", "state.json")
|
|
22593
23003
|
),
|
|
22594
23004
|
readJson(
|
|
22595
|
-
|
|
23005
|
+
path38.join(projectRoot, ".mancode", "aesthetics", "style-tokens.json")
|
|
22596
23006
|
),
|
|
22597
23007
|
readJson(
|
|
22598
|
-
|
|
23008
|
+
path38.join(projectRoot, ".mancode", "project-profile.json")
|
|
22599
23009
|
)
|
|
22600
23010
|
]);
|
|
22601
23011
|
const currentProfile = options.projectProfile ?? profile;
|
|
@@ -22725,7 +23135,7 @@ function renderPlatformDowngrade(options) {
|
|
|
22725
23135
|
}
|
|
22726
23136
|
async function readJson(filePath) {
|
|
22727
23137
|
try {
|
|
22728
|
-
return JSON.parse(await
|
|
23138
|
+
return JSON.parse(await readFile33(filePath, "utf-8"));
|
|
22729
23139
|
} catch {
|
|
22730
23140
|
return null;
|
|
22731
23141
|
}
|
|
@@ -22770,8 +23180,8 @@ var MANCODE_CURSOR_RULE_FILES = [
|
|
|
22770
23180
|
];
|
|
22771
23181
|
async function installCursor(projectRoot, options) {
|
|
22772
23182
|
await installMancodeCore(projectRoot);
|
|
22773
|
-
const rulesDir =
|
|
22774
|
-
await
|
|
23183
|
+
const rulesDir = path39.join(projectRoot, ".cursor", "rules");
|
|
23184
|
+
await mkdir30(rulesDir, { recursive: true });
|
|
22775
23185
|
const sharedContent = await generateSharedContent(projectRoot, {
|
|
22776
23186
|
platform: "cursor",
|
|
22777
23187
|
displayName: "Cursor",
|
|
@@ -22859,14 +23269,14 @@ async function writeRule(rulesDir, fileName, description, alwaysApply, body) {
|
|
|
22859
23269
|
|
|
22860
23270
|
${body.trim()}
|
|
22861
23271
|
`;
|
|
22862
|
-
const rulePath =
|
|
23272
|
+
const rulePath = path39.join(rulesDir, fileName);
|
|
22863
23273
|
const existing = await readTextIfExists4(rulePath);
|
|
22864
23274
|
if (existing !== null && !isGeneratedCursorRule(existing, fileName)) {
|
|
22865
23275
|
throw new Error(
|
|
22866
23276
|
`refusing to overwrite user-authored Cursor rule: ${rulePath}`
|
|
22867
23277
|
);
|
|
22868
23278
|
}
|
|
22869
|
-
await
|
|
23279
|
+
await writeFile33(
|
|
22870
23280
|
rulePath,
|
|
22871
23281
|
content.replace("---\n\n", `---
|
|
22872
23282
|
|
|
@@ -22880,23 +23290,23 @@ async function removeAdvancedRules(rulesDir) {
|
|
|
22880
23290
|
for (const fileName of MANCODE_CURSOR_ADVANCED_RULE_FILES) {
|
|
22881
23291
|
await removeGeneratedCursorRule(rulesDir, fileName);
|
|
22882
23292
|
}
|
|
22883
|
-
await removeLegacyCursorRules(
|
|
23293
|
+
await removeLegacyCursorRules(path39.dirname(path39.dirname(rulesDir)));
|
|
22884
23294
|
}
|
|
22885
23295
|
async function removeCursorGeneratedRules(projectRoot) {
|
|
22886
|
-
const rulesDir =
|
|
23296
|
+
const rulesDir = path39.join(projectRoot, ".cursor", "rules");
|
|
22887
23297
|
for (const fileName of MANCODE_CURSOR_RULE_FILES) {
|
|
22888
23298
|
await removeGeneratedCursorRule(rulesDir, fileName);
|
|
22889
23299
|
}
|
|
22890
23300
|
await removeLegacyCursorRules(projectRoot);
|
|
22891
23301
|
}
|
|
22892
23302
|
async function removeLegacyCursorRules(projectRoot) {
|
|
22893
|
-
const rulesDir =
|
|
23303
|
+
const rulesDir = path39.join(projectRoot, ".cursor", "rules");
|
|
22894
23304
|
for (const fileName of MANCODE_CURSOR_LEGACY_RULE_FILES) {
|
|
22895
23305
|
await removeGeneratedCursorRule(rulesDir, fileName);
|
|
22896
23306
|
}
|
|
22897
23307
|
}
|
|
22898
23308
|
async function removeGeneratedCursorRule(rulesDir, fileName) {
|
|
22899
|
-
const rulePath =
|
|
23309
|
+
const rulePath = path39.join(rulesDir, fileName);
|
|
22900
23310
|
const content = await readTextIfExists4(rulePath);
|
|
22901
23311
|
if (content && isGeneratedCursorRule(content, fileName)) {
|
|
22902
23312
|
await rm15(rulePath, { force: true });
|
|
@@ -22918,7 +23328,7 @@ function isGeneratedCursorRule(content, fileName) {
|
|
|
22918
23328
|
}
|
|
22919
23329
|
async function readTextIfExists4(filePath) {
|
|
22920
23330
|
try {
|
|
22921
|
-
return await
|
|
23331
|
+
return await readFile34(filePath, "utf-8");
|
|
22922
23332
|
} catch (error) {
|
|
22923
23333
|
if (isNodeError5(error) && error.code === "ENOENT") return null;
|
|
22924
23334
|
throw error;
|
|
@@ -22972,16 +23382,16 @@ function renderManpsRule() {
|
|
|
22972
23382
|
|
|
22973
23383
|
// src/installers/platform-status.ts
|
|
22974
23384
|
import { promises as fs } from "fs";
|
|
22975
|
-
import
|
|
23385
|
+
import path41 from "path";
|
|
22976
23386
|
|
|
22977
23387
|
// src/installers/zcode.ts
|
|
22978
|
-
import { writeFile as
|
|
22979
|
-
import
|
|
23388
|
+
import { writeFile as writeFile34 } from "fs/promises";
|
|
23389
|
+
import path40 from "path";
|
|
22980
23390
|
var ZCODE_MANCODE_START_MARKER = "<!-- mancode:zcode:start -->";
|
|
22981
23391
|
var ZCODE_MANCODE_END_MARKER = "<!-- mancode:zcode:end -->";
|
|
22982
23392
|
async function installZcode(projectRoot, options) {
|
|
22983
23393
|
await installMancodeCore(projectRoot);
|
|
22984
|
-
const agentsPath =
|
|
23394
|
+
const agentsPath = path40.join(projectRoot, "AGENTS.md");
|
|
22985
23395
|
const existing = await readTextIfExists(agentsPath);
|
|
22986
23396
|
const sharedContent = await generateSharedContent(projectRoot, {
|
|
22987
23397
|
platform: "zcode",
|
|
@@ -23006,7 +23416,7 @@ async function installZcode(projectRoot, options) {
|
|
|
23006
23416
|
sharedContent.trim(),
|
|
23007
23417
|
ZCODE_MANCODE_END_MARKER
|
|
23008
23418
|
].join("\n");
|
|
23009
|
-
await
|
|
23419
|
+
await writeFile34(
|
|
23010
23420
|
agentsPath,
|
|
23011
23421
|
replaceManagedBlock(
|
|
23012
23422
|
existing,
|
|
@@ -23036,13 +23446,13 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23036
23446
|
if (platform === "claude-code") {
|
|
23037
23447
|
const [hasSoloSkill, registered, hasHookFiles] = await Promise.all([
|
|
23038
23448
|
fileMatches(
|
|
23039
|
-
|
|
23449
|
+
path41.join(rootDir, ".claude", "skills", "solo", "SKILL.md"),
|
|
23040
23450
|
(content) => isGeneratedClaudeSkill(content, "solo")
|
|
23041
23451
|
),
|
|
23042
23452
|
claudeHooksRegistered(rootDir),
|
|
23043
23453
|
pathsExist([
|
|
23044
|
-
|
|
23045
|
-
|
|
23454
|
+
path41.join(rootDir, ".mancode", "hooks", "session-start.mjs"),
|
|
23455
|
+
path41.join(rootDir, ".mancode", "hooks", "user-prompt-submit.mjs")
|
|
23046
23456
|
])
|
|
23047
23457
|
]);
|
|
23048
23458
|
const present = hasSoloSkill && registered && hasHookFiles;
|
|
@@ -23058,7 +23468,7 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23058
23468
|
if (platform === "cursor") {
|
|
23059
23469
|
const hasCoreRules = await allManagedSkills(
|
|
23060
23470
|
MANCODE_CURSOR_CORE_RULE_FILES.map(
|
|
23061
|
-
(file) =>
|
|
23471
|
+
(file) => path41.join(rootDir, ".cursor", "rules", file)
|
|
23062
23472
|
),
|
|
23063
23473
|
[CURSOR_RULE_MANAGED_MARKER]
|
|
23064
23474
|
);
|
|
@@ -23073,13 +23483,13 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23073
23483
|
const [hasRules, hasCommands] = await Promise.all([
|
|
23074
23484
|
allManagedSkills(
|
|
23075
23485
|
MANCODE_CURSOR_RULE_FILES.map(
|
|
23076
|
-
(file) =>
|
|
23486
|
+
(file) => path41.join(rootDir, ".cursor", "rules", file)
|
|
23077
23487
|
),
|
|
23078
23488
|
[CURSOR_RULE_MANAGED_MARKER]
|
|
23079
23489
|
),
|
|
23080
23490
|
allManagedSkills(
|
|
23081
23491
|
MODE_NAMES.map(
|
|
23082
|
-
(mode) =>
|
|
23492
|
+
(mode) => path41.join(rootDir, ".cursor", "commands", `${mode}.md`)
|
|
23083
23493
|
),
|
|
23084
23494
|
[MODE_FILE_MANAGED_MARKER]
|
|
23085
23495
|
)
|
|
@@ -23092,7 +23502,7 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23092
23502
|
};
|
|
23093
23503
|
}
|
|
23094
23504
|
if (platform === "codex") {
|
|
23095
|
-
const hasBlock2 = await fileHasManagedBlock(
|
|
23505
|
+
const hasBlock2 = await fileHasManagedBlock(path41.join(rootDir, "AGENTS.md"));
|
|
23096
23506
|
if (!hasBlock2) {
|
|
23097
23507
|
return {
|
|
23098
23508
|
present: false,
|
|
@@ -23109,9 +23519,9 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23109
23519
|
readyDetail: "managed block present"
|
|
23110
23520
|
};
|
|
23111
23521
|
}
|
|
23112
|
-
const skillsDir =
|
|
23522
|
+
const skillsDir = path41.join(rootDir, ".agents", "skills");
|
|
23113
23523
|
const hasSkills = await allManagedSkills(
|
|
23114
|
-
MODE_NAMES.map((mode) =>
|
|
23524
|
+
MODE_NAMES.map((mode) => path41.join(skillsDir, mode, "SKILL.md")),
|
|
23115
23525
|
MANCODE_AGENT_SKILL_MARKERS
|
|
23116
23526
|
);
|
|
23117
23527
|
return {
|
|
@@ -23123,7 +23533,7 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23123
23533
|
}
|
|
23124
23534
|
if (platform === "zcode") {
|
|
23125
23535
|
const hasBlock2 = await fileHasManagedBlock(
|
|
23126
|
-
|
|
23536
|
+
path41.join(rootDir, "AGENTS.md"),
|
|
23127
23537
|
ZCODE_MANCODE_START_MARKER,
|
|
23128
23538
|
ZCODE_MANCODE_END_MARKER
|
|
23129
23539
|
);
|
|
@@ -23143,9 +23553,9 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23143
23553
|
readyDetail: "managed block present"
|
|
23144
23554
|
};
|
|
23145
23555
|
}
|
|
23146
|
-
const skillsDir =
|
|
23556
|
+
const skillsDir = path41.join(rootDir, ".agents", "skills");
|
|
23147
23557
|
const hasSkills = await allManagedSkills(
|
|
23148
|
-
MODE_NAMES.map((mode) =>
|
|
23558
|
+
MODE_NAMES.map((mode) => path41.join(skillsDir, mode, "SKILL.md")),
|
|
23149
23559
|
MANCODE_AGENT_SKILL_MARKERS
|
|
23150
23560
|
);
|
|
23151
23561
|
return {
|
|
@@ -23156,7 +23566,7 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23156
23566
|
};
|
|
23157
23567
|
}
|
|
23158
23568
|
const hasBlock = await fileHasManagedBlock(
|
|
23159
|
-
|
|
23569
|
+
path41.join(rootDir, ".github", "copilot-instructions.md")
|
|
23160
23570
|
);
|
|
23161
23571
|
if (!hasBlock) {
|
|
23162
23572
|
return {
|
|
@@ -23167,9 +23577,9 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23167
23577
|
};
|
|
23168
23578
|
}
|
|
23169
23579
|
if (!await isPlatformMinimal(rootDir, "copilot")) {
|
|
23170
|
-
const promptsDir =
|
|
23580
|
+
const promptsDir = path41.join(rootDir, ".github", "prompts");
|
|
23171
23581
|
const hasPrompts = await allManagedSkills(
|
|
23172
|
-
MODE_NAMES.map((mode) =>
|
|
23582
|
+
MODE_NAMES.map((mode) => path41.join(promptsDir, `${mode}.prompt.md`)),
|
|
23173
23583
|
[MODE_FILE_MANAGED_MARKER]
|
|
23174
23584
|
);
|
|
23175
23585
|
return {
|
|
@@ -23202,13 +23612,13 @@ async function allManagedSkills(paths, markers) {
|
|
|
23202
23612
|
async function claudeFullContentReady(rootDir) {
|
|
23203
23613
|
const skillChecks = MVP2_SKILLS.map(
|
|
23204
23614
|
(skill) => fileMatches(
|
|
23205
|
-
|
|
23615
|
+
path41.join(rootDir, ".claude", "skills", skill.name, "SKILL.md"),
|
|
23206
23616
|
(content) => isGeneratedClaudeSkill(content, skill.name)
|
|
23207
23617
|
)
|
|
23208
23618
|
);
|
|
23209
23619
|
const agentChecks = ALL_AGENTS.map(
|
|
23210
23620
|
(agent) => fileMatches(
|
|
23211
|
-
|
|
23621
|
+
path41.join(rootDir, ".claude", "agents", `${agent.name}.md`),
|
|
23212
23622
|
(content) => isGeneratedClaudeAgent(content, agent.name)
|
|
23213
23623
|
)
|
|
23214
23624
|
);
|
|
@@ -23236,7 +23646,7 @@ async function fileHasAnyMarker(filePath, needles) {
|
|
|
23236
23646
|
async function isPlatformMinimal(rootDir, platform) {
|
|
23237
23647
|
try {
|
|
23238
23648
|
const raw = await fs.readFile(
|
|
23239
|
-
|
|
23649
|
+
path41.join(rootDir, ".mancode", "config.json"),
|
|
23240
23650
|
"utf-8"
|
|
23241
23651
|
);
|
|
23242
23652
|
const config = JSON.parse(raw);
|
|
@@ -23258,7 +23668,7 @@ async function fileHasManagedBlock(filePath, startMarker = DEFAULT_MANCODE_START
|
|
|
23258
23668
|
async function claudeHooksRegistered(rootDir) {
|
|
23259
23669
|
try {
|
|
23260
23670
|
const raw = await fs.readFile(
|
|
23261
|
-
|
|
23671
|
+
path41.join(rootDir, ".claude", "settings.json"),
|
|
23262
23672
|
"utf-8"
|
|
23263
23673
|
);
|
|
23264
23674
|
const settings = JSON.parse(raw);
|
|
@@ -23299,11 +23709,11 @@ function isRecord6(value) {
|
|
|
23299
23709
|
}
|
|
23300
23710
|
|
|
23301
23711
|
// src/installers/codex.ts
|
|
23302
|
-
import { writeFile as
|
|
23303
|
-
import
|
|
23712
|
+
import { writeFile as writeFile35 } from "fs/promises";
|
|
23713
|
+
import path42 from "path";
|
|
23304
23714
|
async function installCodex(projectRoot, options) {
|
|
23305
23715
|
await installMancodeCore(projectRoot);
|
|
23306
|
-
const agentsPath =
|
|
23716
|
+
const agentsPath = path42.join(projectRoot, "AGENTS.md");
|
|
23307
23717
|
const existing = await readTextIfExists(agentsPath);
|
|
23308
23718
|
const sharedContent = await generateSharedContent(projectRoot, {
|
|
23309
23719
|
platform: "codex",
|
|
@@ -23328,18 +23738,18 @@ async function installCodex(projectRoot, options) {
|
|
|
23328
23738
|
sharedContent.trim(),
|
|
23329
23739
|
DEFAULT_MANCODE_END_MARKER
|
|
23330
23740
|
].join("\n");
|
|
23331
|
-
await
|
|
23741
|
+
await writeFile35(agentsPath, replaceManagedBlock(existing, block), "utf-8");
|
|
23332
23742
|
await installCodexSkills(projectRoot, options.minimal ?? false);
|
|
23333
23743
|
}
|
|
23334
23744
|
|
|
23335
23745
|
// src/installers/copilot.ts
|
|
23336
|
-
import { mkdir as
|
|
23337
|
-
import
|
|
23746
|
+
import { mkdir as mkdir31, writeFile as writeFile36 } from "fs/promises";
|
|
23747
|
+
import path43 from "path";
|
|
23338
23748
|
async function installCopilot(projectRoot, options) {
|
|
23339
23749
|
await installMancodeCore(projectRoot);
|
|
23340
|
-
const githubDir =
|
|
23341
|
-
await
|
|
23342
|
-
const instructionsPath =
|
|
23750
|
+
const githubDir = path43.join(projectRoot, ".github");
|
|
23751
|
+
await mkdir31(githubDir, { recursive: true });
|
|
23752
|
+
const instructionsPath = path43.join(githubDir, "copilot-instructions.md");
|
|
23343
23753
|
const existing = await readTextIfExists(instructionsPath);
|
|
23344
23754
|
const sharedContent = await generateSharedContent(projectRoot, {
|
|
23345
23755
|
platform: "copilot",
|
|
@@ -23367,7 +23777,7 @@ async function installCopilot(projectRoot, options) {
|
|
|
23367
23777
|
sections.push("", renderCopilotPromptConventions());
|
|
23368
23778
|
}
|
|
23369
23779
|
sections.push(DEFAULT_MANCODE_END_MARKER);
|
|
23370
|
-
await
|
|
23780
|
+
await writeFile36(
|
|
23371
23781
|
instructionsPath,
|
|
23372
23782
|
replaceManagedBlock(existing, sections.join("\n")),
|
|
23373
23783
|
"utf-8"
|
|
@@ -23463,12 +23873,12 @@ function isPlatformName(platform) {
|
|
|
23463
23873
|
}
|
|
23464
23874
|
|
|
23465
23875
|
// src/system/detect-team.ts
|
|
23466
|
-
import { execFile as
|
|
23876
|
+
import { execFile as execFile6 } from "child_process";
|
|
23467
23877
|
import { access as access2 } from "fs/promises";
|
|
23468
|
-
import
|
|
23878
|
+
import path44 from "path";
|
|
23469
23879
|
import process2 from "process";
|
|
23470
|
-
import { promisify as
|
|
23471
|
-
var execFileAsync =
|
|
23880
|
+
import { promisify as promisify6 } from "util";
|
|
23881
|
+
var execFileAsync = promisify6(execFile6);
|
|
23472
23882
|
var NO_TEAM = {
|
|
23473
23883
|
isTeam: false,
|
|
23474
23884
|
contributors: 1,
|
|
@@ -23575,7 +23985,7 @@ async function anyPathExists(projectRoot, candidates) {
|
|
|
23575
23985
|
const results = await Promise.all(
|
|
23576
23986
|
candidates.map(async (candidate) => {
|
|
23577
23987
|
try {
|
|
23578
|
-
await access2(
|
|
23988
|
+
await access2(path44.join(projectRoot, candidate));
|
|
23579
23989
|
return true;
|
|
23580
23990
|
} catch {
|
|
23581
23991
|
return false;
|
|
@@ -23597,10 +24007,10 @@ function emptySignals(isGitRepository) {
|
|
|
23597
24007
|
}
|
|
23598
24008
|
|
|
23599
24009
|
// src/system/detect.ts
|
|
23600
|
-
import { execFile as
|
|
24010
|
+
import { execFile as execFile7 } from "child_process";
|
|
23601
24011
|
import process3 from "process";
|
|
23602
|
-
import { promisify as
|
|
23603
|
-
var execFileAsync2 =
|
|
24012
|
+
import { promisify as promisify7 } from "util";
|
|
24013
|
+
var execFileAsync2 = promisify7(execFile7);
|
|
23604
24014
|
async function detectSystemDeps(env = process3.env) {
|
|
23605
24015
|
try {
|
|
23606
24016
|
await execFileAsync2("git", ["--version"], {
|
|
@@ -23616,7 +24026,7 @@ async function detectSystemDeps(env = process3.env) {
|
|
|
23616
24026
|
// src/system/init-onboarding.ts
|
|
23617
24027
|
import { execFileSync } from "child_process";
|
|
23618
24028
|
import { promises as fs2 } from "fs";
|
|
23619
|
-
import
|
|
24029
|
+
import path45 from "path";
|
|
23620
24030
|
import process4 from "process";
|
|
23621
24031
|
import { stdin, stdout } from "process";
|
|
23622
24032
|
import { createInterface } from "readline/promises";
|
|
@@ -23721,7 +24131,7 @@ async function detectPlatformHints(rootDir, environment = process4.env) {
|
|
|
23721
24131
|
hints.add("copilot");
|
|
23722
24132
|
const exists = async (relative) => {
|
|
23723
24133
|
try {
|
|
23724
|
-
await fs2.access(
|
|
24134
|
+
await fs2.access(path45.join(rootDir, relative));
|
|
23725
24135
|
return true;
|
|
23726
24136
|
} catch {
|
|
23727
24137
|
return false;
|
|
@@ -23797,7 +24207,7 @@ function createTerminalPrompter() {
|
|
|
23797
24207
|
|
|
23798
24208
|
// src/system/scan-aesthetics.ts
|
|
23799
24209
|
import { promises as fs3 } from "fs";
|
|
23800
|
-
import
|
|
24210
|
+
import path46 from "path";
|
|
23801
24211
|
var MAX_COMPONENT_SCAN_DEPTH = 12;
|
|
23802
24212
|
var MAX_COMPONENT_FILES = 2e3;
|
|
23803
24213
|
async function scanAesthetics(projectRoot, uiLibrary = null) {
|
|
@@ -23833,7 +24243,7 @@ async function scanAesthetics(projectRoot, uiLibrary = null) {
|
|
|
23833
24243
|
} else if (await hasTailwindDep(projectRoot) || uiLibrary) {
|
|
23834
24244
|
matchLevel = "low";
|
|
23835
24245
|
}
|
|
23836
|
-
if (uiLibrary && await pathExists5(
|
|
24246
|
+
if (uiLibrary && await pathExists5(path46.join(projectRoot, "package.json"))) {
|
|
23837
24247
|
sourceFiles.push("package.json");
|
|
23838
24248
|
}
|
|
23839
24249
|
sourceFiles.push(...cssScan.sourceFiles);
|
|
@@ -23858,7 +24268,7 @@ async function findTailwindConfig(projectRoot) {
|
|
|
23858
24268
|
"tailwind.config.mjs"
|
|
23859
24269
|
];
|
|
23860
24270
|
for (const name of candidates) {
|
|
23861
|
-
const absPath =
|
|
24271
|
+
const absPath = path46.join(projectRoot, name);
|
|
23862
24272
|
if (await pathExists5(absPath)) {
|
|
23863
24273
|
return { absPath, relPath: name };
|
|
23864
24274
|
}
|
|
@@ -24085,7 +24495,7 @@ async function scanComponents(projectRoot) {
|
|
|
24085
24495
|
const names = /* @__PURE__ */ new Set();
|
|
24086
24496
|
let visitedFiles = 0;
|
|
24087
24497
|
for (const relRoot of roots) {
|
|
24088
|
-
const absRoot =
|
|
24498
|
+
const absRoot = path46.join(projectRoot, relRoot);
|
|
24089
24499
|
if (!await pathExists5(absRoot)) continue;
|
|
24090
24500
|
visitedFiles = await collectComponentNames(absRoot, names, 0, visitedFiles);
|
|
24091
24501
|
if (visitedFiles >= MAX_COMPONENT_FILES) break;
|
|
@@ -24105,7 +24515,7 @@ async function collectComponentNames(dir, names, depth, visitedFiles) {
|
|
|
24105
24515
|
}
|
|
24106
24516
|
for (const entry of entries) {
|
|
24107
24517
|
if (fileCount >= MAX_COMPONENT_FILES) return fileCount;
|
|
24108
|
-
const abs =
|
|
24518
|
+
const abs = path46.join(dir, entry);
|
|
24109
24519
|
let info;
|
|
24110
24520
|
try {
|
|
24111
24521
|
info = await fs3.lstat(abs);
|
|
@@ -24126,7 +24536,7 @@ async function collectComponentNames(dir, names, depth, visitedFiles) {
|
|
|
24126
24536
|
""
|
|
24127
24537
|
);
|
|
24128
24538
|
if (base === "index") {
|
|
24129
|
-
base =
|
|
24539
|
+
base = path46.basename(dir);
|
|
24130
24540
|
}
|
|
24131
24541
|
if (base.startsWith(".")) continue;
|
|
24132
24542
|
const componentName = toPascalCase(base);
|
|
@@ -24148,7 +24558,7 @@ async function scanCssVariables(projectRoot) {
|
|
|
24148
24558
|
const variables = {};
|
|
24149
24559
|
const sourceFiles = [];
|
|
24150
24560
|
for (const relPath of candidates) {
|
|
24151
|
-
const absPath =
|
|
24561
|
+
const absPath = path46.join(projectRoot, relPath);
|
|
24152
24562
|
if (!await pathExists5(absPath)) continue;
|
|
24153
24563
|
const content = await fs3.readFile(absPath, "utf-8");
|
|
24154
24564
|
const found = extractCssVariables(content);
|
|
@@ -24194,7 +24604,7 @@ function toPascalCase(value) {
|
|
|
24194
24604
|
async function hasTailwindDep(projectRoot) {
|
|
24195
24605
|
try {
|
|
24196
24606
|
const raw = await fs3.readFile(
|
|
24197
|
-
|
|
24607
|
+
path46.join(projectRoot, "package.json"),
|
|
24198
24608
|
"utf-8"
|
|
24199
24609
|
);
|
|
24200
24610
|
const pkg = JSON.parse(raw);
|
|
@@ -24219,15 +24629,15 @@ async function pathExists5(p) {
|
|
|
24219
24629
|
|
|
24220
24630
|
// src/context/greenfield-init.ts
|
|
24221
24631
|
import {
|
|
24222
|
-
lstat as
|
|
24223
|
-
mkdir as
|
|
24224
|
-
readFile as
|
|
24632
|
+
lstat as lstat18,
|
|
24633
|
+
mkdir as mkdir32,
|
|
24634
|
+
readFile as readFile35,
|
|
24225
24635
|
rename as rename8,
|
|
24226
24636
|
rm as rm16,
|
|
24227
|
-
writeFile as
|
|
24637
|
+
writeFile as writeFile37
|
|
24228
24638
|
} from "fs/promises";
|
|
24229
|
-
import
|
|
24230
|
-
var JOURNAL_RELATIVE_DIRECTORY =
|
|
24639
|
+
import path47 from "path";
|
|
24640
|
+
var JOURNAL_RELATIVE_DIRECTORY = path47.join(
|
|
24231
24641
|
"local",
|
|
24232
24642
|
"runtime",
|
|
24233
24643
|
"initialization"
|
|
@@ -24250,9 +24660,9 @@ async function stageGreenfieldInitialization(input) {
|
|
|
24250
24660
|
normalized.operationId
|
|
24251
24661
|
);
|
|
24252
24662
|
try {
|
|
24253
|
-
await
|
|
24663
|
+
await mkdir32(stagingRoot);
|
|
24254
24664
|
} catch (error) {
|
|
24255
|
-
if (
|
|
24665
|
+
if (isAlreadyExists22(error)) {
|
|
24256
24666
|
throw new Error("MANCODE_GREENFIELD_STAGING_EXISTS");
|
|
24257
24667
|
}
|
|
24258
24668
|
throw error;
|
|
@@ -24271,7 +24681,7 @@ async function stageGreenfieldInitialization(input) {
|
|
|
24271
24681
|
operationId: normalized.operationId,
|
|
24272
24682
|
workspaceId: normalized.workspaceId,
|
|
24273
24683
|
state: "staged",
|
|
24274
|
-
stagingDirectoryName:
|
|
24684
|
+
stagingDirectoryName: path47.basename(stagingRoot),
|
|
24275
24685
|
targetDirectoryName: ".mancode",
|
|
24276
24686
|
manifestDigest: digestCanonicalJson(manifest),
|
|
24277
24687
|
configDigest: digestCanonicalJson(config),
|
|
@@ -24301,7 +24711,7 @@ async function stageGreenfieldInitialization(input) {
|
|
|
24301
24711
|
return journal;
|
|
24302
24712
|
}
|
|
24303
24713
|
async function publishGreenfieldInitialization(input) {
|
|
24304
|
-
const root =
|
|
24714
|
+
const root = path47.resolve(input.projectRoot);
|
|
24305
24715
|
assertUlid(input.operationId, "greenfield operationId");
|
|
24306
24716
|
const stagingRoot = greenfieldStagingPath(root, input.operationId);
|
|
24307
24717
|
const targetRoot = greenfieldTargetPath(root);
|
|
@@ -24330,10 +24740,10 @@ async function initializeGreenfield(input, publication) {
|
|
|
24330
24740
|
}
|
|
24331
24741
|
function greenfieldStagingPath(projectRoot, operationId) {
|
|
24332
24742
|
assertUlid(operationId, "greenfield operationId");
|
|
24333
|
-
return
|
|
24743
|
+
return path47.join(path47.resolve(projectRoot), `.mancode.init-${operationId}`);
|
|
24334
24744
|
}
|
|
24335
24745
|
function greenfieldTargetPath(projectRoot) {
|
|
24336
|
-
return
|
|
24746
|
+
return path47.join(path47.resolve(projectRoot), ".mancode");
|
|
24337
24747
|
}
|
|
24338
24748
|
function parseGreenfieldInitializationJournal(value) {
|
|
24339
24749
|
assertRecord(value, "greenfield initialization journal");
|
|
@@ -24436,7 +24846,7 @@ async function finishPublishedInitialization(input, stagedJournal) {
|
|
|
24436
24846
|
activatedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString()
|
|
24437
24847
|
};
|
|
24438
24848
|
assertSchemaManifestTransition(manifest, activeManifest);
|
|
24439
|
-
await writeJson(
|
|
24849
|
+
await writeJson(path47.join(targetRoot, "schema.json"), activeManifest);
|
|
24440
24850
|
throwIfOperationCrashInjected(
|
|
24441
24851
|
"greenfield_initialize",
|
|
24442
24852
|
"activate-v3-manifest"
|
|
@@ -24452,46 +24862,46 @@ async function finishPublishedInitialization(input, stagedJournal) {
|
|
|
24452
24862
|
}
|
|
24453
24863
|
async function writeGreenfieldLayout(stagingRoot, manifest, config, policy, projectFacts, journal) {
|
|
24454
24864
|
await Promise.all([
|
|
24455
|
-
|
|
24456
|
-
|
|
24865
|
+
mkdir32(path47.join(stagingRoot, "shared", "context"), { recursive: true }),
|
|
24866
|
+
mkdir32(path47.join(stagingRoot, "shared", "memory", "decisions"), {
|
|
24457
24867
|
recursive: true
|
|
24458
24868
|
}),
|
|
24459
|
-
|
|
24869
|
+
mkdir32(path47.join(stagingRoot, "shared", "team", "actors"), {
|
|
24460
24870
|
recursive: true
|
|
24461
24871
|
}),
|
|
24462
|
-
|
|
24872
|
+
mkdir32(path47.join(stagingRoot, "shared", "team", "handoffs"), {
|
|
24463
24873
|
recursive: true
|
|
24464
24874
|
}),
|
|
24465
|
-
|
|
24875
|
+
mkdir32(path47.join(stagingRoot, "shared", "team", "events"), {
|
|
24466
24876
|
recursive: true
|
|
24467
24877
|
}),
|
|
24468
|
-
|
|
24878
|
+
mkdir32(path47.join(stagingRoot, "shared", "team", "transport"), {
|
|
24469
24879
|
recursive: true
|
|
24470
24880
|
}),
|
|
24471
|
-
|
|
24472
|
-
|
|
24881
|
+
mkdir32(path47.join(stagingRoot, "local", "sessions"), { recursive: true }),
|
|
24882
|
+
mkdir32(path47.join(stagingRoot, JOURNAL_RELATIVE_DIRECTORY), {
|
|
24473
24883
|
recursive: true
|
|
24474
24884
|
}),
|
|
24475
|
-
|
|
24476
|
-
|
|
24477
|
-
|
|
24478
|
-
|
|
24479
|
-
|
|
24480
|
-
|
|
24885
|
+
mkdir32(path47.join(stagingRoot, "local", "workflows"), { recursive: true }),
|
|
24886
|
+
mkdir32(path47.join(stagingRoot, "local", "overlays"), { recursive: true }),
|
|
24887
|
+
mkdir32(path47.join(stagingRoot, "local", "quarantine"), { recursive: true }),
|
|
24888
|
+
mkdir32(path47.join(stagingRoot, "local", "publish"), { recursive: true }),
|
|
24889
|
+
mkdir32(path47.join(stagingRoot, "local", "cache"), { recursive: true }),
|
|
24890
|
+
mkdir32(path47.join(stagingRoot, "runtime", "non-git", journal.workspaceId), {
|
|
24481
24891
|
recursive: true
|
|
24482
24892
|
})
|
|
24483
24893
|
]);
|
|
24484
24894
|
await Promise.all([
|
|
24485
|
-
writeJson(
|
|
24486
|
-
writeJson(
|
|
24487
|
-
writeJson(
|
|
24895
|
+
writeJson(path47.join(stagingRoot, "schema.json"), manifest),
|
|
24896
|
+
writeJson(path47.join(stagingRoot, "shared", "config.json"), config),
|
|
24897
|
+
writeJson(path47.join(stagingRoot, "shared", "team", "policy.json"), policy),
|
|
24488
24898
|
writeJson(
|
|
24489
|
-
|
|
24899
|
+
path47.join(stagingRoot, "shared", "context", "project.json"),
|
|
24490
24900
|
projectFacts
|
|
24491
24901
|
),
|
|
24492
24902
|
writeJson(journalPath2(stagingRoot, journal.operationId), journal),
|
|
24493
|
-
|
|
24494
|
-
|
|
24903
|
+
writeFile37(
|
|
24904
|
+
path47.join(stagingRoot, ".gitignore"),
|
|
24495
24905
|
`${V3_IGNORE.join("\n")}
|
|
24496
24906
|
`,
|
|
24497
24907
|
{ encoding: "utf8", flag: "wx" }
|
|
@@ -24500,14 +24910,14 @@ async function writeGreenfieldLayout(stagingRoot, manifest, config, policy, proj
|
|
|
24500
24910
|
}
|
|
24501
24911
|
async function readGreenfieldJournal(root, operationId) {
|
|
24502
24912
|
try {
|
|
24503
|
-
const raw = await
|
|
24913
|
+
const raw = await readFile35(journalPath2(root, operationId), "utf8");
|
|
24504
24914
|
const journal = parseGreenfieldInitializationJournal(JSON.parse(raw));
|
|
24505
24915
|
if (journal.operationId !== operationId) {
|
|
24506
24916
|
throw new Error("MANCODE_GREENFIELD_JOURNAL_CORRUPT");
|
|
24507
24917
|
}
|
|
24508
24918
|
return journal;
|
|
24509
24919
|
} catch (error) {
|
|
24510
|
-
if (error instanceof SyntaxError ||
|
|
24920
|
+
if (error instanceof SyntaxError || isNotFound26(error)) {
|
|
24511
24921
|
throw new Error("MANCODE_GREENFIELD_JOURNAL_CORRUPT");
|
|
24512
24922
|
}
|
|
24513
24923
|
throw error;
|
|
@@ -24516,10 +24926,10 @@ async function readGreenfieldJournal(root, operationId) {
|
|
|
24516
24926
|
async function readManifest(root) {
|
|
24517
24927
|
try {
|
|
24518
24928
|
return parseSchemaManifest(
|
|
24519
|
-
JSON.parse(await
|
|
24929
|
+
JSON.parse(await readFile35(path47.join(root, "schema.json"), "utf8"))
|
|
24520
24930
|
);
|
|
24521
24931
|
} catch (error) {
|
|
24522
|
-
if (error instanceof SyntaxError ||
|
|
24932
|
+
if (error instanceof SyntaxError || isNotFound26(error)) {
|
|
24523
24933
|
throw new Error("MANCODE_GREENFIELD_REPAIR_REQUIRED");
|
|
24524
24934
|
}
|
|
24525
24935
|
throw error;
|
|
@@ -24554,7 +24964,7 @@ async function readConfig(root) {
|
|
|
24554
24964
|
try {
|
|
24555
24965
|
config = parseProjectConfig(
|
|
24556
24966
|
JSON.parse(
|
|
24557
|
-
await
|
|
24967
|
+
await readFile35(path47.join(root, "shared", "config.json"), "utf8")
|
|
24558
24968
|
)
|
|
24559
24969
|
);
|
|
24560
24970
|
} catch (error) {
|
|
@@ -24570,8 +24980,8 @@ async function readPolicy(root) {
|
|
|
24570
24980
|
try {
|
|
24571
24981
|
policy = parseTeamPolicy(
|
|
24572
24982
|
JSON.parse(
|
|
24573
|
-
await
|
|
24574
|
-
|
|
24983
|
+
await readFile35(
|
|
24984
|
+
path47.join(root, "shared", "team", "policy.json"),
|
|
24575
24985
|
"utf8"
|
|
24576
24986
|
)
|
|
24577
24987
|
)
|
|
@@ -24588,14 +24998,14 @@ async function readProjectFactsAt(root) {
|
|
|
24588
24998
|
try {
|
|
24589
24999
|
return parseProjectFacts(
|
|
24590
25000
|
JSON.parse(
|
|
24591
|
-
await
|
|
24592
|
-
|
|
25001
|
+
await readFile35(
|
|
25002
|
+
path47.join(root, "shared", "context", "project.json"),
|
|
24593
25003
|
"utf8"
|
|
24594
25004
|
)
|
|
24595
25005
|
)
|
|
24596
25006
|
);
|
|
24597
25007
|
} catch (error) {
|
|
24598
|
-
if (error instanceof SyntaxError ||
|
|
25008
|
+
if (error instanceof SyntaxError || isNotFound26(error)) {
|
|
24599
25009
|
throw new Error("MANCODE_GREENFIELD_REPAIR_REQUIRED");
|
|
24600
25010
|
}
|
|
24601
25011
|
throw error;
|
|
@@ -24628,7 +25038,7 @@ function normalizeInput(input) {
|
|
|
24628
25038
|
parseSchemaManifest(manifest);
|
|
24629
25039
|
return {
|
|
24630
25040
|
...input,
|
|
24631
|
-
projectRoot:
|
|
25041
|
+
projectRoot: path47.resolve(input.projectRoot),
|
|
24632
25042
|
projectConfig: config,
|
|
24633
25043
|
teamPolicy: policy,
|
|
24634
25044
|
projectFacts: input.projectFacts === void 0 ? void 0 : parseProjectFacts(input.projectFacts)
|
|
@@ -24677,16 +25087,16 @@ function initializationProjectFacts(input, now) {
|
|
|
24677
25087
|
}
|
|
24678
25088
|
function journalPath2(root, operationId) {
|
|
24679
25089
|
assertUlid(operationId, "greenfield operationId");
|
|
24680
|
-
return
|
|
25090
|
+
return path47.join(root, JOURNAL_RELATIVE_DIRECTORY, `${operationId}.json`);
|
|
24681
25091
|
}
|
|
24682
25092
|
async function writeJson(target, value) {
|
|
24683
|
-
const directory =
|
|
24684
|
-
await
|
|
24685
|
-
const temporary =
|
|
25093
|
+
const directory = path47.dirname(target);
|
|
25094
|
+
await mkdir32(directory, { recursive: true });
|
|
25095
|
+
const temporary = path47.join(
|
|
24686
25096
|
directory,
|
|
24687
|
-
`.${
|
|
25097
|
+
`.${path47.basename(target)}.${process.pid}.${Date.now()}.tmp`
|
|
24688
25098
|
);
|
|
24689
|
-
await
|
|
25099
|
+
await writeFile37(temporary, `${JSON.stringify(value, null, 2)}
|
|
24690
25100
|
`, {
|
|
24691
25101
|
encoding: "utf8",
|
|
24692
25102
|
flag: "wx"
|
|
@@ -24710,16 +25120,16 @@ function isState(value) {
|
|
|
24710
25120
|
}
|
|
24711
25121
|
async function lstatOrNull4(target) {
|
|
24712
25122
|
try {
|
|
24713
|
-
return await
|
|
25123
|
+
return await lstat18(target);
|
|
24714
25124
|
} catch (error) {
|
|
24715
|
-
if (
|
|
25125
|
+
if (isNotFound26(error)) return null;
|
|
24716
25126
|
throw error;
|
|
24717
25127
|
}
|
|
24718
25128
|
}
|
|
24719
|
-
function
|
|
25129
|
+
function isNotFound26(error) {
|
|
24720
25130
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
24721
25131
|
}
|
|
24722
|
-
function
|
|
25132
|
+
function isAlreadyExists22(error) {
|
|
24723
25133
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
24724
25134
|
}
|
|
24725
25135
|
|
|
@@ -24813,9 +25223,9 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
24813
25223
|
return EXIT_INIT_FAILED;
|
|
24814
25224
|
}
|
|
24815
25225
|
const authority = resolveInitAuthority(options);
|
|
24816
|
-
const mancodeDir =
|
|
24817
|
-
const stateFile =
|
|
24818
|
-
const v3SchemaFile =
|
|
25226
|
+
const mancodeDir = path48.join(rootDir, ".mancode");
|
|
25227
|
+
const stateFile = path48.join(mancodeDir, "state.json");
|
|
25228
|
+
const v3SchemaFile = path48.join(mancodeDir, "schema.json");
|
|
24819
25229
|
const wasInitialized = await pathExists6(stateFile);
|
|
24820
25230
|
let mutationSnapshots = [];
|
|
24821
25231
|
let directorySnapshots = [];
|
|
@@ -24883,7 +25293,7 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
24883
25293
|
}
|
|
24884
25294
|
return initializeV3(rootDir, options);
|
|
24885
25295
|
}
|
|
24886
|
-
const isGitRepo = await pathExists6(
|
|
25296
|
+
const isGitRepo = await pathExists6(path48.join(rootDir, ".git"));
|
|
24887
25297
|
const hasManifest = await hasProjectManifest(rootDir);
|
|
24888
25298
|
let isGenericProject = false;
|
|
24889
25299
|
if (!isGitRepo && !hasManifest) {
|
|
@@ -25001,8 +25411,8 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
25001
25411
|
const managedFiles = getInitManagedFilePaths(rootDir, selectedPlatforms);
|
|
25002
25412
|
mutationSnapshots = await snapshotFiles(managedFiles);
|
|
25003
25413
|
directorySnapshots = await snapshotDirectories(managedFiles, [
|
|
25004
|
-
|
|
25005
|
-
|
|
25414
|
+
path48.join(mancodeDir, "workflows"),
|
|
25415
|
+
path48.join(mancodeDir, "preseason-reports")
|
|
25006
25416
|
]);
|
|
25007
25417
|
const team = await detectTeamStatus(rootDir);
|
|
25008
25418
|
const platformMinimal = Object.fromEntries(
|
|
@@ -25063,7 +25473,7 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
25063
25473
|
`;
|
|
25064
25474
|
await fs4.writeFile(stateFile, stateContent, "utf-8");
|
|
25065
25475
|
await fs4.writeFile(
|
|
25066
|
-
|
|
25476
|
+
path48.join(mancodeDir, "project-profile.json"),
|
|
25067
25477
|
`${JSON.stringify(profile, null, 2)}
|
|
25068
25478
|
`,
|
|
25069
25479
|
"utf-8"
|
|
@@ -25100,7 +25510,7 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
25100
25510
|
)
|
|
25101
25511
|
);
|
|
25102
25512
|
const tokens = await scanAesthetics(rootDir, uiLibrary);
|
|
25103
|
-
const tokensPath =
|
|
25513
|
+
const tokensPath = path48.join(
|
|
25104
25514
|
mancodeDir,
|
|
25105
25515
|
"aesthetics",
|
|
25106
25516
|
"style-tokens.json"
|
|
@@ -25264,7 +25674,7 @@ async function initializeV3(rootDir, options) {
|
|
|
25264
25674
|
);
|
|
25265
25675
|
return EXIT_INIT_FAILED;
|
|
25266
25676
|
}
|
|
25267
|
-
const schemaPath =
|
|
25677
|
+
const schemaPath = path48.join(rootDir, ".mancode", "schema.json");
|
|
25268
25678
|
let existingV3 = false;
|
|
25269
25679
|
if (await pathExists6(schemaPath)) {
|
|
25270
25680
|
try {
|
|
@@ -25356,7 +25766,7 @@ function printV3InitError(error) {
|
|
|
25356
25766
|
}
|
|
25357
25767
|
}
|
|
25358
25768
|
async function updateConfigOptions(mancodeDir, patch, preserveInstalledPlatforms) {
|
|
25359
|
-
const configPath =
|
|
25769
|
+
const configPath = path48.join(mancodeDir, "config.json");
|
|
25360
25770
|
let config = {};
|
|
25361
25771
|
try {
|
|
25362
25772
|
config = JSON.parse(await fs4.readFile(configPath, "utf-8"));
|
|
@@ -25389,7 +25799,7 @@ async function updateConfigOptions(mancodeDir, patch, preserveInstalledPlatforms
|
|
|
25389
25799
|
async function readExistingInitPreferences(mancodeDir) {
|
|
25390
25800
|
try {
|
|
25391
25801
|
const config = JSON.parse(
|
|
25392
|
-
await fs4.readFile(
|
|
25802
|
+
await fs4.readFile(path48.join(mancodeDir, "config.json"), "utf-8")
|
|
25393
25803
|
);
|
|
25394
25804
|
const preferences = {
|
|
25395
25805
|
platforms: Array.isArray(config.platforms) ? config.platforms.filter(
|
|
@@ -25455,13 +25865,13 @@ async function selectInitPlatforms(input) {
|
|
|
25455
25865
|
}
|
|
25456
25866
|
async function hasProjectManifest(rootDir) {
|
|
25457
25867
|
for (const name of PROJECT_MANIFESTS) {
|
|
25458
|
-
if (await pathExists6(
|
|
25868
|
+
if (await pathExists6(path48.join(rootDir, name))) return true;
|
|
25459
25869
|
}
|
|
25460
25870
|
return false;
|
|
25461
25871
|
}
|
|
25462
25872
|
async function canInitializeGenericProject(rootDir) {
|
|
25463
|
-
const resolved =
|
|
25464
|
-
if (resolved ===
|
|
25873
|
+
const resolved = path48.resolve(rootDir);
|
|
25874
|
+
if (resolved === path48.parse(resolved).root || resolved === path48.resolve(os.homedir())) {
|
|
25465
25875
|
return { ok: false, reason: "unsafe" };
|
|
25466
25876
|
}
|
|
25467
25877
|
try {
|
|
@@ -25475,11 +25885,11 @@ async function canInitializeGenericProject(rootDir) {
|
|
|
25475
25885
|
}
|
|
25476
25886
|
}
|
|
25477
25887
|
async function validateV3CliProjectBoundary(rootDir, options, locale, legacyInitialized) {
|
|
25478
|
-
const isGitRepo = await pathExists6(
|
|
25888
|
+
const isGitRepo = await pathExists6(path48.join(rootDir, ".git"));
|
|
25479
25889
|
const hasManifest = await hasProjectManifest(rootDir);
|
|
25480
25890
|
if (isGitRepo || hasManifest) return null;
|
|
25481
25891
|
const v3Initialized = await pathExists6(
|
|
25482
|
-
|
|
25892
|
+
path48.join(rootDir, ".mancode", "schema.json")
|
|
25483
25893
|
);
|
|
25484
25894
|
const legacyAuthorityPresent = legacyInitialized || (await scanLegacyAuthority(rootDir)).authorityPresent;
|
|
25485
25895
|
const genericSafety = await canInitializeGenericProject(rootDir);
|
|
@@ -25608,7 +26018,7 @@ function getInitManagedFilePaths(rootDir, platforms) {
|
|
|
25608
26018
|
files.push(`.github/prompts/${mode}.prompt.md`);
|
|
25609
26019
|
}
|
|
25610
26020
|
}
|
|
25611
|
-
return [...new Set(files.map((file) =>
|
|
26021
|
+
return [...new Set(files.map((file) => path48.join(rootDir, file)))];
|
|
25612
26022
|
}
|
|
25613
26023
|
async function snapshotFiles(filePaths) {
|
|
25614
26024
|
return Promise.all(
|
|
@@ -25627,10 +26037,10 @@ async function snapshotFiles(filePaths) {
|
|
|
25627
26037
|
async function snapshotDirectories(filePaths, additionalDirectories = []) {
|
|
25628
26038
|
const directories = new Set(additionalDirectories);
|
|
25629
26039
|
for (const filePath of filePaths) {
|
|
25630
|
-
let current =
|
|
25631
|
-
while (current !==
|
|
26040
|
+
let current = path48.dirname(filePath);
|
|
26041
|
+
while (current !== path48.dirname(current)) {
|
|
25632
26042
|
directories.add(current);
|
|
25633
|
-
current =
|
|
26043
|
+
current = path48.dirname(current);
|
|
25634
26044
|
}
|
|
25635
26045
|
}
|
|
25636
26046
|
return Promise.all(
|
|
@@ -25646,7 +26056,7 @@ async function restoreFiles(snapshots) {
|
|
|
25646
26056
|
await fs4.rm(snapshot.filePath, { force: true });
|
|
25647
26057
|
continue;
|
|
25648
26058
|
}
|
|
25649
|
-
await fs4.mkdir(
|
|
26059
|
+
await fs4.mkdir(path48.dirname(snapshot.filePath), { recursive: true });
|
|
25650
26060
|
await fs4.writeFile(snapshot.filePath, snapshot.content, "utf-8");
|
|
25651
26061
|
}
|
|
25652
26062
|
}
|
|
@@ -25713,15 +26123,15 @@ async function pathExists6(p) {
|
|
|
25713
26123
|
|
|
25714
26124
|
// src/commands/install.ts
|
|
25715
26125
|
import { promises as fs5 } from "fs";
|
|
25716
|
-
import
|
|
26126
|
+
import path49 from "path";
|
|
25717
26127
|
import process6 from "process";
|
|
25718
26128
|
var EXIT_OK2 = 0;
|
|
25719
26129
|
var EXIT_NOT_INITIALIZED = 1;
|
|
25720
26130
|
var EXIT_UNSUPPORTED_PLATFORM = 2;
|
|
25721
26131
|
var EXIT_INSTALL_FAILED = 3;
|
|
25722
26132
|
async function install(rootDir = process6.cwd(), platform = "claude-code", options = {}) {
|
|
25723
|
-
const stateFile =
|
|
25724
|
-
const v3SchemaFile =
|
|
26133
|
+
const stateFile = path49.join(rootDir, ".mancode", "state.json");
|
|
26134
|
+
const v3SchemaFile = path49.join(rootDir, ".mancode", "schema.json");
|
|
25725
26135
|
if (await pathExists7(v3SchemaFile)) {
|
|
25726
26136
|
return installV3(rootDir, platform, options);
|
|
25727
26137
|
}
|
|
@@ -25864,7 +26274,7 @@ function printUnsupportedPlatform(platform) {
|
|
|
25864
26274
|
}
|
|
25865
26275
|
}
|
|
25866
26276
|
async function readConfig2(rootDir) {
|
|
25867
|
-
const configPath =
|
|
26277
|
+
const configPath = path49.join(rootDir, ".mancode", "config.json");
|
|
25868
26278
|
try {
|
|
25869
26279
|
const raw = await fs5.readFile(configPath, "utf-8");
|
|
25870
26280
|
return { config: JSON.parse(raw), valid: true };
|
|
@@ -25879,7 +26289,7 @@ function isNodeError7(err) {
|
|
|
25879
26289
|
return err instanceof Error && "code" in err;
|
|
25880
26290
|
}
|
|
25881
26291
|
async function updateConfig(rootDir, config) {
|
|
25882
|
-
const configPath =
|
|
26292
|
+
const configPath = path49.join(rootDir, ".mancode", "config.json");
|
|
25883
26293
|
const content = `${JSON.stringify(config, null, 2)}
|
|
25884
26294
|
`;
|
|
25885
26295
|
await fs5.writeFile(configPath, content, "utf-8");
|
|
@@ -25915,7 +26325,7 @@ function readConfiguredMinimal(value, platform) {
|
|
|
25915
26325
|
async function readStatePlatform(rootDir) {
|
|
25916
26326
|
try {
|
|
25917
26327
|
const raw = await fs5.readFile(
|
|
25918
|
-
|
|
26328
|
+
path49.join(rootDir, ".mancode", "state.json"),
|
|
25919
26329
|
"utf-8"
|
|
25920
26330
|
);
|
|
25921
26331
|
const state = JSON.parse(raw);
|
|
@@ -25938,11 +26348,11 @@ function isRecord8(value) {
|
|
|
25938
26348
|
|
|
25939
26349
|
// src/commands/list-platforms.ts
|
|
25940
26350
|
import { promises as fs6 } from "fs";
|
|
25941
|
-
import
|
|
26351
|
+
import path50 from "path";
|
|
25942
26352
|
import process7 from "process";
|
|
25943
26353
|
var EXIT_OK3 = 0;
|
|
25944
26354
|
async function listPlatforms(rootDir = process7.cwd()) {
|
|
25945
|
-
if (await pathExists8(
|
|
26355
|
+
if (await pathExists8(path50.join(rootDir, ".mancode", "schema.json"))) {
|
|
25946
26356
|
return listV3Platforms(rootDir);
|
|
25947
26357
|
}
|
|
25948
26358
|
const installed = new Set(await readInstalledPlatforms(rootDir));
|
|
@@ -25978,7 +26388,7 @@ async function listV3Platforms(rootDir) {
|
|
|
25978
26388
|
async function readInstalledPlatforms(rootDir) {
|
|
25979
26389
|
try {
|
|
25980
26390
|
const raw = await fs6.readFile(
|
|
25981
|
-
|
|
26391
|
+
path50.join(rootDir, ".mancode", "config.json"),
|
|
25982
26392
|
"utf-8"
|
|
25983
26393
|
);
|
|
25984
26394
|
const config = JSON.parse(raw);
|
|
@@ -26010,24 +26420,24 @@ function describePlatform(platform) {
|
|
|
26010
26420
|
}
|
|
26011
26421
|
|
|
26012
26422
|
// src/commands/manps.ts
|
|
26013
|
-
import { access as access4, readFile as
|
|
26014
|
-
import
|
|
26423
|
+
import { access as access4, readFile as readFile37 } from "fs/promises";
|
|
26424
|
+
import path52 from "path";
|
|
26015
26425
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
26016
26426
|
|
|
26017
26427
|
// src/system/preseason.ts
|
|
26018
|
-
import { execFile as
|
|
26428
|
+
import { execFile as execFile8 } from "child_process";
|
|
26019
26429
|
import { createHash as createHash8 } from "crypto";
|
|
26020
26430
|
import { existsSync, readFileSync } from "fs";
|
|
26021
26431
|
import {
|
|
26022
26432
|
access as access3,
|
|
26023
|
-
lstat as
|
|
26024
|
-
mkdir as
|
|
26025
|
-
readFile as
|
|
26026
|
-
readdir as
|
|
26433
|
+
lstat as lstat19,
|
|
26434
|
+
mkdir as mkdir33,
|
|
26435
|
+
readFile as readFile36,
|
|
26436
|
+
readdir as readdir17,
|
|
26027
26437
|
rename as rename9,
|
|
26028
|
-
writeFile as
|
|
26438
|
+
writeFile as writeFile38
|
|
26029
26439
|
} from "fs/promises";
|
|
26030
|
-
import
|
|
26440
|
+
import path51 from "path";
|
|
26031
26441
|
var PRESEASON_AREAS = [
|
|
26032
26442
|
"all",
|
|
26033
26443
|
"deps",
|
|
@@ -26107,10 +26517,10 @@ async function runPreseasonScan(projectRoot, area = "all", options = {}) {
|
|
|
26107
26517
|
const needsFiles = normalizedArea === "all" || normalizedArea === "dead-code" || normalizedArea === "config";
|
|
26108
26518
|
const files = needsFiles ? await listProjectFiles(projectRoot) : [];
|
|
26109
26519
|
const issues = (await scanArea(projectRoot, normalizedArea, pkg, files)).slice(0, 20);
|
|
26110
|
-
const storageRoot = options.storageRoot ??
|
|
26111
|
-
const reportDir =
|
|
26112
|
-
await
|
|
26113
|
-
const issueDbPath =
|
|
26520
|
+
const storageRoot = options.storageRoot ?? path51.join(projectRoot, ".mancode");
|
|
26521
|
+
const reportDir = path51.join(storageRoot, "preseason-reports");
|
|
26522
|
+
await mkdir33(reportDir, { recursive: true });
|
|
26523
|
+
const issueDbPath = path51.join(storageRoot, "preseason-issues.json");
|
|
26114
26524
|
const reportPath = await allocateReportPath(
|
|
26115
26525
|
reportDir,
|
|
26116
26526
|
`${generatedAt.replace(/[:.]/g, "-")}-${normalizedArea}`
|
|
@@ -26124,9 +26534,9 @@ async function runPreseasonScan(projectRoot, area = "all", options = {}) {
|
|
|
26124
26534
|
issueDbPath
|
|
26125
26535
|
};
|
|
26126
26536
|
const database = await buildIssueDatabase(projectRoot, report);
|
|
26127
|
-
await
|
|
26128
|
-
await
|
|
26129
|
-
|
|
26537
|
+
await writeFile38(reportPath, renderPreseasonReport(report), "utf-8");
|
|
26538
|
+
await writeFile38(
|
|
26539
|
+
path51.join(storageRoot, "preseason-report.md"),
|
|
26130
26540
|
renderPreseasonReport(report),
|
|
26131
26541
|
"utf-8"
|
|
26132
26542
|
);
|
|
@@ -26134,7 +26544,7 @@ async function runPreseasonScan(projectRoot, area = "all", options = {}) {
|
|
|
26134
26544
|
return report;
|
|
26135
26545
|
}
|
|
26136
26546
|
async function runPreseasonRemediation(projectRoot, issues, options = {}) {
|
|
26137
|
-
const issueDbPath = options.issueDbPath ??
|
|
26547
|
+
const issueDbPath = options.issueDbPath ?? path51.join(projectRoot, ".mancode", "preseason-issues.json");
|
|
26138
26548
|
const database = await readIssueDatabase(issueDbPath);
|
|
26139
26549
|
const keys = new Set(issues.map((issue) => issueKey(issue)));
|
|
26140
26550
|
const targets = database.issues.filter(
|
|
@@ -26212,7 +26622,7 @@ async function runPreseasonRemediation(projectRoot, issues, options = {}) {
|
|
|
26212
26622
|
write2(" Decision: skipped.");
|
|
26213
26623
|
}
|
|
26214
26624
|
database.updatedAt = now;
|
|
26215
|
-
await
|
|
26625
|
+
await writeFile38(
|
|
26216
26626
|
issueDbPath,
|
|
26217
26627
|
`${JSON.stringify(database, null, 2)}
|
|
26218
26628
|
`,
|
|
@@ -26244,7 +26654,7 @@ async function scanArea(projectRoot, area, pkg, files) {
|
|
|
26244
26654
|
async function allocateReportPath(reportDir, baseName) {
|
|
26245
26655
|
for (let attempt = 0; attempt < 1e3; attempt++) {
|
|
26246
26656
|
const suffix = attempt === 0 ? "" : `-${attempt + 1}`;
|
|
26247
|
-
const candidate =
|
|
26657
|
+
const candidate = path51.join(reportDir, `${baseName}${suffix}.md`);
|
|
26248
26658
|
if (!existsSync(candidate)) return candidate;
|
|
26249
26659
|
}
|
|
26250
26660
|
throw new Error(`unable to allocate preseason report path: ${baseName}`);
|
|
@@ -26287,24 +26697,24 @@ async function walk(root, current, results, depth) {
|
|
|
26287
26697
|
if (depth > MAX_SCAN_DEPTH || results.length >= MAX_PROJECT_FILES) return;
|
|
26288
26698
|
let entries;
|
|
26289
26699
|
try {
|
|
26290
|
-
entries = await
|
|
26700
|
+
entries = await readdir17(current);
|
|
26291
26701
|
} catch {
|
|
26292
26702
|
return;
|
|
26293
26703
|
}
|
|
26294
26704
|
for (const entry of entries) {
|
|
26295
26705
|
if (IGNORE_DIRS.has(entry)) continue;
|
|
26296
|
-
const abs =
|
|
26297
|
-
const rel =
|
|
26706
|
+
const abs = path51.join(current, entry);
|
|
26707
|
+
const rel = path51.relative(root, abs);
|
|
26298
26708
|
let info;
|
|
26299
26709
|
try {
|
|
26300
|
-
info = await
|
|
26710
|
+
info = await lstat19(abs);
|
|
26301
26711
|
} catch {
|
|
26302
26712
|
continue;
|
|
26303
26713
|
}
|
|
26304
26714
|
if (info.isSymbolicLink()) continue;
|
|
26305
26715
|
if (info.isDirectory()) {
|
|
26306
26716
|
await walk(root, abs, results, depth + 1);
|
|
26307
|
-
} else if (SOURCE_EXTENSIONS.has(
|
|
26717
|
+
} else if (SOURCE_EXTENSIONS.has(path51.extname(entry)) || entry === "package.json") {
|
|
26308
26718
|
results.push(rel);
|
|
26309
26719
|
if (results.length >= MAX_PROJECT_FILES) return;
|
|
26310
26720
|
}
|
|
@@ -26312,7 +26722,7 @@ async function walk(root, current, results, depth) {
|
|
|
26312
26722
|
}
|
|
26313
26723
|
async function readPackageJson(projectRoot) {
|
|
26314
26724
|
try {
|
|
26315
|
-
const raw = await
|
|
26725
|
+
const raw = await readFile36(path51.join(projectRoot, "package.json"), "utf-8");
|
|
26316
26726
|
return JSON.parse(raw);
|
|
26317
26727
|
} catch {
|
|
26318
26728
|
return null;
|
|
@@ -26405,7 +26815,7 @@ function scanTodos(projectRoot, files) {
|
|
|
26405
26815
|
const matches = [];
|
|
26406
26816
|
for (const file of files) {
|
|
26407
26817
|
if (matches.length >= 7) break;
|
|
26408
|
-
const abs =
|
|
26818
|
+
const abs = path51.join(projectRoot, file);
|
|
26409
26819
|
matches.push(...readTodoIssues(abs, file, matches.length));
|
|
26410
26820
|
}
|
|
26411
26821
|
return matches.slice(0, 7);
|
|
@@ -26446,7 +26856,7 @@ function scanTestGaps(files) {
|
|
|
26446
26856
|
if (sourceFiles.length === 0) return [];
|
|
26447
26857
|
const tests = new Set(files.filter((file) => file.startsWith("tests/")));
|
|
26448
26858
|
const missing = sourceFiles.filter((file) => {
|
|
26449
|
-
const base =
|
|
26859
|
+
const base = path51.basename(file).replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
26450
26860
|
return !Array.from(tests).some((test) => test.includes(base));
|
|
26451
26861
|
}).slice(0, 4);
|
|
26452
26862
|
return missing.map((file, index) => ({
|
|
@@ -26455,13 +26865,13 @@ function scanTestGaps(files) {
|
|
|
26455
26865
|
type: "tests",
|
|
26456
26866
|
title: "Core source file has no obvious test",
|
|
26457
26867
|
file,
|
|
26458
|
-
detail: `No matching test file was found for ${
|
|
26868
|
+
detail: `No matching test file was found for ${path51.basename(file)}.`,
|
|
26459
26869
|
recommendation: "Add focused coverage for the public behavior or document why this module is exercised indirectly."
|
|
26460
26870
|
}));
|
|
26461
26871
|
}
|
|
26462
26872
|
function scanConfig(projectRoot, files) {
|
|
26463
26873
|
const issues = [];
|
|
26464
|
-
if (!files.includes(".gitignore") && !pathExistsSync(
|
|
26874
|
+
if (!files.includes(".gitignore") && !pathExistsSync(path51.join(projectRoot, ".gitignore"))) {
|
|
26465
26875
|
issues.push({
|
|
26466
26876
|
id: "config-gitignore",
|
|
26467
26877
|
severity: "P1",
|
|
@@ -26472,7 +26882,7 @@ function scanConfig(projectRoot, files) {
|
|
|
26472
26882
|
recommendation: "Add a .gitignore that excludes dependencies, build output, coverage, and local env files."
|
|
26473
26883
|
});
|
|
26474
26884
|
}
|
|
26475
|
-
if (!files.includes(".editorconfig") && !pathExistsSync(
|
|
26885
|
+
if (!files.includes(".editorconfig") && !pathExistsSync(path51.join(projectRoot, ".editorconfig"))) {
|
|
26476
26886
|
issues.push({
|
|
26477
26887
|
id: "config-editorconfig",
|
|
26478
26888
|
severity: "P2",
|
|
@@ -26491,7 +26901,7 @@ function scanAestheticDrift(projectRoot, files) {
|
|
|
26491
26901
|
for (const file of frontendFiles) {
|
|
26492
26902
|
let content;
|
|
26493
26903
|
try {
|
|
26494
|
-
content = readFileSyncSafe(
|
|
26904
|
+
content = readFileSyncSafe(path51.join(projectRoot, file));
|
|
26495
26905
|
} catch {
|
|
26496
26906
|
continue;
|
|
26497
26907
|
}
|
|
@@ -26511,7 +26921,7 @@ function scanAestheticDrift(projectRoot, files) {
|
|
|
26511
26921
|
return issues;
|
|
26512
26922
|
}
|
|
26513
26923
|
async function scanArchitecture(projectRoot) {
|
|
26514
|
-
const localBinary =
|
|
26924
|
+
const localBinary = path51.join(
|
|
26515
26925
|
projectRoot,
|
|
26516
26926
|
"node_modules",
|
|
26517
26927
|
".bin",
|
|
@@ -26559,7 +26969,7 @@ async function hasDependencyCruiserConfig(projectRoot) {
|
|
|
26559
26969
|
"dependency-cruiser.config.mjs"
|
|
26560
26970
|
];
|
|
26561
26971
|
const results = await Promise.all(
|
|
26562
|
-
files.map((file) => pathExists9(
|
|
26972
|
+
files.map((file) => pathExists9(path51.join(projectRoot, file)))
|
|
26563
26973
|
);
|
|
26564
26974
|
return results.some(Boolean);
|
|
26565
26975
|
}
|
|
@@ -26576,7 +26986,7 @@ function architectureScannerUnavailableIssue() {
|
|
|
26576
26986
|
function runDepcruise(binary, projectRoot) {
|
|
26577
26987
|
return new Promise((resolve) => {
|
|
26578
26988
|
const needsShell = process.platform === "win32";
|
|
26579
|
-
|
|
26989
|
+
execFile8(
|
|
26580
26990
|
binary,
|
|
26581
26991
|
["--output-type", "json", "."],
|
|
26582
26992
|
{
|
|
@@ -26665,9 +27075,9 @@ function inferCommands(pkg) {
|
|
|
26665
27075
|
return ["lint", "test", "build"].filter((name) => scripts[name]).map((name) => `npm run ${name}`);
|
|
26666
27076
|
}
|
|
26667
27077
|
async function buildIssueDatabase(projectRoot, report) {
|
|
26668
|
-
const reportRef =
|
|
27078
|
+
const reportRef = path51.relative(projectRoot, report.reportPath);
|
|
26669
27079
|
const run = {
|
|
26670
|
-
id:
|
|
27080
|
+
id: path51.basename(report.reportPath, ".md"),
|
|
26671
27081
|
generatedAt: report.generatedAt,
|
|
26672
27082
|
area: report.area,
|
|
26673
27083
|
reportPath: reportRef,
|
|
@@ -26709,7 +27119,7 @@ async function buildIssueDatabase(projectRoot, report) {
|
|
|
26709
27119
|
async function readIssueDatabase(issueDbPath) {
|
|
26710
27120
|
let raw;
|
|
26711
27121
|
try {
|
|
26712
|
-
raw = await
|
|
27122
|
+
raw = await readFile36(issueDbPath, "utf-8");
|
|
26713
27123
|
} catch (err) {
|
|
26714
27124
|
if (isNodeError8(err) && err.code === "ENOENT") {
|
|
26715
27125
|
return emptyIssueDatabase();
|
|
@@ -26730,7 +27140,7 @@ async function readIssueDatabase(issueDbPath) {
|
|
|
26730
27140
|
}
|
|
26731
27141
|
async function writeJsonAtomic3(file, value) {
|
|
26732
27142
|
const tmp = `${file}.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
26733
|
-
await
|
|
27143
|
+
await writeFile38(tmp, `${JSON.stringify(value, null, 2)}
|
|
26734
27144
|
`, "utf-8");
|
|
26735
27145
|
await rename9(tmp, file);
|
|
26736
27146
|
}
|
|
@@ -26773,20 +27183,20 @@ function compareIssueRecords(a, b) {
|
|
|
26773
27183
|
}
|
|
26774
27184
|
async function applySafeRemediation(projectRoot, issue) {
|
|
26775
27185
|
if (issue.id === "config-gitignore" && issue.file === ".gitignore") {
|
|
26776
|
-
const gitignorePath =
|
|
27186
|
+
const gitignorePath = path51.join(projectRoot, ".gitignore");
|
|
26777
27187
|
if (pathExistsSync(gitignorePath)) {
|
|
26778
27188
|
return { applied: false };
|
|
26779
27189
|
}
|
|
26780
|
-
await
|
|
27190
|
+
await writeFile38(gitignorePath, `${DEFAULT_GITIGNORE}
|
|
26781
27191
|
`, "utf-8");
|
|
26782
27192
|
return { applied: true, action: "created .gitignore" };
|
|
26783
27193
|
}
|
|
26784
27194
|
if (issue.id === "config-editorconfig" && issue.file === ".editorconfig") {
|
|
26785
|
-
const editorconfigPath =
|
|
27195
|
+
const editorconfigPath = path51.join(projectRoot, ".editorconfig");
|
|
26786
27196
|
if (pathExistsSync(editorconfigPath)) {
|
|
26787
27197
|
return { applied: false };
|
|
26788
27198
|
}
|
|
26789
|
-
await
|
|
27199
|
+
await writeFile38(editorconfigPath, `${DEFAULT_EDITORCONFIG}
|
|
26790
27200
|
`, "utf-8");
|
|
26791
27201
|
return { applied: true, action: "created .editorconfig" };
|
|
26792
27202
|
}
|
|
@@ -26822,10 +27232,10 @@ async function inferSafePackageScript(projectRoot, scriptName) {
|
|
|
26822
27232
|
}
|
|
26823
27233
|
}
|
|
26824
27234
|
async function addPackageScript(projectRoot, scriptName, script) {
|
|
26825
|
-
const packagePath =
|
|
27235
|
+
const packagePath = path51.join(projectRoot, "package.json");
|
|
26826
27236
|
let pkg;
|
|
26827
27237
|
try {
|
|
26828
|
-
pkg = JSON.parse(await
|
|
27238
|
+
pkg = JSON.parse(await readFile36(packagePath, "utf-8"));
|
|
26829
27239
|
} catch {
|
|
26830
27240
|
return false;
|
|
26831
27241
|
}
|
|
@@ -26835,7 +27245,7 @@ async function addPackageScript(projectRoot, scriptName, script) {
|
|
|
26835
27245
|
...scripts,
|
|
26836
27246
|
[scriptName]: script
|
|
26837
27247
|
};
|
|
26838
|
-
await
|
|
27248
|
+
await writeFile38(packagePath, `${JSON.stringify(pkg, null, 2)}
|
|
26839
27249
|
`, "utf-8");
|
|
26840
27250
|
return true;
|
|
26841
27251
|
}
|
|
@@ -26935,7 +27345,7 @@ var EXIT_NOT_INITIALIZED2 = 1;
|
|
|
26935
27345
|
var EXIT_SCAN_FAILED = 2;
|
|
26936
27346
|
var EXIT_INVALID_ARG = 3;
|
|
26937
27347
|
async function manps(rootDir, area = "all", options = {}) {
|
|
26938
|
-
const v3SchemaPath =
|
|
27348
|
+
const v3SchemaPath = path52.join(rootDir, ".mancode", "schema.json");
|
|
26939
27349
|
const v3Activation = await readV3ActivationState(v3SchemaPath);
|
|
26940
27350
|
if (v3Activation !== null && v3Activation !== "v3_active" && v3Activation !== "dual_read") {
|
|
26941
27351
|
const message = `manps is unavailable while mancode activation is ${v3Activation}`;
|
|
@@ -26948,7 +27358,7 @@ async function manps(rootDir, area = "all", options = {}) {
|
|
|
26948
27358
|
return EXIT_SCAN_FAILED;
|
|
26949
27359
|
}
|
|
26950
27360
|
const v3Initialized = v3Activation === "v3_active";
|
|
26951
|
-
const initialized = v3Initialized || await pathExists10(
|
|
27361
|
+
const initialized = v3Initialized || await pathExists10(path52.join(rootDir, ".mancode", "state.json"));
|
|
26952
27362
|
if (!initialized) {
|
|
26953
27363
|
if (options.json) {
|
|
26954
27364
|
console.log(JSON.stringify({ error: "not initialized" }, null, 2));
|
|
@@ -26961,7 +27371,7 @@ async function manps(rootDir, area = "all", options = {}) {
|
|
|
26961
27371
|
let report;
|
|
26962
27372
|
try {
|
|
26963
27373
|
report = await runPreseasonScan(rootDir, area, {
|
|
26964
|
-
storageRoot: v3Initialized ?
|
|
27374
|
+
storageRoot: v3Initialized ? path52.join(rootDir, ".mancode", "local") : void 0
|
|
26965
27375
|
});
|
|
26966
27376
|
} catch (err) {
|
|
26967
27377
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -27030,8 +27440,8 @@ async function manps(rootDir, area = "all", options = {}) {
|
|
|
27030
27440
|
console.log(
|
|
27031
27441
|
`Issues: ${report.issues.length} total (P0 ${p0}, P1 ${p1}, P2 ${p2})`
|
|
27032
27442
|
);
|
|
27033
|
-
console.log(`Report: ${
|
|
27034
|
-
console.log(`Issue DB: ${
|
|
27443
|
+
console.log(`Report: ${path52.relative(rootDir, report.reportPath)}`);
|
|
27444
|
+
console.log(`Issue DB: ${path52.relative(rootDir, report.issueDbPath)}`);
|
|
27035
27445
|
if (report.issues.length > 0) {
|
|
27036
27446
|
console.log("");
|
|
27037
27447
|
for (const issue of report.issues.slice(0, 7)) {
|
|
@@ -27047,7 +27457,7 @@ async function manps(rootDir, area = "all", options = {}) {
|
|
|
27047
27457
|
console.log(` Skipped: ${remediation.skipped}`);
|
|
27048
27458
|
console.log(` Fixed: ${remediation.fixed}`);
|
|
27049
27459
|
console.log(
|
|
27050
|
-
` Issue DB: ${
|
|
27460
|
+
` Issue DB: ${path52.relative(rootDir, remediation.issueDbPath)}`
|
|
27051
27461
|
);
|
|
27052
27462
|
}
|
|
27053
27463
|
return EXIT_OK4;
|
|
@@ -27108,7 +27518,7 @@ async function readV3ActivationState(schemaPath) {
|
|
|
27108
27518
|
if (!await pathExists10(schemaPath)) return null;
|
|
27109
27519
|
try {
|
|
27110
27520
|
const manifest = parseSchemaManifest(
|
|
27111
|
-
JSON.parse(await
|
|
27521
|
+
JSON.parse(await readFile37(schemaPath, "utf8"))
|
|
27112
27522
|
);
|
|
27113
27523
|
return manifest.activationState;
|
|
27114
27524
|
} catch {
|
|
@@ -27117,8 +27527,8 @@ async function readV3ActivationState(schemaPath) {
|
|
|
27117
27527
|
}
|
|
27118
27528
|
|
|
27119
27529
|
// src/commands/migrate.ts
|
|
27120
|
-
import { readFile as
|
|
27121
|
-
import
|
|
27530
|
+
import { readFile as readFile38 } from "fs/promises";
|
|
27531
|
+
import path53 from "path";
|
|
27122
27532
|
var EXIT_OK5 = 0;
|
|
27123
27533
|
var EXIT_INVALID_ARG2 = 2;
|
|
27124
27534
|
var EXIT_MIGRATION_BLOCKED = 3;
|
|
@@ -27244,14 +27654,14 @@ async function readScopeFile(rootDir, file) {
|
|
|
27244
27654
|
if (!file.trim() || file.includes("\0")) {
|
|
27245
27655
|
throw new Error("MANCODE_MIGRATION_SCOPE_FILE_INVALID");
|
|
27246
27656
|
}
|
|
27247
|
-
const resolved =
|
|
27248
|
-
const relative =
|
|
27249
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
27657
|
+
const resolved = path53.resolve(rootDir, file);
|
|
27658
|
+
const relative = path53.relative(path53.resolve(rootDir), resolved);
|
|
27659
|
+
if (relative === ".." || relative.startsWith(`..${path53.sep}`) || path53.isAbsolute(relative)) {
|
|
27250
27660
|
throw new Error("MANCODE_MIGRATION_SCOPE_FILE_INVALID");
|
|
27251
27661
|
}
|
|
27252
27662
|
try {
|
|
27253
27663
|
return JSON.parse(
|
|
27254
|
-
await
|
|
27664
|
+
await readFile38(resolved, "utf8")
|
|
27255
27665
|
);
|
|
27256
27666
|
} catch (error) {
|
|
27257
27667
|
if (error instanceof SyntaxError) {
|
|
@@ -27353,16 +27763,16 @@ async function runOperationMutation(rootDir, operationId, options, mode) {
|
|
|
27353
27763
|
// src/commands/refresh-project.ts
|
|
27354
27764
|
import { randomUUID } from "crypto";
|
|
27355
27765
|
import { promises as fs7 } from "fs";
|
|
27356
|
-
import
|
|
27766
|
+
import path54 from "path";
|
|
27357
27767
|
import process8 from "process";
|
|
27358
27768
|
var EXIT_OK6 = 0;
|
|
27359
27769
|
var EXIT_NOT_INITIALIZED3 = 1;
|
|
27360
27770
|
var EXIT_CORRUPT_STATE = 2;
|
|
27361
27771
|
var EXIT_REFRESH_FAILED = 3;
|
|
27362
27772
|
async function refreshProject(rootDir = process8.cwd()) {
|
|
27363
|
-
const mancodeDir =
|
|
27364
|
-
const statePath =
|
|
27365
|
-
if (await pathExists11(
|
|
27773
|
+
const mancodeDir = path54.join(rootDir, ".mancode");
|
|
27774
|
+
const statePath = path54.join(mancodeDir, "state.json");
|
|
27775
|
+
if (await pathExists11(path54.join(mancodeDir, "schema.json"))) {
|
|
27366
27776
|
return refreshV3Project(rootDir);
|
|
27367
27777
|
}
|
|
27368
27778
|
if (!await pathExists11(statePath)) {
|
|
@@ -27381,12 +27791,12 @@ async function refreshProject(rootDir = process8.cwd()) {
|
|
|
27381
27791
|
const [profile, team, hasGit, hasManifest] = await Promise.all([
|
|
27382
27792
|
detectProjectProfile(rootDir),
|
|
27383
27793
|
detectTeamStatus(rootDir),
|
|
27384
|
-
pathExists11(
|
|
27794
|
+
pathExists11(path54.join(rootDir, ".git")),
|
|
27385
27795
|
hasProjectManifest2(rootDir)
|
|
27386
27796
|
]);
|
|
27387
27797
|
const uiLibrary = primaryUiLibrary(profile);
|
|
27388
27798
|
const stack = [...profile.languages, ...profile.frameworks];
|
|
27389
|
-
const config = await readJson2(
|
|
27799
|
+
const config = await readJson2(path54.join(mancodeDir, "config.json"));
|
|
27390
27800
|
const configuredTeam = config.forceTeamMode === true ? true : config.teamMode === "on" ? true : config.teamMode === "off" ? false : team.isTeam;
|
|
27391
27801
|
const nextState = {
|
|
27392
27802
|
...state,
|
|
@@ -27398,7 +27808,7 @@ async function refreshProject(rootDir = process8.cwd()) {
|
|
|
27398
27808
|
};
|
|
27399
27809
|
await writeProjectFacts2(
|
|
27400
27810
|
statePath,
|
|
27401
|
-
|
|
27811
|
+
path54.join(mancodeDir, "project-profile.json"),
|
|
27402
27812
|
`${JSON.stringify(nextState, null, 2)}
|
|
27403
27813
|
`,
|
|
27404
27814
|
`${JSON.stringify(profile, null, 2)}
|
|
@@ -27465,7 +27875,7 @@ async function refreshV3Project(rootDir) {
|
|
|
27465
27875
|
}
|
|
27466
27876
|
async function hasProjectManifest2(rootDir) {
|
|
27467
27877
|
for (const manifest of PROJECT_MANIFESTS) {
|
|
27468
|
-
if (await pathExists11(
|
|
27878
|
+
if (await pathExists11(path54.join(rootDir, manifest))) return true;
|
|
27469
27879
|
}
|
|
27470
27880
|
return false;
|
|
27471
27881
|
}
|
|
@@ -27531,9 +27941,9 @@ async function readOptionalText(filePath) {
|
|
|
27531
27941
|
}
|
|
27532
27942
|
}
|
|
27533
27943
|
function temporaryPath(filePath) {
|
|
27534
|
-
return
|
|
27535
|
-
|
|
27536
|
-
`.${
|
|
27944
|
+
return path54.join(
|
|
27945
|
+
path54.dirname(filePath),
|
|
27946
|
+
`.${path54.basename(filePath)}.${process8.pid}.${randomUUID()}.tmp`
|
|
27537
27947
|
);
|
|
27538
27948
|
}
|
|
27539
27949
|
async function refreshStaticPlatforms(rootDir, config, fallbackPlatform, stack, uiLibrary, profile) {
|
|
@@ -27603,14 +28013,14 @@ async function pathExists11(filePath) {
|
|
|
27603
28013
|
|
|
27604
28014
|
// src/commands/refresh-style.ts
|
|
27605
28015
|
import { promises as fs8 } from "fs";
|
|
27606
|
-
import
|
|
28016
|
+
import path55 from "path";
|
|
27607
28017
|
import process9 from "process";
|
|
27608
28018
|
var EXIT_OK7 = 0;
|
|
27609
28019
|
var EXIT_NOT_INITIALIZED4 = 1;
|
|
27610
28020
|
var EXIT_V3_REFRESH_FAILED = 2;
|
|
27611
28021
|
async function refreshStyle(rootDir = process9.cwd()) {
|
|
27612
|
-
const stateFile =
|
|
27613
|
-
if (await pathExists12(
|
|
28022
|
+
const stateFile = path55.join(rootDir, ".mancode", "state.json");
|
|
28023
|
+
if (await pathExists12(path55.join(rootDir, ".mancode", "schema.json"))) {
|
|
27614
28024
|
return refreshV3Style(rootDir);
|
|
27615
28025
|
}
|
|
27616
28026
|
if (!await pathExists12(stateFile)) {
|
|
@@ -27620,7 +28030,7 @@ async function refreshStyle(rootDir = process9.cwd()) {
|
|
|
27620
28030
|
}
|
|
27621
28031
|
console.log("\u2713 \u5237\u65B0\u9879\u76EE profile...");
|
|
27622
28032
|
const profile = await detectProjectProfile(rootDir);
|
|
27623
|
-
const profilePath =
|
|
28033
|
+
const profilePath = path55.join(rootDir, ".mancode", "project-profile.json");
|
|
27624
28034
|
await fs8.writeFile(
|
|
27625
28035
|
profilePath,
|
|
27626
28036
|
`${JSON.stringify(profile, null, 2)}
|
|
@@ -27642,13 +28052,13 @@ async function refreshStyle(rootDir = process9.cwd()) {
|
|
|
27642
28052
|
}
|
|
27643
28053
|
console.log("\u2713 \u626B\u63CF\u9879\u76EE\u8BBE\u8BA1 token...");
|
|
27644
28054
|
const tokens = await scanAesthetics(rootDir, uiLibraryHint);
|
|
27645
|
-
const tokensPath =
|
|
28055
|
+
const tokensPath = path55.join(
|
|
27646
28056
|
rootDir,
|
|
27647
28057
|
".mancode",
|
|
27648
28058
|
"aesthetics",
|
|
27649
28059
|
"style-tokens.json"
|
|
27650
28060
|
);
|
|
27651
|
-
await fs8.mkdir(
|
|
28061
|
+
await fs8.mkdir(path55.dirname(tokensPath), { recursive: true });
|
|
27652
28062
|
await fs8.writeFile(
|
|
27653
28063
|
tokensPath,
|
|
27654
28064
|
`${JSON.stringify(tokens, null, 2)}
|
|
@@ -27720,7 +28130,7 @@ async function refreshV3Style(rootDir) {
|
|
|
27720
28130
|
console.log(
|
|
27721
28131
|
` \u7C7B\u578B: ${profile.projectKind} | UI: ${profile.uiAssets} | \u6D4F\u89C8\u5668: ${profile.browserAutomation}`
|
|
27722
28132
|
);
|
|
27723
|
-
const tokensPath =
|
|
28133
|
+
const tokensPath = path55.join(
|
|
27724
28134
|
rootDir,
|
|
27725
28135
|
".mancode",
|
|
27726
28136
|
"local",
|
|
@@ -27737,7 +28147,7 @@ async function refreshV3Style(rootDir) {
|
|
|
27737
28147
|
}
|
|
27738
28148
|
console.log("\u2713 \u626B\u63CF\u9879\u76EE\u8BBE\u8BA1 token...");
|
|
27739
28149
|
const tokens = await scanAesthetics(rootDir, uiLibraryHint);
|
|
27740
|
-
await fs8.mkdir(
|
|
28150
|
+
await fs8.mkdir(path55.dirname(tokensPath), { recursive: true });
|
|
27741
28151
|
await fs8.writeFile(
|
|
27742
28152
|
tokensPath,
|
|
27743
28153
|
`${JSON.stringify(tokens, null, 2)}
|
|
@@ -27771,7 +28181,7 @@ async function printStaticPlatformRefreshHint(rootDir) {
|
|
|
27771
28181
|
);
|
|
27772
28182
|
}
|
|
27773
28183
|
async function refreshLegacyStateContext(rootDir, profile, uiLibrary) {
|
|
27774
|
-
const statePath =
|
|
28184
|
+
const statePath = path55.join(rootDir, ".mancode", "state.json");
|
|
27775
28185
|
try {
|
|
27776
28186
|
const state = JSON.parse(await fs8.readFile(statePath, "utf-8"));
|
|
27777
28187
|
const stack = [...profile.languages, ...profile.frameworks];
|
|
@@ -27795,7 +28205,7 @@ async function refreshLegacyStateContext(rootDir, profile, uiLibrary) {
|
|
|
27795
28205
|
async function readInstalledPlatforms2(rootDir) {
|
|
27796
28206
|
try {
|
|
27797
28207
|
const raw = await fs8.readFile(
|
|
27798
|
-
|
|
28208
|
+
path55.join(rootDir, ".mancode", "config.json"),
|
|
27799
28209
|
"utf-8"
|
|
27800
28210
|
);
|
|
27801
28211
|
const config = JSON.parse(raw);
|
|
@@ -27818,7 +28228,7 @@ async function pathExists12(p) {
|
|
|
27818
28228
|
// src/commands/status.ts
|
|
27819
28229
|
import { spawn } from "child_process";
|
|
27820
28230
|
import { promises as fs9 } from "fs";
|
|
27821
|
-
import
|
|
28231
|
+
import path56 from "path";
|
|
27822
28232
|
import process10 from "process";
|
|
27823
28233
|
|
|
27824
28234
|
// src/team/assessment.ts
|
|
@@ -27974,8 +28384,8 @@ var EXIT_OK8 = 0;
|
|
|
27974
28384
|
var EXIT_NOT_INITIALIZED5 = 1;
|
|
27975
28385
|
var EXIT_CORRUPT_STATE2 = 2;
|
|
27976
28386
|
async function status(rootDir = process10.cwd(), options = {}) {
|
|
27977
|
-
const stateFile =
|
|
27978
|
-
const v3SchemaFile =
|
|
28387
|
+
const stateFile = path56.join(rootDir, ".mancode", "state.json");
|
|
28388
|
+
const v3SchemaFile = path56.join(rootDir, ".mancode", "schema.json");
|
|
27979
28389
|
if (await pathExists13(v3SchemaFile)) {
|
|
27980
28390
|
return statusV3(rootDir, options);
|
|
27981
28391
|
}
|
|
@@ -28207,10 +28617,10 @@ async function readV3StatusSession(rootDir) {
|
|
|
28207
28617
|
}
|
|
28208
28618
|
async function shouldRefreshProject(rootDir, state) {
|
|
28209
28619
|
if (state.projectMode !== "generic") return false;
|
|
28210
|
-
const hasGit = await pathExists13(
|
|
28620
|
+
const hasGit = await pathExists13(path56.join(rootDir, ".git"));
|
|
28211
28621
|
if (hasGit) return true;
|
|
28212
28622
|
for (const manifest of PROJECT_MANIFESTS) {
|
|
28213
|
-
if (await pathExists13(
|
|
28623
|
+
if (await pathExists13(path56.join(rootDir, manifest))) return true;
|
|
28214
28624
|
}
|
|
28215
28625
|
return false;
|
|
28216
28626
|
}
|
|
@@ -28254,19 +28664,19 @@ async function getCurrentWorkflow(rootDir, taskId) {
|
|
|
28254
28664
|
}
|
|
28255
28665
|
async function getProjectName(rootDir) {
|
|
28256
28666
|
try {
|
|
28257
|
-
const raw = await fs9.readFile(
|
|
28667
|
+
const raw = await fs9.readFile(path56.join(rootDir, "package.json"), "utf-8");
|
|
28258
28668
|
const pkg = JSON.parse(raw);
|
|
28259
28669
|
if (pkg.name && typeof pkg.name === "string") {
|
|
28260
28670
|
return pkg.name;
|
|
28261
28671
|
}
|
|
28262
28672
|
} catch {
|
|
28263
28673
|
}
|
|
28264
|
-
return
|
|
28674
|
+
return path56.basename(rootDir);
|
|
28265
28675
|
}
|
|
28266
28676
|
async function readConfig3(rootDir) {
|
|
28267
28677
|
try {
|
|
28268
28678
|
const raw = await fs9.readFile(
|
|
28269
|
-
|
|
28679
|
+
path56.join(rootDir, ".mancode", "config.json"),
|
|
28270
28680
|
"utf-8"
|
|
28271
28681
|
);
|
|
28272
28682
|
return JSON.parse(raw);
|
|
@@ -28294,9 +28704,9 @@ function getEffectiveTeamStatus(state, config, detected) {
|
|
|
28294
28704
|
}
|
|
28295
28705
|
async function checkHooks(rootDir) {
|
|
28296
28706
|
const [sessionStart, userPromptSubmit, registered] = await Promise.all([
|
|
28297
|
-
pathExists13(
|
|
28707
|
+
pathExists13(path56.join(rootDir, ".mancode", "hooks", "session-start.mjs")),
|
|
28298
28708
|
pathExists13(
|
|
28299
|
-
|
|
28709
|
+
path56.join(rootDir, ".mancode", "hooks", "user-prompt-submit.mjs")
|
|
28300
28710
|
),
|
|
28301
28711
|
isRegistered(rootDir)
|
|
28302
28712
|
]);
|
|
@@ -28305,7 +28715,7 @@ async function checkHooks(rootDir) {
|
|
|
28305
28715
|
async function isRegistered(rootDir) {
|
|
28306
28716
|
try {
|
|
28307
28717
|
const raw = await fs9.readFile(
|
|
28308
|
-
|
|
28718
|
+
path56.join(rootDir, ".claude", "settings.json"),
|
|
28309
28719
|
"utf-8"
|
|
28310
28720
|
);
|
|
28311
28721
|
const settings = JSON.parse(raw);
|
|
@@ -28334,7 +28744,7 @@ function hasHookCommand2(value, needle) {
|
|
|
28334
28744
|
});
|
|
28335
28745
|
}
|
|
28336
28746
|
async function estimateHookInjection(rootDir) {
|
|
28337
|
-
const hookPath =
|
|
28747
|
+
const hookPath = path56.join(
|
|
28338
28748
|
rootDir,
|
|
28339
28749
|
".mancode",
|
|
28340
28750
|
"hooks",
|
|
@@ -29825,162 +30235,24 @@ function assertPositiveRevision2(value, label) {
|
|
|
29825
30235
|
}
|
|
29826
30236
|
}
|
|
29827
30237
|
|
|
29828
|
-
// src/team/git-ref-bundle.ts
|
|
29829
|
-
import { execFile as execFileCallback4 } from "child_process";
|
|
29830
|
-
import { lstat as lstat18, mkdir as mkdir32, writeFile as writeFile37 } from "fs/promises";
|
|
29831
|
-
import path55 from "path";
|
|
29832
|
-
import { promisify as promisify6 } from "util";
|
|
29833
|
-
var execFile7 = promisify6(execFileCallback4);
|
|
29834
|
-
function createGitRefTaskBundle(input) {
|
|
29835
|
-
const { task } = input;
|
|
29836
|
-
if (task.metadata.taskRef.namespace !== "shared") {
|
|
29837
|
-
throw new Error("MANCODE_REMOTE_COORDINATION_REQUIRES_SHARED_TASK");
|
|
29838
|
-
}
|
|
29839
|
-
if (task.aggregate === null) {
|
|
29840
|
-
throw new Error("MANCODE_TASK_UNAVAILABLE");
|
|
29841
|
-
}
|
|
29842
|
-
const artifacts = [
|
|
29843
|
-
artifact("metadata", "metadata.json", task.metadata),
|
|
29844
|
-
artifact("requirements", "requirements.json", task.requirements),
|
|
29845
|
-
artifact("review", "review-ledger.json", task.review),
|
|
29846
|
-
artifact("verification", "verification-ledger.json", task.verification)
|
|
29847
|
-
];
|
|
29848
|
-
if (task.latestCheckpoint !== null) {
|
|
29849
|
-
artifacts.push(
|
|
29850
|
-
artifact(
|
|
29851
|
-
"checkpoint",
|
|
29852
|
-
`checkpoints/${task.latestCheckpoint.checkpointId}.json`,
|
|
29853
|
-
task.latestCheckpoint
|
|
29854
|
-
)
|
|
29855
|
-
);
|
|
29856
|
-
}
|
|
29857
|
-
if (task.plan !== null) {
|
|
29858
|
-
artifacts.push(artifact("plan", "plan.md", task.plan.content));
|
|
29859
|
-
} else {
|
|
29860
|
-
artifacts.push(
|
|
29861
|
-
artifact(
|
|
29862
|
-
"summary",
|
|
29863
|
-
"summary.md",
|
|
29864
|
-
task.latestCheckpoint?.summary ?? `Task ${formatTaskRef(task.metadata.taskRef)} revision ${task.metadata.revision}.`
|
|
29865
|
-
)
|
|
29866
|
-
);
|
|
29867
|
-
}
|
|
29868
|
-
artifacts.sort(
|
|
29869
|
-
(left, right) => left.kind < right.kind ? -1 : left.kind > right.kind ? 1 : 0
|
|
29870
|
-
);
|
|
29871
|
-
const body = {
|
|
29872
|
-
schemaVersion: 1,
|
|
29873
|
-
taskRef: task.metadata.taskRef,
|
|
29874
|
-
taskRevision: task.metadata.revision,
|
|
29875
|
-
ownershipEpoch: task.metadata.ownershipEpoch,
|
|
29876
|
-
aggregate: task.aggregate,
|
|
29877
|
-
aggregateDigest: digestCanonicalJson(task.aggregate),
|
|
29878
|
-
codeRef: parseCodeRef(input.codeRef),
|
|
29879
|
-
artifacts,
|
|
29880
|
-
createdAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString()
|
|
29881
|
-
};
|
|
29882
|
-
return parseGitRefTaskBundle({
|
|
29883
|
-
...body,
|
|
29884
|
-
bundleDigest: gitRefTaskBundleDigest(body)
|
|
29885
|
-
});
|
|
29886
|
-
}
|
|
29887
|
-
async function assertGitRefBundleCodeReachable(projectRoot, bundle) {
|
|
29888
|
-
const parsed = parseGitRefTaskBundle(bundle);
|
|
29889
|
-
try {
|
|
29890
|
-
await execFile7(
|
|
29891
|
-
"git",
|
|
29892
|
-
["cat-file", "-e", `${parsed.codeRef.head}^{commit}`],
|
|
29893
|
-
{
|
|
29894
|
-
cwd: path55.resolve(projectRoot),
|
|
29895
|
-
windowsHide: true
|
|
29896
|
-
}
|
|
29897
|
-
);
|
|
29898
|
-
} catch {
|
|
29899
|
-
throw new Error("MANCODE_TASK_BUNDLE_CODE_UNREACHABLE");
|
|
29900
|
-
}
|
|
29901
|
-
}
|
|
29902
|
-
async function quarantineGitRefTaskBundle(projectRoot, remoteRevision, bundle) {
|
|
29903
|
-
if (!Number.isSafeInteger(remoteRevision) || remoteRevision < 1) {
|
|
29904
|
-
throw new Error("MANCODE_TRANSPORT_REVISION_INVALID");
|
|
29905
|
-
}
|
|
29906
|
-
const parsed = parseGitRefTaskBundle(bundle);
|
|
29907
|
-
const directory = path55.join(
|
|
29908
|
-
path55.resolve(projectRoot),
|
|
29909
|
-
".mancode",
|
|
29910
|
-
"local",
|
|
29911
|
-
"quarantine",
|
|
29912
|
-
"git-ref",
|
|
29913
|
-
parsed.taskRef.taskId,
|
|
29914
|
-
String(remoteRevision)
|
|
29915
|
-
);
|
|
29916
|
-
await ensureFixedDirectory(projectRoot, [
|
|
29917
|
-
".mancode",
|
|
29918
|
-
"local",
|
|
29919
|
-
"quarantine",
|
|
29920
|
-
"git-ref",
|
|
29921
|
-
parsed.taskRef.taskId,
|
|
29922
|
-
String(remoteRevision)
|
|
29923
|
-
]);
|
|
29924
|
-
const target = path55.join(directory, `${parsed.bundleDigest.slice(7)}.json`);
|
|
29925
|
-
try {
|
|
29926
|
-
await writeFile37(target, `${JSON.stringify(parsed, null, 2)}
|
|
29927
|
-
`, {
|
|
29928
|
-
encoding: "utf8",
|
|
29929
|
-
flag: "wx"
|
|
29930
|
-
});
|
|
29931
|
-
} catch (error) {
|
|
29932
|
-
if (!isAlreadyExists21(error)) throw error;
|
|
29933
|
-
}
|
|
29934
|
-
return target;
|
|
29935
|
-
}
|
|
29936
|
-
function artifact(kind, relativePath, value) {
|
|
29937
|
-
const content = JSON.parse(JSON.stringify(value));
|
|
29938
|
-
return {
|
|
29939
|
-
kind,
|
|
29940
|
-
relativePath,
|
|
29941
|
-
content,
|
|
29942
|
-
contentDigest: digestCanonicalJson(content)
|
|
29943
|
-
};
|
|
29944
|
-
}
|
|
29945
|
-
function parseCodeRef(value) {
|
|
29946
|
-
if (typeof value.branch !== "string" || !value.branch.trim() || value.branch.includes("\0") || typeof value.head !== "string" || !/^[0-9a-f]{40,64}$/.test(value.head)) {
|
|
29947
|
-
throw new Error("MANCODE_TASK_BUNDLE_CODE_REF_INVALID");
|
|
29948
|
-
}
|
|
29949
|
-
return { branch: value.branch, head: value.head };
|
|
29950
|
-
}
|
|
29951
|
-
async function ensureFixedDirectory(projectRoot, segments) {
|
|
29952
|
-
let current = path55.resolve(projectRoot);
|
|
29953
|
-
for (const segment of segments) {
|
|
29954
|
-
current = path55.join(current, segment);
|
|
29955
|
-
try {
|
|
29956
|
-
await mkdir32(current);
|
|
29957
|
-
} catch (error) {
|
|
29958
|
-
if (!isAlreadyExists21(error)) throw error;
|
|
29959
|
-
}
|
|
29960
|
-
const entry = await lstat18(current);
|
|
29961
|
-
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
29962
|
-
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
29963
|
-
}
|
|
29964
|
-
}
|
|
29965
|
-
}
|
|
29966
|
-
function isAlreadyExists21(error) {
|
|
29967
|
-
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
29968
|
-
}
|
|
29969
|
-
|
|
29970
30238
|
// src/team/git-ref-handoff-repair.ts
|
|
29971
|
-
import { lstat as
|
|
29972
|
-
import
|
|
30239
|
+
import { lstat as lstat20, mkdir as mkdir34, readFile as readFile39, readdir as readdir18, writeFile as writeFile39 } from "fs/promises";
|
|
30240
|
+
import path57 from "path";
|
|
29973
30241
|
|
|
29974
30242
|
// src/team/git-ref-operation.ts
|
|
29975
|
-
import { execFile as
|
|
29976
|
-
import { promisify as
|
|
30243
|
+
import { execFile as execFileCallback6 } from "child_process";
|
|
30244
|
+
import { promisify as promisify8 } from "util";
|
|
29977
30245
|
|
|
29978
30246
|
// src/team/git-ref-coordination.ts
|
|
29979
30247
|
function prepareGitRefCoordinationMutation(manifest, input) {
|
|
29980
30248
|
const context = openMutationContext(manifest, input);
|
|
29981
30249
|
switch (input.kind) {
|
|
29982
30250
|
case "ownership_fence":
|
|
29983
|
-
return prepareOwnershipFence(
|
|
30251
|
+
return prepareOwnershipFence(
|
|
30252
|
+
context,
|
|
30253
|
+
input.taskBundle,
|
|
30254
|
+
input.expectedPredecessorBundleDigest
|
|
30255
|
+
);
|
|
29984
30256
|
case "claim_acquire":
|
|
29985
30257
|
return prepareClaimAcquire(
|
|
29986
30258
|
context,
|
|
@@ -30099,13 +30371,16 @@ function openMutationContext(manifest, input) {
|
|
|
30099
30371
|
metadata
|
|
30100
30372
|
};
|
|
30101
30373
|
}
|
|
30102
|
-
function prepareOwnershipFence(context, taskBundle) {
|
|
30374
|
+
function prepareOwnershipFence(context, taskBundle, expectedPredecessorBundleDigest) {
|
|
30103
30375
|
const metadata = metadataFromBundle2(taskBundle);
|
|
30104
30376
|
assertRemoteTaskEligible(metadata);
|
|
30105
30377
|
assertTaskBundleIdentity(taskBundle, context.taskRef);
|
|
30106
30378
|
if (metadata.ownerActorId === null) {
|
|
30107
30379
|
throw new Error("MANCODE_TASK_OWNER_REQUIRED");
|
|
30108
30380
|
}
|
|
30381
|
+
if ((context.taskBundle?.bundleDigest ?? null) !== expectedPredecessorBundleDigest) {
|
|
30382
|
+
throw new Error("MANCODE_TASK_BUNDLE_DIVERGED");
|
|
30383
|
+
}
|
|
30109
30384
|
if (context.fence === null) {
|
|
30110
30385
|
if (metadata.ownerActorId !== context.input.actorId || metadata.ownershipEpoch !== 0 || taskBundle.ownershipEpoch !== 0) {
|
|
30111
30386
|
throw new Error("MANCODE_TASK_OWNER_REQUIRED");
|
|
@@ -30119,14 +30394,45 @@ function prepareOwnershipFence(context, taskBundle) {
|
|
|
30119
30394
|
throw new Error("MANCODE_TASK_REVISION_CONFLICT");
|
|
30120
30395
|
}
|
|
30121
30396
|
if (taskBundle.taskRevision === context.fence.taskRevision) {
|
|
30122
|
-
if (taskBundle.aggregateDigest !== context.fence.aggregateDigest
|
|
30397
|
+
if (taskBundle.aggregateDigest !== context.fence.aggregateDigest) {
|
|
30123
30398
|
throw new Error("MANCODE_SPLIT_BRAIN");
|
|
30124
30399
|
}
|
|
30125
|
-
|
|
30400
|
+
if (taskBundle.codeRef.branch !== context.taskBundle?.codeRef.branch || taskBundle.codeRef.head === context.taskBundle?.codeRef.head) {
|
|
30401
|
+
throw new Error("MANCODE_REMOTE_FENCE_NO_CHANGE");
|
|
30402
|
+
}
|
|
30403
|
+
return prepared(
|
|
30404
|
+
context,
|
|
30405
|
+
buildFence(context, taskBundle, metadata.ownerActorId),
|
|
30406
|
+
refreshOwnerClaimsForCodeRef(context, taskBundle, metadata),
|
|
30407
|
+
context.handoffs,
|
|
30408
|
+
taskBundle
|
|
30409
|
+
);
|
|
30126
30410
|
}
|
|
30127
30411
|
}
|
|
30412
|
+
const codeHeadChanged = context.taskBundle !== null && (taskBundle.codeRef.branch !== context.taskBundle.codeRef.branch || taskBundle.codeRef.head !== context.taskBundle.codeRef.head);
|
|
30128
30413
|
const fence = buildFence(context, taskBundle, metadata.ownerActorId);
|
|
30129
|
-
return prepared(
|
|
30414
|
+
return prepared(
|
|
30415
|
+
context,
|
|
30416
|
+
fence,
|
|
30417
|
+
codeHeadChanged ? refreshOwnerClaimsForCodeRef(context, taskBundle, metadata) : context.claims,
|
|
30418
|
+
context.handoffs,
|
|
30419
|
+
taskBundle
|
|
30420
|
+
);
|
|
30421
|
+
}
|
|
30422
|
+
function refreshOwnerClaimsForCodeRef(context, taskBundle, metadata) {
|
|
30423
|
+
return context.claims.map((claim) => {
|
|
30424
|
+
if (claim.state !== "active" || claim.ownerActorId !== context.input.actorId || Date.parse(claim.expiresAt) <= context.now.getTime() || claim.ownershipEpochAtAcquire !== taskBundle.ownershipEpoch || claim.implementationScopeDigest !== metadata.implementationScope.digest) {
|
|
30425
|
+
return claim;
|
|
30426
|
+
}
|
|
30427
|
+
const next = bindClaim(context, {
|
|
30428
|
+
...claim,
|
|
30429
|
+
revision: claim.revision + 1,
|
|
30430
|
+
lastValidatedTaskRevision: taskBundle.taskRevision,
|
|
30431
|
+
lastValidatedCodeRef: taskBundle.codeRef
|
|
30432
|
+
});
|
|
30433
|
+
assertClaimTransition(claim, next);
|
|
30434
|
+
return next;
|
|
30435
|
+
});
|
|
30130
30436
|
}
|
|
30131
30437
|
function prepareClaimAcquire(context, proposal, confirmScopeWarning) {
|
|
30132
30438
|
const { fence, taskBundle, metadata } = requireTaskContext(context);
|
|
@@ -30512,6 +30818,7 @@ function prepared(context, ownershipFence, claims, handoffs, taskBundle) {
|
|
|
30512
30818
|
claims: claims.map(parseClaim).sort(compareClaims2),
|
|
30513
30819
|
handoffs: handoffs.map(parseHandoff).sort(compareHandoffs2),
|
|
30514
30820
|
taskBundle,
|
|
30821
|
+
expectedTaskBundleDigest: context.taskBundle?.bundleDigest ?? null,
|
|
30515
30822
|
forwardRepair: null
|
|
30516
30823
|
};
|
|
30517
30824
|
}
|
|
@@ -31664,7 +31971,7 @@ function handoffSuccessorClaimId(operationId, predecessorClaimId, createdAt) {
|
|
|
31664
31971
|
}
|
|
31665
31972
|
|
|
31666
31973
|
// src/team/git-ref-operation.ts
|
|
31667
|
-
var
|
|
31974
|
+
var execFile9 = promisify8(execFileCallback6);
|
|
31668
31975
|
async function syncGitRefTask(input) {
|
|
31669
31976
|
const taskRef = requireSharedTask(input.taskRef);
|
|
31670
31977
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
@@ -31686,6 +31993,10 @@ async function syncGitRefTask(input) {
|
|
|
31686
31993
|
);
|
|
31687
31994
|
const snapshot = await transport.pull();
|
|
31688
31995
|
const bundle = await bundleFromContext(context, now);
|
|
31996
|
+
const remoteBase = await readGitRefTaskRemoteBase(
|
|
31997
|
+
context.projectRoot,
|
|
31998
|
+
taskRef
|
|
31999
|
+
);
|
|
31689
32000
|
const remoteTaskPublished = snapshot.manifest?.ownershipFences.some(
|
|
31690
32001
|
(fence) => sameTaskRef(fence.taskRef, taskRef)
|
|
31691
32002
|
) === true && snapshot.manifest.taskBundles.some(
|
|
@@ -31701,6 +32012,7 @@ async function syncGitRefTask(input) {
|
|
|
31701
32012
|
transport,
|
|
31702
32013
|
snapshot,
|
|
31703
32014
|
bundle,
|
|
32015
|
+
remoteBase?.bundle ?? null,
|
|
31704
32016
|
operationId,
|
|
31705
32017
|
now
|
|
31706
32018
|
);
|
|
@@ -31710,6 +32022,12 @@ async function syncGitRefTask(input) {
|
|
|
31710
32022
|
context.project.config,
|
|
31711
32023
|
refreshed
|
|
31712
32024
|
);
|
|
32025
|
+
const refreshedManifest = requireRemoteManifest(refreshed);
|
|
32026
|
+
await recordGitRefTaskRemoteBase(
|
|
32027
|
+
context.projectRoot,
|
|
32028
|
+
refreshedManifest.revision,
|
|
32029
|
+
requireRemoteBundle(refreshedManifest, taskRef)
|
|
32030
|
+
);
|
|
31713
32031
|
return { bundle, ...result2 };
|
|
31714
32032
|
} finally {
|
|
31715
32033
|
await context.release();
|
|
@@ -31741,6 +32059,10 @@ async function acquireGitRefClaim(input) {
|
|
|
31741
32059
|
);
|
|
31742
32060
|
let snapshot = await transport.pull();
|
|
31743
32061
|
const bundle = await bundleFromContext(context, now);
|
|
32062
|
+
const remoteBase = await readGitRefTaskRemoteBase(
|
|
32063
|
+
context.projectRoot,
|
|
32064
|
+
taskRef
|
|
32065
|
+
);
|
|
31744
32066
|
if (!remoteBundleMatches(snapshot, bundle)) {
|
|
31745
32067
|
await assertCleanGitWorktree(context.projectRoot);
|
|
31746
32068
|
const bootstrapOperationId = createUlid(now.getTime());
|
|
@@ -31749,6 +32071,7 @@ async function acquireGitRefClaim(input) {
|
|
|
31749
32071
|
transport,
|
|
31750
32072
|
snapshot,
|
|
31751
32073
|
bundle,
|
|
32074
|
+
remoteBase?.bundle ?? null,
|
|
31752
32075
|
bootstrapOperationId,
|
|
31753
32076
|
now
|
|
31754
32077
|
);
|
|
@@ -31756,6 +32079,11 @@ async function acquireGitRefClaim(input) {
|
|
|
31756
32079
|
}
|
|
31757
32080
|
const manifest = requireRemoteManifest(snapshot);
|
|
31758
32081
|
const fence = requireRemoteFence(manifest, taskRef);
|
|
32082
|
+
await recordGitRefTaskRemoteBase(
|
|
32083
|
+
context.projectRoot,
|
|
32084
|
+
manifest.revision,
|
|
32085
|
+
requireRemoteBundle(manifest, taskRef)
|
|
32086
|
+
);
|
|
31759
32087
|
const remote = context.project.config.transport.remote;
|
|
31760
32088
|
if (remote === null) throw new Error("MANCODE_TRANSPORT_UNAVAILABLE");
|
|
31761
32089
|
const remoteIdentityHash = await resolveGitRefRemoteIdentityHash(
|
|
@@ -31792,6 +32120,11 @@ async function acquireGitRefClaim(input) {
|
|
|
31792
32120
|
context.project.config,
|
|
31793
32121
|
refreshed
|
|
31794
32122
|
);
|
|
32123
|
+
await recordGitRefTaskRemoteBase(
|
|
32124
|
+
context.projectRoot,
|
|
32125
|
+
requireRemoteManifest(refreshed).revision,
|
|
32126
|
+
requireRemoteBundle(requireRemoteManifest(refreshed), taskRef)
|
|
32127
|
+
);
|
|
31795
32128
|
const claim = requireRemoteManifest(refreshed).claims.find(
|
|
31796
32129
|
(candidate) => candidate.claimId === claimId
|
|
31797
32130
|
);
|
|
@@ -32245,7 +32578,7 @@ async function assertCleanGitWorktree(projectRoot, materializedTaskRef) {
|
|
|
32245
32578
|
`:(exclude,top).mancode/shared/workflows/${materializedTaskRef.taskId}/**`
|
|
32246
32579
|
);
|
|
32247
32580
|
}
|
|
32248
|
-
const { stdout: stdout2 } = await
|
|
32581
|
+
const { stdout: stdout2 } = await execFile9("git", args, {
|
|
32249
32582
|
cwd: projectRoot,
|
|
32250
32583
|
windowsHide: true
|
|
32251
32584
|
});
|
|
@@ -32274,7 +32607,7 @@ function freezeDeep(value) {
|
|
|
32274
32607
|
for (const child of Object.values(value)) freezeDeep(child);
|
|
32275
32608
|
return Object.freeze(value);
|
|
32276
32609
|
}
|
|
32277
|
-
async function synchronizeBundle(context, transport, snapshot, bundle, operationId, now) {
|
|
32610
|
+
async function synchronizeBundle(context, transport, snapshot, bundle, remoteBase, operationId, now) {
|
|
32278
32611
|
const manifest = requireRemoteManifest(snapshot);
|
|
32279
32612
|
const fence = manifest.ownershipFences.find(
|
|
32280
32613
|
(candidate) => sameTaskRef(candidate.taskRef, context.taskRef)
|
|
@@ -32287,6 +32620,16 @@ async function synchronizeBundle(context, transport, snapshot, bundle, operation
|
|
|
32287
32620
|
changed: false
|
|
32288
32621
|
};
|
|
32289
32622
|
}
|
|
32623
|
+
if (fence !== void 0 && fence.ownerActorId !== context.session.actorId) {
|
|
32624
|
+
throw new Error("MANCODE_TASK_OWNER_REQUIRED");
|
|
32625
|
+
}
|
|
32626
|
+
const remoteBundle = fence === void 0 ? null : requireRemoteBundle(manifest, context.taskRef);
|
|
32627
|
+
if (remoteBundle === null !== (remoteBase === null) || remoteBundle !== null && (remoteBase === null || remoteBundle.bundleDigest !== remoteBase.bundleDigest)) {
|
|
32628
|
+
throw new Error("MANCODE_TASK_BUNDLE_DIVERGED");
|
|
32629
|
+
}
|
|
32630
|
+
if (remoteBundle !== null) {
|
|
32631
|
+
await assertCodeRefFastForward(context.projectRoot, remoteBundle, bundle);
|
|
32632
|
+
}
|
|
32290
32633
|
const mutation = prepareGitRefCoordinationMutation(manifest, {
|
|
32291
32634
|
kind: "ownership_fence",
|
|
32292
32635
|
operationId,
|
|
@@ -32294,6 +32637,7 @@ async function synchronizeBundle(context, transport, snapshot, bundle, operation
|
|
|
32294
32637
|
taskRef: context.taskRef,
|
|
32295
32638
|
expectedRemoteRevision: manifest.revision,
|
|
32296
32639
|
expectedOwnershipEpoch: fence?.ownershipEpoch ?? 0,
|
|
32640
|
+
expectedPredecessorBundleDigest: remoteBundle?.bundleDigest ?? null,
|
|
32297
32641
|
taskBundle: bundle,
|
|
32298
32642
|
now
|
|
32299
32643
|
});
|
|
@@ -32352,6 +32696,21 @@ function remoteBundleMatches(snapshot, bundle) {
|
|
|
32352
32696
|
);
|
|
32353
32697
|
return remote !== void 0 && remote.aggregateDigest === bundle.aggregateDigest && remote.taskRevision === bundle.taskRevision && remote.ownershipEpoch === bundle.ownershipEpoch && remote.codeRef.branch === bundle.codeRef.branch && remote.codeRef.head === bundle.codeRef.head;
|
|
32354
32698
|
}
|
|
32699
|
+
async function assertCodeRefFastForward(projectRoot, previous, next) {
|
|
32700
|
+
if (previous.codeRef.branch !== next.codeRef.branch) {
|
|
32701
|
+
throw new Error("MANCODE_TASK_BUNDLE_DIVERGED");
|
|
32702
|
+
}
|
|
32703
|
+
if (previous.codeRef.head === next.codeRef.head) return;
|
|
32704
|
+
try {
|
|
32705
|
+
await execFile9(
|
|
32706
|
+
"git",
|
|
32707
|
+
["merge-base", "--is-ancestor", previous.codeRef.head, next.codeRef.head],
|
|
32708
|
+
{ cwd: projectRoot, windowsHide: true }
|
|
32709
|
+
);
|
|
32710
|
+
} catch {
|
|
32711
|
+
throw new Error("MANCODE_TASK_BUNDLE_DIVERGED");
|
|
32712
|
+
}
|
|
32713
|
+
}
|
|
32355
32714
|
function requireRemoteManifest(snapshot) {
|
|
32356
32715
|
if (snapshot.manifest === null) {
|
|
32357
32716
|
throw new Error("MANCODE_TRANSPORT_ACTOR_NOT_JOINED");
|
|
@@ -32441,7 +32800,7 @@ async function recoverGitRefHandoffRepairs(projectRoot) {
|
|
|
32441
32800
|
}
|
|
32442
32801
|
async function recoverGitRefHandoffRepair(projectRoot, operationId, transportReceipt) {
|
|
32443
32802
|
assertUlid(operationId, "git-ref handoff repair operationId");
|
|
32444
|
-
const root =
|
|
32803
|
+
const root = path57.resolve(projectRoot);
|
|
32445
32804
|
let journal = await requireJournal2(root, operationId);
|
|
32446
32805
|
if (journal.state === "committed" || journal.state === "aborted") {
|
|
32447
32806
|
return recoveryResult2(journal);
|
|
@@ -32519,7 +32878,7 @@ async function recoverGitRefHandoffRepair(projectRoot, operationId, transportRec
|
|
|
32519
32878
|
}
|
|
32520
32879
|
}
|
|
32521
32880
|
async function prepareHandoffRepairWhileTaskLocked(projectRoot, rawPrepared) {
|
|
32522
|
-
const root =
|
|
32881
|
+
const root = path57.resolve(projectRoot);
|
|
32523
32882
|
const prepared2 = parsePrepared2(rawPrepared);
|
|
32524
32883
|
const runtime = await readProjectRuntimeContext(root);
|
|
32525
32884
|
const previousMetadata = bundleMetadata2(prepared2.predecessorBundle);
|
|
@@ -32582,7 +32941,7 @@ async function restorePredecessorMetadata2(projectRoot, journal) {
|
|
|
32582
32941
|
);
|
|
32583
32942
|
}
|
|
32584
32943
|
async function replaceMetadataVerified(projectRoot, expected, targetMetadata, alternateExpected) {
|
|
32585
|
-
const target =
|
|
32944
|
+
const target = path57.join(
|
|
32586
32945
|
taskRootPath(projectRoot, targetMetadata.taskRef),
|
|
32587
32946
|
"metadata.json"
|
|
32588
32947
|
);
|
|
@@ -32708,12 +33067,12 @@ async function createJournal3(projectRoot, journal) {
|
|
|
32708
33067
|
await ensureJournalDirectory2(projectRoot);
|
|
32709
33068
|
const target = journalPath3(projectRoot, journal.operationId);
|
|
32710
33069
|
try {
|
|
32711
|
-
await
|
|
33070
|
+
await writeFile39(target, serialize13(journal), {
|
|
32712
33071
|
encoding: "utf8",
|
|
32713
33072
|
flag: "wx"
|
|
32714
33073
|
});
|
|
32715
33074
|
} catch (error) {
|
|
32716
|
-
if (!
|
|
33075
|
+
if (!isAlreadyExists23(error)) throw error;
|
|
32717
33076
|
const existing = await requireJournal2(projectRoot, journal.operationId);
|
|
32718
33077
|
if (digestCanonicalJson(existing) !== digestCanonicalJson(journal)) {
|
|
32719
33078
|
throw new Error("MANCODE_HANDOFF_REPAIR_JOURNAL_CONFLICT");
|
|
@@ -32727,10 +33086,10 @@ async function replaceJournal3(projectRoot, journal) {
|
|
|
32727
33086
|
async function requireJournal2(projectRoot, operationId) {
|
|
32728
33087
|
try {
|
|
32729
33088
|
return parseJournal3(
|
|
32730
|
-
JSON.parse(await
|
|
33089
|
+
JSON.parse(await readFile39(journalPath3(projectRoot, operationId), "utf8"))
|
|
32731
33090
|
);
|
|
32732
33091
|
} catch (error) {
|
|
32733
|
-
if (error instanceof SyntaxError ||
|
|
33092
|
+
if (error instanceof SyntaxError || isNotFound27(error)) {
|
|
32734
33093
|
throw new Error("MANCODE_HANDOFF_REPAIR_JOURNAL_NOT_FOUND");
|
|
32735
33094
|
}
|
|
32736
33095
|
throw error;
|
|
@@ -32739,9 +33098,9 @@ async function requireJournal2(projectRoot, operationId) {
|
|
|
32739
33098
|
async function listJournals2(projectRoot) {
|
|
32740
33099
|
let entries;
|
|
32741
33100
|
try {
|
|
32742
|
-
entries = await
|
|
33101
|
+
entries = await readdir18(journalDirectory2(projectRoot));
|
|
32743
33102
|
} catch (error) {
|
|
32744
|
-
if (
|
|
33103
|
+
if (isNotFound27(error)) return [];
|
|
32745
33104
|
throw error;
|
|
32746
33105
|
}
|
|
32747
33106
|
const journals = [];
|
|
@@ -32750,8 +33109,8 @@ async function listJournals2(projectRoot) {
|
|
|
32750
33109
|
journals.push(
|
|
32751
33110
|
parseJournal3(
|
|
32752
33111
|
JSON.parse(
|
|
32753
|
-
await
|
|
32754
|
-
|
|
33112
|
+
await readFile39(
|
|
33113
|
+
path57.join(journalDirectory2(projectRoot), entry),
|
|
32755
33114
|
"utf8"
|
|
32756
33115
|
)
|
|
32757
33116
|
)
|
|
@@ -32761,43 +33120,43 @@ async function listJournals2(projectRoot) {
|
|
|
32761
33120
|
return journals;
|
|
32762
33121
|
}
|
|
32763
33122
|
async function readSafeFile2(target) {
|
|
32764
|
-
const before = await
|
|
33123
|
+
const before = await lstat20(target);
|
|
32765
33124
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
32766
33125
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
32767
33126
|
}
|
|
32768
|
-
const content = await
|
|
32769
|
-
const after = await
|
|
33127
|
+
const content = await readFile39(target, "utf8");
|
|
33128
|
+
const after = await lstat20(target);
|
|
32770
33129
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
32771
33130
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
32772
33131
|
}
|
|
32773
33132
|
return content;
|
|
32774
33133
|
}
|
|
32775
33134
|
async function atomicWrite2(target, content) {
|
|
32776
|
-
const temporary =
|
|
32777
|
-
|
|
32778
|
-
`.${
|
|
33135
|
+
const temporary = path57.join(
|
|
33136
|
+
path57.dirname(target),
|
|
33137
|
+
`.${path57.basename(target)}.${process.pid}.${Date.now()}.tmp`
|
|
32779
33138
|
);
|
|
32780
|
-
await
|
|
33139
|
+
await writeFile39(temporary, content, { encoding: "utf8", flag: "wx" });
|
|
32781
33140
|
await replaceFileAtomically(temporary, target);
|
|
32782
33141
|
}
|
|
32783
33142
|
async function ensureJournalDirectory2(projectRoot) {
|
|
32784
|
-
let current =
|
|
33143
|
+
let current = path57.resolve(projectRoot);
|
|
32785
33144
|
for (const segment of [".mancode", "local", "journals", "git-ref-handoff"]) {
|
|
32786
|
-
current =
|
|
33145
|
+
current = path57.join(current, segment);
|
|
32787
33146
|
try {
|
|
32788
|
-
await
|
|
33147
|
+
await mkdir34(current);
|
|
32789
33148
|
} catch (error) {
|
|
32790
|
-
if (!
|
|
33149
|
+
if (!isAlreadyExists23(error)) throw error;
|
|
32791
33150
|
}
|
|
32792
|
-
const entry = await
|
|
33151
|
+
const entry = await lstat20(current);
|
|
32793
33152
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
32794
33153
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
32795
33154
|
}
|
|
32796
33155
|
}
|
|
32797
33156
|
}
|
|
32798
33157
|
function journalDirectory2(projectRoot) {
|
|
32799
|
-
return
|
|
32800
|
-
|
|
33158
|
+
return path57.join(
|
|
33159
|
+
path57.resolve(projectRoot),
|
|
32801
33160
|
".mancode",
|
|
32802
33161
|
"local",
|
|
32803
33162
|
"journals",
|
|
@@ -32806,7 +33165,7 @@ function journalDirectory2(projectRoot) {
|
|
|
32806
33165
|
}
|
|
32807
33166
|
function journalPath3(projectRoot, operationId) {
|
|
32808
33167
|
assertUlid(operationId, "git-ref handoff repair operationId");
|
|
32809
|
-
return
|
|
33168
|
+
return path57.join(journalDirectory2(projectRoot), `${operationId}.json`);
|
|
32810
33169
|
}
|
|
32811
33170
|
function serialize13(value) {
|
|
32812
33171
|
return `${JSON.stringify(value, null, 2)}
|
|
@@ -32818,10 +33177,10 @@ function parseTimestamp14(value) {
|
|
|
32818
33177
|
}
|
|
32819
33178
|
return value;
|
|
32820
33179
|
}
|
|
32821
|
-
function
|
|
33180
|
+
function isAlreadyExists23(error) {
|
|
32822
33181
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
32823
33182
|
}
|
|
32824
|
-
function
|
|
33183
|
+
function isNotFound27(error) {
|
|
32825
33184
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
32826
33185
|
}
|
|
32827
33186
|
|
|
@@ -32905,8 +33264,8 @@ function parseReceipt(value) {
|
|
|
32905
33264
|
}
|
|
32906
33265
|
|
|
32907
33266
|
// src/team/policy-operation.ts
|
|
32908
|
-
import { lstat as
|
|
32909
|
-
import
|
|
33267
|
+
import { lstat as lstat21, mkdir as mkdir35, readdir as readdir19, unlink as unlink3, writeFile as writeFile40 } from "fs/promises";
|
|
33268
|
+
import path58 from "path";
|
|
32910
33269
|
async function updateTeamPolicy(input) {
|
|
32911
33270
|
const operationId = input.operationId ?? createUlid();
|
|
32912
33271
|
const eventId = createUlid();
|
|
@@ -32917,7 +33276,7 @@ async function updateTeamPolicy(input) {
|
|
|
32917
33276
|
throw new Error("MANCODE_TEAM_POLICY_INVALID");
|
|
32918
33277
|
}
|
|
32919
33278
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
32920
|
-
const root =
|
|
33279
|
+
const root = path58.resolve(input.projectRoot);
|
|
32921
33280
|
const runtime = await readProjectRuntimeContext(root);
|
|
32922
33281
|
const store = resolveCoordinationEntityHomeStore(
|
|
32923
33282
|
runtime.entityHomeStoreContext
|
|
@@ -32998,7 +33357,7 @@ async function applyTeamTransportSet(input, write2) {
|
|
|
32998
33357
|
}
|
|
32999
33358
|
const remote = transportRemote(input.mode, input.remote);
|
|
33000
33359
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
33001
|
-
const root =
|
|
33360
|
+
const root = path58.resolve(input.projectRoot);
|
|
33002
33361
|
const runtime = await readProjectRuntimeContext(root);
|
|
33003
33362
|
const store = resolveCoordinationEntityHomeStore(
|
|
33004
33363
|
runtime.entityHomeStoreContext
|
|
@@ -33131,9 +33490,9 @@ async function assertTransportAuthorityEmpty(projectRoot, store) {
|
|
|
33131
33490
|
listClaims(store),
|
|
33132
33491
|
listHandoffs(store),
|
|
33133
33492
|
directoryHasEntries(taskHeadDirectory(store)),
|
|
33134
|
-
directoryHasEntries(
|
|
33493
|
+
directoryHasEntries(path58.join(store.root, "transport-migrations")),
|
|
33135
33494
|
directoryHasEntries(
|
|
33136
|
-
|
|
33495
|
+
path58.join(projectRoot, ".mancode", "shared", "team", "transport")
|
|
33137
33496
|
),
|
|
33138
33497
|
pathExists14(gitRefCachePath(projectRoot))
|
|
33139
33498
|
]);
|
|
@@ -33163,21 +33522,21 @@ function assertPositiveRevision5(value, label) {
|
|
|
33163
33522
|
}
|
|
33164
33523
|
}
|
|
33165
33524
|
function teamPolicyPath(projectRoot) {
|
|
33166
|
-
return
|
|
33525
|
+
return path58.join(projectRoot, ".mancode", "shared", "team", "policy.json");
|
|
33167
33526
|
}
|
|
33168
33527
|
function projectConfigPath(projectRoot) {
|
|
33169
|
-
return
|
|
33528
|
+
return path58.join(projectRoot, ".mancode", "shared", "config.json");
|
|
33170
33529
|
}
|
|
33171
33530
|
async function writeJsonAtomic4(target, value) {
|
|
33172
|
-
await
|
|
33173
|
-
await assertPlainDirectory(
|
|
33531
|
+
await mkdir35(path58.dirname(target), { recursive: true });
|
|
33532
|
+
await assertPlainDirectory(path58.dirname(target));
|
|
33174
33533
|
await assertPlainFileOrMissing(target);
|
|
33175
|
-
const temporary =
|
|
33176
|
-
|
|
33177
|
-
`.${
|
|
33534
|
+
const temporary = path58.join(
|
|
33535
|
+
path58.dirname(target),
|
|
33536
|
+
`.${path58.basename(target)}.${process.pid}.${createUlid()}.tmp`
|
|
33178
33537
|
);
|
|
33179
33538
|
try {
|
|
33180
|
-
await
|
|
33539
|
+
await writeFile40(temporary, `${JSON.stringify(value, null, 2)}
|
|
33181
33540
|
`, {
|
|
33182
33541
|
encoding: "utf8",
|
|
33183
33542
|
flag: "wx"
|
|
@@ -33189,61 +33548,61 @@ async function writeJsonAtomic4(target, value) {
|
|
|
33189
33548
|
}
|
|
33190
33549
|
}
|
|
33191
33550
|
async function assertPlainDirectory(target) {
|
|
33192
|
-
const entry = await
|
|
33551
|
+
const entry = await lstat21(target);
|
|
33193
33552
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
33194
33553
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
33195
33554
|
}
|
|
33196
33555
|
}
|
|
33197
33556
|
async function assertPlainFileOrMissing(target) {
|
|
33198
33557
|
try {
|
|
33199
|
-
const entry = await
|
|
33558
|
+
const entry = await lstat21(target);
|
|
33200
33559
|
if (!entry.isFile() || entry.isSymbolicLink()) {
|
|
33201
33560
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
33202
33561
|
}
|
|
33203
33562
|
} catch (error) {
|
|
33204
|
-
if (
|
|
33563
|
+
if (isNotFound28(error)) return;
|
|
33205
33564
|
throw error;
|
|
33206
33565
|
}
|
|
33207
33566
|
}
|
|
33208
33567
|
async function directoryHasEntries(target) {
|
|
33209
33568
|
try {
|
|
33210
|
-
const entry = await
|
|
33569
|
+
const entry = await lstat21(target);
|
|
33211
33570
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
33212
33571
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
33213
33572
|
}
|
|
33214
|
-
return (await
|
|
33573
|
+
return (await readdir19(target)).length > 0;
|
|
33215
33574
|
} catch (error) {
|
|
33216
|
-
if (
|
|
33575
|
+
if (isNotFound28(error)) return false;
|
|
33217
33576
|
throw error;
|
|
33218
33577
|
}
|
|
33219
33578
|
}
|
|
33220
33579
|
async function pathExists14(target) {
|
|
33221
33580
|
try {
|
|
33222
|
-
await
|
|
33581
|
+
await lstat21(target);
|
|
33223
33582
|
return true;
|
|
33224
33583
|
} catch (error) {
|
|
33225
|
-
if (
|
|
33584
|
+
if (isNotFound28(error)) return false;
|
|
33226
33585
|
throw error;
|
|
33227
33586
|
}
|
|
33228
33587
|
}
|
|
33229
33588
|
async function releaseLocks3(locks) {
|
|
33230
33589
|
await Promise.allSettled([...locks].reverse().map((lock) => lock.release()));
|
|
33231
33590
|
}
|
|
33232
|
-
function
|
|
33591
|
+
function isNotFound28(error) {
|
|
33233
33592
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
33234
33593
|
}
|
|
33235
33594
|
|
|
33236
33595
|
// src/team/transport-migration-adapters.ts
|
|
33237
33596
|
import {
|
|
33238
|
-
lstat as
|
|
33239
|
-
mkdir as
|
|
33240
|
-
readFile as
|
|
33241
|
-
readdir as
|
|
33597
|
+
lstat as lstat22,
|
|
33598
|
+
mkdir as mkdir36,
|
|
33599
|
+
readFile as readFile40,
|
|
33600
|
+
readdir as readdir20,
|
|
33242
33601
|
rename as rename10,
|
|
33243
33602
|
unlink as unlink4,
|
|
33244
|
-
writeFile as
|
|
33603
|
+
writeFile as writeFile41
|
|
33245
33604
|
} from "fs/promises";
|
|
33246
|
-
import
|
|
33605
|
+
import path59 from "path";
|
|
33247
33606
|
|
|
33248
33607
|
// src/team/transport-migration.ts
|
|
33249
33608
|
var DIGEST_PATTERN7 = /^sha256:[a-f0-9]{64}$/;
|
|
@@ -34315,7 +34674,7 @@ function compareUtf812(left, right) {
|
|
|
34315
34674
|
var STAGE_DIRECTORY = "transport-migrations";
|
|
34316
34675
|
var COLLECTIONS = ["claims", "handoffs", "task-heads"];
|
|
34317
34676
|
async function createTransportMigrationFileAdapters(input) {
|
|
34318
|
-
const projectRoot =
|
|
34677
|
+
const projectRoot = path59.resolve(input.projectRoot);
|
|
34319
34678
|
assertUlid(input.actorId, "transport migration adapter actorId");
|
|
34320
34679
|
if (input.operationId !== void 0) {
|
|
34321
34680
|
assertUlid(input.operationId, "transport migration adapter operationId");
|
|
@@ -34367,7 +34726,7 @@ async function createTransportMigrationFileAdapters(input) {
|
|
|
34367
34726
|
var FileSystemTransportMigrationConfigAdapter = class {
|
|
34368
34727
|
constructor(projectRoot, coordinationStore) {
|
|
34369
34728
|
this.coordinationStore = coordinationStore;
|
|
34370
|
-
this.projectRoot =
|
|
34729
|
+
this.projectRoot = path59.resolve(projectRoot);
|
|
34371
34730
|
}
|
|
34372
34731
|
coordinationStore;
|
|
34373
34732
|
projectRoot;
|
|
@@ -35230,27 +35589,27 @@ async function publishMigrationActorProfiles(projectRoot, profiles) {
|
|
|
35230
35589
|
}
|
|
35231
35590
|
}
|
|
35232
35591
|
async function archiveLocalCoordinationCollections(store, operationId) {
|
|
35233
|
-
const archiveRoot =
|
|
35592
|
+
const archiveRoot = path59.join(
|
|
35234
35593
|
store.root,
|
|
35235
35594
|
STAGE_DIRECTORY,
|
|
35236
35595
|
"archive",
|
|
35237
35596
|
operationId
|
|
35238
35597
|
);
|
|
35239
|
-
await
|
|
35598
|
+
await mkdir36(archiveRoot, { recursive: true });
|
|
35240
35599
|
const directories = {
|
|
35241
35600
|
claims: claimDirectory(store),
|
|
35242
35601
|
handoffs: handoffDirectory(store),
|
|
35243
35602
|
"task-heads": taskHeadDirectory(store)
|
|
35244
35603
|
};
|
|
35245
35604
|
for (const name of COLLECTIONS) {
|
|
35246
|
-
const archived =
|
|
35247
|
-
const absent =
|
|
35605
|
+
const archived = path59.join(archiveRoot, name);
|
|
35606
|
+
const absent = path59.join(archiveRoot, `${name}.absent`);
|
|
35248
35607
|
if (await pathKind(archived) === "directory" || await pathKind(absent) === "file") {
|
|
35249
35608
|
continue;
|
|
35250
35609
|
}
|
|
35251
35610
|
const sourceKind = await pathKind(directories[name]);
|
|
35252
35611
|
if (sourceKind === null) {
|
|
35253
|
-
await
|
|
35612
|
+
await writeFile41(absent, "\n", { encoding: "utf8", flag: "wx" });
|
|
35254
35613
|
continue;
|
|
35255
35614
|
}
|
|
35256
35615
|
if (sourceKind !== "directory") {
|
|
@@ -35263,9 +35622,9 @@ async function listActorProfiles(projectRoot) {
|
|
|
35263
35622
|
const directory = sharedActorProfileDirectory(projectRoot);
|
|
35264
35623
|
let entries;
|
|
35265
35624
|
try {
|
|
35266
|
-
entries = await
|
|
35625
|
+
entries = await readdir20(directory);
|
|
35267
35626
|
} catch (error) {
|
|
35268
|
-
if (
|
|
35627
|
+
if (isNotFound29(error)) return [];
|
|
35269
35628
|
throw error;
|
|
35270
35629
|
}
|
|
35271
35630
|
const profiles = [];
|
|
@@ -35282,18 +35641,18 @@ async function listActorProfiles(projectRoot) {
|
|
|
35282
35641
|
return profiles;
|
|
35283
35642
|
}
|
|
35284
35643
|
async function listSharedTaskRefs(projectRoot) {
|
|
35285
|
-
const directory =
|
|
35644
|
+
const directory = path59.join(projectRoot, ".mancode", "shared", "workflows");
|
|
35286
35645
|
let entries;
|
|
35287
35646
|
try {
|
|
35288
|
-
entries = await
|
|
35647
|
+
entries = await readdir20(directory);
|
|
35289
35648
|
} catch (error) {
|
|
35290
|
-
if (
|
|
35649
|
+
if (isNotFound29(error)) return [];
|
|
35291
35650
|
throw error;
|
|
35292
35651
|
}
|
|
35293
35652
|
const refs = [];
|
|
35294
35653
|
for (const taskId of entries.sort(compareUtf813)) {
|
|
35295
35654
|
assertUlid(taskId, "shared workflow directory");
|
|
35296
|
-
const stat4 = await
|
|
35655
|
+
const stat4 = await lstat22(path59.join(directory, taskId));
|
|
35297
35656
|
if (!stat4.isDirectory() || stat4.isSymbolicLink()) {
|
|
35298
35657
|
throw new Error("MANCODE_CONTEXT_PATH_UNSAFE");
|
|
35299
35658
|
}
|
|
@@ -35305,7 +35664,7 @@ async function readTaskSnapshotOrNull(projectRoot, taskRef) {
|
|
|
35305
35664
|
try {
|
|
35306
35665
|
return await new V3ContextStore(projectRoot).readTaskSnapshot(taskRef);
|
|
35307
35666
|
} catch (error) {
|
|
35308
|
-
if (error instanceof Error && (error.message === "MANCODE_TASK_NOT_FOUND" ||
|
|
35667
|
+
if (error instanceof Error && (error.message === "MANCODE_TASK_NOT_FOUND" || isNotFound29(error))) {
|
|
35309
35668
|
return null;
|
|
35310
35669
|
}
|
|
35311
35670
|
throw error;
|
|
@@ -35367,7 +35726,7 @@ async function readStagedRecord(store, operationId) {
|
|
|
35367
35726
|
);
|
|
35368
35727
|
}
|
|
35369
35728
|
function stagedPath(store, operationId) {
|
|
35370
|
-
return
|
|
35729
|
+
return path59.join(
|
|
35371
35730
|
store.root,
|
|
35372
35731
|
STAGE_DIRECTORY,
|
|
35373
35732
|
"staged",
|
|
@@ -35375,7 +35734,7 @@ function stagedPath(store, operationId) {
|
|
|
35375
35734
|
);
|
|
35376
35735
|
}
|
|
35377
35736
|
function establishedPath(store, operationId) {
|
|
35378
|
-
return
|
|
35737
|
+
return path59.join(
|
|
35379
35738
|
store.root,
|
|
35380
35739
|
STAGE_DIRECTORY,
|
|
35381
35740
|
"established",
|
|
@@ -35383,12 +35742,12 @@ function establishedPath(store, operationId) {
|
|
|
35383
35742
|
);
|
|
35384
35743
|
}
|
|
35385
35744
|
function projectConfigPath2(projectRoot) {
|
|
35386
|
-
return
|
|
35745
|
+
return path59.join(projectRoot, ".mancode", "shared", "config.json");
|
|
35387
35746
|
}
|
|
35388
35747
|
async function readProjectConfigFile(projectRoot) {
|
|
35389
35748
|
try {
|
|
35390
35749
|
return parseProjectConfig(
|
|
35391
|
-
JSON.parse(await
|
|
35750
|
+
JSON.parse(await readFile40(projectConfigPath2(projectRoot), "utf8"))
|
|
35392
35751
|
);
|
|
35393
35752
|
} catch (error) {
|
|
35394
35753
|
if (error instanceof SyntaxError) {
|
|
@@ -35398,14 +35757,14 @@ async function readProjectConfigFile(projectRoot) {
|
|
|
35398
35757
|
}
|
|
35399
35758
|
}
|
|
35400
35759
|
async function writeJsonAtomic5(target, value) {
|
|
35401
|
-
await
|
|
35402
|
-
await assertPlainDirectory2(
|
|
35403
|
-
const temporary =
|
|
35404
|
-
|
|
35405
|
-
`.${
|
|
35760
|
+
await mkdir36(path59.dirname(target), { recursive: true });
|
|
35761
|
+
await assertPlainDirectory2(path59.dirname(target));
|
|
35762
|
+
const temporary = path59.join(
|
|
35763
|
+
path59.dirname(target),
|
|
35764
|
+
`.${path59.basename(target)}.${process.pid}.${createUlid()}.tmp`
|
|
35406
35765
|
);
|
|
35407
35766
|
try {
|
|
35408
|
-
await
|
|
35767
|
+
await writeFile41(temporary, serialize14(value), {
|
|
35409
35768
|
encoding: "utf8",
|
|
35410
35769
|
flag: "wx"
|
|
35411
35770
|
});
|
|
@@ -35416,12 +35775,12 @@ async function writeJsonAtomic5(target, value) {
|
|
|
35416
35775
|
}
|
|
35417
35776
|
}
|
|
35418
35777
|
async function writeJsonExclusiveOrEqual(target, value, parser, conflictCode) {
|
|
35419
|
-
await
|
|
35420
|
-
await assertPlainDirectory2(
|
|
35778
|
+
await mkdir36(path59.dirname(target), { recursive: true });
|
|
35779
|
+
await assertPlainDirectory2(path59.dirname(target));
|
|
35421
35780
|
try {
|
|
35422
|
-
await
|
|
35781
|
+
await writeFile41(target, serialize14(value), { encoding: "utf8", flag: "wx" });
|
|
35423
35782
|
} catch (error) {
|
|
35424
|
-
if (!
|
|
35783
|
+
if (!isAlreadyExists24(error)) throw error;
|
|
35425
35784
|
const existing = await readJsonOrNull5(target, parser, conflictCode);
|
|
35426
35785
|
if (existing !== null && digestCanonicalJson(existing) === digestCanonicalJson(value)) {
|
|
35427
35786
|
return;
|
|
@@ -35431,18 +35790,18 @@ async function writeJsonExclusiveOrEqual(target, value, parser, conflictCode) {
|
|
|
35431
35790
|
}
|
|
35432
35791
|
async function readJsonOrNull5(target, parser, corruptCode) {
|
|
35433
35792
|
try {
|
|
35434
|
-
const before = await
|
|
35793
|
+
const before = await lstat22(target);
|
|
35435
35794
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
35436
35795
|
throw new Error("MANCODE_TRANSPORT_MIGRATION_STAGE_UNSAFE");
|
|
35437
35796
|
}
|
|
35438
|
-
const parsed = parser(JSON.parse(await
|
|
35439
|
-
const after = await
|
|
35797
|
+
const parsed = parser(JSON.parse(await readFile40(target, "utf8")));
|
|
35798
|
+
const after = await lstat22(target);
|
|
35440
35799
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
35441
35800
|
throw new Error("MANCODE_TRANSPORT_MIGRATION_STAGE_UNSAFE");
|
|
35442
35801
|
}
|
|
35443
35802
|
return parsed;
|
|
35444
35803
|
} catch (error) {
|
|
35445
|
-
if (
|
|
35804
|
+
if (isNotFound29(error)) return null;
|
|
35446
35805
|
if (error instanceof SyntaxError) throw new Error(corruptCode);
|
|
35447
35806
|
throw error;
|
|
35448
35807
|
}
|
|
@@ -35494,18 +35853,18 @@ function requireRemote(value) {
|
|
|
35494
35853
|
}
|
|
35495
35854
|
async function pathKind(target) {
|
|
35496
35855
|
try {
|
|
35497
|
-
const stat4 = await
|
|
35856
|
+
const stat4 = await lstat22(target);
|
|
35498
35857
|
if (stat4.isSymbolicLink()) return "other";
|
|
35499
35858
|
if (stat4.isFile()) return "file";
|
|
35500
35859
|
if (stat4.isDirectory()) return "directory";
|
|
35501
35860
|
return "other";
|
|
35502
35861
|
} catch (error) {
|
|
35503
|
-
if (
|
|
35862
|
+
if (isNotFound29(error)) return null;
|
|
35504
35863
|
throw error;
|
|
35505
35864
|
}
|
|
35506
35865
|
}
|
|
35507
35866
|
async function assertPlainDirectory2(target) {
|
|
35508
|
-
const stat4 = await
|
|
35867
|
+
const stat4 = await lstat22(target);
|
|
35509
35868
|
if (!stat4.isDirectory() || stat4.isSymbolicLink()) {
|
|
35510
35869
|
throw new Error("MANCODE_TRANSPORT_MIGRATION_STAGE_UNSAFE");
|
|
35511
35870
|
}
|
|
@@ -35514,7 +35873,7 @@ async function unlinkIfExists2(target) {
|
|
|
35514
35873
|
try {
|
|
35515
35874
|
await unlink4(target);
|
|
35516
35875
|
} catch (error) {
|
|
35517
|
-
if (!
|
|
35876
|
+
if (!isNotFound29(error)) throw error;
|
|
35518
35877
|
}
|
|
35519
35878
|
}
|
|
35520
35879
|
function serialize14(value) {
|
|
@@ -35524,10 +35883,10 @@ function serialize14(value) {
|
|
|
35524
35883
|
function compareUtf813(left, right) {
|
|
35525
35884
|
return Buffer.from(left, "utf8").compare(Buffer.from(right, "utf8"));
|
|
35526
35885
|
}
|
|
35527
|
-
function
|
|
35886
|
+
function isAlreadyExists24(error) {
|
|
35528
35887
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
35529
35888
|
}
|
|
35530
|
-
function
|
|
35889
|
+
function isNotFound29(error) {
|
|
35531
35890
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
35532
35891
|
}
|
|
35533
35892
|
|
|
@@ -36967,16 +37326,16 @@ function parsePositiveInteger5(value) {
|
|
|
36967
37326
|
}
|
|
36968
37327
|
|
|
36969
37328
|
// src/commands/uninstall.ts
|
|
36970
|
-
import { access as access5, readFile as
|
|
36971
|
-
import
|
|
37329
|
+
import { access as access5, readFile as readFile41, rm as rm17, writeFile as writeFile42 } from "fs/promises";
|
|
37330
|
+
import path60 from "path";
|
|
36972
37331
|
import process11 from "process";
|
|
36973
37332
|
var EXIT_OK9 = 0;
|
|
36974
37333
|
var EXIT_NOT_INITIALIZED6 = 1;
|
|
36975
37334
|
var EXIT_UNSUPPORTED_PLATFORM2 = 2;
|
|
36976
37335
|
var EXIT_V3_AUTHORITY_PROTECTED = 3;
|
|
36977
37336
|
async function uninstall(rootDir = process11.cwd(), platform, options = {}) {
|
|
36978
|
-
const stateFile =
|
|
36979
|
-
const v3SchemaFile =
|
|
37337
|
+
const stateFile = path60.join(rootDir, ".mancode", "state.json");
|
|
37338
|
+
const v3SchemaFile = path60.join(rootDir, ".mancode", "schema.json");
|
|
36980
37339
|
if (await pathExists15(v3SchemaFile)) {
|
|
36981
37340
|
return uninstallV3(rootDir, platform, options);
|
|
36982
37341
|
}
|
|
@@ -37067,7 +37426,7 @@ async function uninstallAll(rootDir) {
|
|
|
37067
37426
|
await uninstallPlatform(rootDir, p);
|
|
37068
37427
|
}
|
|
37069
37428
|
console.log("\u2713 Removing .mancode/ directory...");
|
|
37070
|
-
await rm17(
|
|
37429
|
+
await rm17(path60.join(rootDir, ".mancode"), {
|
|
37071
37430
|
recursive: true,
|
|
37072
37431
|
force: true
|
|
37073
37432
|
});
|
|
@@ -37077,10 +37436,10 @@ async function uninstallClaudeCode(rootDir) {
|
|
|
37077
37436
|
await cleanClaudeSettings(rootDir);
|
|
37078
37437
|
}
|
|
37079
37438
|
async function cleanClaudeSettings(rootDir) {
|
|
37080
|
-
const settingsPath =
|
|
37439
|
+
const settingsPath = path60.join(rootDir, ".claude", "settings.json");
|
|
37081
37440
|
let content;
|
|
37082
37441
|
try {
|
|
37083
|
-
content = await
|
|
37442
|
+
content = await readFile41(settingsPath, "utf-8");
|
|
37084
37443
|
} catch {
|
|
37085
37444
|
return;
|
|
37086
37445
|
}
|
|
@@ -37106,7 +37465,7 @@ async function cleanClaudeSettings(rootDir) {
|
|
|
37106
37465
|
);
|
|
37107
37466
|
settings.skills = Object.keys(retainedSkills).length > 0 ? retainedSkills : void 0;
|
|
37108
37467
|
}
|
|
37109
|
-
await
|
|
37468
|
+
await writeFile42(
|
|
37110
37469
|
settingsPath,
|
|
37111
37470
|
`${JSON.stringify(settings, null, 2)}
|
|
37112
37471
|
`,
|
|
@@ -37155,12 +37514,12 @@ async function uninstallCursor(rootDir) {
|
|
|
37155
37514
|
await removeCursorCommands(rootDir);
|
|
37156
37515
|
}
|
|
37157
37516
|
async function uninstallCodex(rootDir) {
|
|
37158
|
-
const agentsPath =
|
|
37517
|
+
const agentsPath = path60.join(rootDir, "AGENTS.md");
|
|
37159
37518
|
try {
|
|
37160
|
-
const content = await
|
|
37519
|
+
const content = await readFile41(agentsPath, "utf-8");
|
|
37161
37520
|
const cleaned = removeManagedBlock(content);
|
|
37162
37521
|
if (cleaned.trim()) {
|
|
37163
|
-
await
|
|
37522
|
+
await writeFile42(agentsPath, `${cleaned}
|
|
37164
37523
|
`, "utf-8");
|
|
37165
37524
|
} else {
|
|
37166
37525
|
await rm17(agentsPath, { force: true });
|
|
@@ -37170,16 +37529,16 @@ async function uninstallCodex(rootDir) {
|
|
|
37170
37529
|
await removeCodexSkills(rootDir);
|
|
37171
37530
|
}
|
|
37172
37531
|
async function uninstallCopilot(rootDir) {
|
|
37173
|
-
const instructionsPath =
|
|
37532
|
+
const instructionsPath = path60.join(
|
|
37174
37533
|
rootDir,
|
|
37175
37534
|
".github",
|
|
37176
37535
|
"copilot-instructions.md"
|
|
37177
37536
|
);
|
|
37178
37537
|
try {
|
|
37179
|
-
const content = await
|
|
37538
|
+
const content = await readFile41(instructionsPath, "utf-8");
|
|
37180
37539
|
const cleaned = removeManagedBlock(content);
|
|
37181
37540
|
if (cleaned.trim()) {
|
|
37182
|
-
await
|
|
37541
|
+
await writeFile42(instructionsPath, `${cleaned}
|
|
37183
37542
|
`, "utf-8");
|
|
37184
37543
|
} else {
|
|
37185
37544
|
await rm17(instructionsPath, { force: true });
|
|
@@ -37189,16 +37548,16 @@ async function uninstallCopilot(rootDir) {
|
|
|
37189
37548
|
await removeCopilotPrompts(rootDir);
|
|
37190
37549
|
}
|
|
37191
37550
|
async function uninstallZcode(rootDir) {
|
|
37192
|
-
const agentsPath =
|
|
37551
|
+
const agentsPath = path60.join(rootDir, "AGENTS.md");
|
|
37193
37552
|
try {
|
|
37194
|
-
const content = await
|
|
37553
|
+
const content = await readFile41(agentsPath, "utf-8");
|
|
37195
37554
|
const cleaned = removeManagedBlock(
|
|
37196
37555
|
content,
|
|
37197
37556
|
ZCODE_MANCODE_START_MARKER,
|
|
37198
37557
|
ZCODE_MANCODE_END_MARKER
|
|
37199
37558
|
);
|
|
37200
37559
|
if (cleaned.trim()) {
|
|
37201
|
-
await
|
|
37560
|
+
await writeFile42(agentsPath, `${cleaned}
|
|
37202
37561
|
`, "utf-8");
|
|
37203
37562
|
} else {
|
|
37204
37563
|
await rm17(agentsPath, { force: true });
|
|
@@ -37208,9 +37567,9 @@ async function uninstallZcode(rootDir) {
|
|
|
37208
37567
|
await removeZcodeSkills(rootDir);
|
|
37209
37568
|
}
|
|
37210
37569
|
async function removeFromConfig(rootDir, platform) {
|
|
37211
|
-
const configPath =
|
|
37570
|
+
const configPath = path60.join(rootDir, ".mancode", "config.json");
|
|
37212
37571
|
try {
|
|
37213
|
-
const raw = await
|
|
37572
|
+
const raw = await readFile41(configPath, "utf-8");
|
|
37214
37573
|
const config = JSON.parse(raw);
|
|
37215
37574
|
if (Array.isArray(config.platforms)) {
|
|
37216
37575
|
config.platforms = config.platforms.filter((p) => p !== platform);
|
|
@@ -37222,7 +37581,7 @@ async function removeFromConfig(rootDir, platform) {
|
|
|
37222
37581
|
);
|
|
37223
37582
|
config.platformOptions = Object.keys(platformOptions).length > 0 ? platformOptions : void 0;
|
|
37224
37583
|
}
|
|
37225
|
-
await
|
|
37584
|
+
await writeFile42(
|
|
37226
37585
|
configPath,
|
|
37227
37586
|
`${JSON.stringify(config, null, 2)}
|
|
37228
37587
|
`,
|
|
@@ -37255,8 +37614,8 @@ function version() {
|
|
|
37255
37614
|
}
|
|
37256
37615
|
|
|
37257
37616
|
// src/commands/workflow.ts
|
|
37258
|
-
import { access as access6, readFile as
|
|
37259
|
-
import
|
|
37617
|
+
import { access as access6, readFile as readFile43, rm as rm19, writeFile as writeFile44 } from "fs/promises";
|
|
37618
|
+
import path62 from "path";
|
|
37260
37619
|
|
|
37261
37620
|
// src/context/child-result-merge.ts
|
|
37262
37621
|
async function mergeV3ChildResult(input) {
|
|
@@ -39711,14 +40070,14 @@ function updateMetadata4(previous, verification, operationId, updatedAt) {
|
|
|
39711
40070
|
|
|
39712
40071
|
// src/context/workflow-create.ts
|
|
39713
40072
|
import {
|
|
39714
|
-
lstat as
|
|
39715
|
-
mkdir as
|
|
39716
|
-
readFile as
|
|
40073
|
+
lstat as lstat23,
|
|
40074
|
+
mkdir as mkdir37,
|
|
40075
|
+
readFile as readFile42,
|
|
39717
40076
|
rename as rename11,
|
|
39718
40077
|
rm as rm18,
|
|
39719
|
-
writeFile as
|
|
40078
|
+
writeFile as writeFile43
|
|
39720
40079
|
} from "fs/promises";
|
|
39721
|
-
import
|
|
40080
|
+
import path61 from "path";
|
|
39722
40081
|
|
|
39723
40082
|
// src/context/creation-resolution.ts
|
|
39724
40083
|
function resolveWorkflowCreation(request) {
|
|
@@ -39828,7 +40187,7 @@ function rejectConflict(provided, expected, label) {
|
|
|
39828
40187
|
|
|
39829
40188
|
// src/context/workflow-create.ts
|
|
39830
40189
|
async function createV3Workflow(input) {
|
|
39831
|
-
const projectRoot =
|
|
40190
|
+
const projectRoot = path61.resolve(requireProjectRoot2(input.projectRoot));
|
|
39832
40191
|
const task = requireText2(input.task, "workflow task");
|
|
39833
40192
|
const client = requireText2(input.client, "workflow client");
|
|
39834
40193
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
@@ -39991,8 +40350,8 @@ async function createV3Workflow(input) {
|
|
|
39991
40350
|
assertOperationRecoveryPayloadCoversJournal(operation, recoveryPayload);
|
|
39992
40351
|
assertOperationJournalMatchesDefinition(operation);
|
|
39993
40352
|
const taskParent = await ensureSafeTaskParent3(projectRoot, taskRef);
|
|
39994
|
-
const targetDirectory =
|
|
39995
|
-
const stagingDirectory =
|
|
40353
|
+
const targetDirectory = path61.join(taskParent, taskRef.taskId);
|
|
40354
|
+
const stagingDirectory = path61.join(
|
|
39996
40355
|
taskParent,
|
|
39997
40356
|
`.${taskRef.taskId}.${operationId}.staging`
|
|
39998
40357
|
);
|
|
@@ -40433,10 +40792,10 @@ async function ensureSafeTaskParent3(projectRoot, taskRef) {
|
|
|
40433
40792
|
const segments = [".mancode", taskRef.namespace, "workflows"];
|
|
40434
40793
|
let current = projectRoot;
|
|
40435
40794
|
for (const segment of segments) {
|
|
40436
|
-
current =
|
|
40795
|
+
current = path61.join(current, segment);
|
|
40437
40796
|
const existing = await lstatOrNull5(current);
|
|
40438
40797
|
if (existing === null) {
|
|
40439
|
-
await
|
|
40798
|
+
await mkdir37(current);
|
|
40440
40799
|
continue;
|
|
40441
40800
|
}
|
|
40442
40801
|
if (!existing.isDirectory() || existing.isSymbolicLink()) {
|
|
@@ -40449,7 +40808,7 @@ async function assertDirectoryAbsent(target, code) {
|
|
|
40449
40808
|
if (await lstatOrNull5(target) !== null) throw new Error(code);
|
|
40450
40809
|
}
|
|
40451
40810
|
async function writeStagedEntities(stagingDirectory, entities) {
|
|
40452
|
-
await
|
|
40811
|
+
await mkdir37(stagingDirectory);
|
|
40453
40812
|
await assertDirectory(stagingDirectory);
|
|
40454
40813
|
await Promise.all([
|
|
40455
40814
|
writeStagedJson(stagingDirectory, "metadata.json", entities.metadata),
|
|
@@ -40469,13 +40828,13 @@ async function writeStagedEntities(stagingDirectory, entities) {
|
|
|
40469
40828
|
}
|
|
40470
40829
|
async function writeStagedJson(stagingDirectory, fileName, value) {
|
|
40471
40830
|
await assertDirectory(stagingDirectory);
|
|
40472
|
-
const target =
|
|
40473
|
-
await
|
|
40831
|
+
const target = path61.join(stagingDirectory, fileName);
|
|
40832
|
+
await writeFile43(target, `${JSON.stringify(value, null, 2)}
|
|
40474
40833
|
`, {
|
|
40475
40834
|
encoding: "utf8",
|
|
40476
40835
|
flag: "wx"
|
|
40477
40836
|
});
|
|
40478
|
-
const entry = await
|
|
40837
|
+
const entry = await lstat23(target);
|
|
40479
40838
|
if (!entry.isFile() || entry.isSymbolicLink()) {
|
|
40480
40839
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
40481
40840
|
}
|
|
@@ -40507,13 +40866,13 @@ async function validateStagedEntities(stagingDirectory) {
|
|
|
40507
40866
|
});
|
|
40508
40867
|
}
|
|
40509
40868
|
async function readStagedJson(stagingDirectory, fileName, parser) {
|
|
40510
|
-
const target =
|
|
40511
|
-
const before = await
|
|
40869
|
+
const target = path61.join(stagingDirectory, fileName);
|
|
40870
|
+
const before = await lstat23(target);
|
|
40512
40871
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
40513
40872
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
40514
40873
|
}
|
|
40515
|
-
const parsed = parser(JSON.parse(await
|
|
40516
|
-
const after = await
|
|
40874
|
+
const parsed = parser(JSON.parse(await readFile42(target, "utf8")));
|
|
40875
|
+
const after = await lstat23(target);
|
|
40517
40876
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
40518
40877
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
40519
40878
|
}
|
|
@@ -40608,16 +40967,16 @@ async function abortPreparedCreate(store, journal, stagingDirectory, now) {
|
|
|
40608
40967
|
}
|
|
40609
40968
|
}
|
|
40610
40969
|
async function assertDirectory(target) {
|
|
40611
|
-
const entry = await
|
|
40970
|
+
const entry = await lstat23(target);
|
|
40612
40971
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
40613
40972
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
40614
40973
|
}
|
|
40615
40974
|
}
|
|
40616
40975
|
async function lstatOrNull5(target) {
|
|
40617
40976
|
try {
|
|
40618
|
-
return await
|
|
40977
|
+
return await lstat23(target);
|
|
40619
40978
|
} catch (error) {
|
|
40620
|
-
if (
|
|
40979
|
+
if (isNotFound30(error)) return null;
|
|
40621
40980
|
throw error;
|
|
40622
40981
|
}
|
|
40623
40982
|
}
|
|
@@ -40637,7 +40996,7 @@ function requireText2(value, label) {
|
|
|
40637
40996
|
}
|
|
40638
40997
|
return value.trim();
|
|
40639
40998
|
}
|
|
40640
|
-
function
|
|
40999
|
+
function isNotFound30(error) {
|
|
40641
41000
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
40642
41001
|
}
|
|
40643
41002
|
|
|
@@ -41191,6 +41550,9 @@ async function publishTaskMutation(input) {
|
|
|
41191
41550
|
taskRef: input.context.taskRef,
|
|
41192
41551
|
expectedRemoteRevision: input.manifest.revision,
|
|
41193
41552
|
expectedOwnershipEpoch: input.fence.ownershipEpoch,
|
|
41553
|
+
expectedTaskBundleDigest: input.manifest.taskBundles.find(
|
|
41554
|
+
(bundle) => sameTaskRef(bundle.taskRef, input.context.taskRef)
|
|
41555
|
+
)?.bundleDigest ?? null,
|
|
41194
41556
|
ownershipFence: fence,
|
|
41195
41557
|
claims: input.claims,
|
|
41196
41558
|
handoffs,
|
|
@@ -41579,7 +41941,7 @@ async function workflow(rootDir, subcommand, args = [], options = {}) {
|
|
|
41579
41941
|
if (v3Activation === "v3_active") {
|
|
41580
41942
|
return workflowV3(rootDir, subcommand, args, options);
|
|
41581
41943
|
}
|
|
41582
|
-
if (!await pathExists16(
|
|
41944
|
+
if (!await pathExists16(path62.join(rootDir, ".mancode", "state.json"))) {
|
|
41583
41945
|
if (v3Activation !== null) {
|
|
41584
41946
|
return printV3Error(
|
|
41585
41947
|
options.json,
|
|
@@ -42507,8 +42869,8 @@ function parseV3ParticipantActorIds(values) {
|
|
|
42507
42869
|
return values;
|
|
42508
42870
|
}
|
|
42509
42871
|
async function readWorkflowInputFile(projectRoot, value) {
|
|
42510
|
-
const inputPath =
|
|
42511
|
-
return
|
|
42872
|
+
const inputPath = path62.isAbsolute(value) ? value : path62.resolve(projectRoot, value);
|
|
42873
|
+
return readFile43(inputPath, "utf8");
|
|
42512
42874
|
}
|
|
42513
42875
|
async function readWorkflowJsonInputFile(projectRoot, value) {
|
|
42514
42876
|
return JSON.parse(await readWorkflowInputFile(projectRoot, value));
|
|
@@ -42575,7 +42937,7 @@ async function readV3ActivationState2(rootDir) {
|
|
|
42575
42937
|
try {
|
|
42576
42938
|
const manifest = parseSchemaManifest(
|
|
42577
42939
|
JSON.parse(
|
|
42578
|
-
await
|
|
42940
|
+
await readFile43(path62.join(rootDir, ".mancode", "schema.json"), "utf8")
|
|
42579
42941
|
)
|
|
42580
42942
|
);
|
|
42581
42943
|
return manifest.activationState === "v3_active" ? "v3_active" : "other";
|
|
@@ -42620,21 +42982,21 @@ async function workflowRequirements(rootDir, args, options) {
|
|
|
42620
42982
|
"requirements can only be finalized for an in-progress man or manteam workflow at step 1 or 2"
|
|
42621
42983
|
);
|
|
42622
42984
|
}
|
|
42623
|
-
const workflowPath =
|
|
42624
|
-
const jsonPath =
|
|
42625
|
-
const markdownPath =
|
|
42626
|
-
const metadataPath3 =
|
|
42985
|
+
const workflowPath = path62.join(rootDir, ".mancode", "workflows", taskId);
|
|
42986
|
+
const jsonPath = path62.join(workflowPath, "requirements.json");
|
|
42987
|
+
const markdownPath = path62.join(workflowPath, "requirements.md");
|
|
42988
|
+
const metadataPath3 = path62.join(workflowPath, "metadata.json");
|
|
42627
42989
|
let originalJson;
|
|
42628
42990
|
let originalMarkdown;
|
|
42629
42991
|
let originalMetadata;
|
|
42630
42992
|
try {
|
|
42631
|
-
const inputPath =
|
|
42632
|
-
const input = await
|
|
42993
|
+
const inputPath = path62.isAbsolute(options.file) ? options.file : path62.resolve(rootDir, options.file);
|
|
42994
|
+
const input = await readFile43(inputPath, "utf-8");
|
|
42633
42995
|
const requirements = parseRequirementsLedger2(input);
|
|
42634
42996
|
[originalJson, originalMarkdown, originalMetadata] = await Promise.all([
|
|
42635
42997
|
readOptionalText2(jsonPath),
|
|
42636
42998
|
readOptionalText2(markdownPath),
|
|
42637
|
-
|
|
42999
|
+
readFile43(metadataPath3, "utf-8")
|
|
42638
43000
|
]);
|
|
42639
43001
|
await writeRequirementsArtifacts(rootDir, taskId, requirements);
|
|
42640
43002
|
await updateWorkflow(rootDir, taskId, {
|
|
@@ -42664,7 +43026,7 @@ async function workflowRequirements(rootDir, args, options) {
|
|
|
42664
43026
|
const rollback = await Promise.allSettled([
|
|
42665
43027
|
restoreOptionalText(jsonPath, originalJson),
|
|
42666
43028
|
restoreOptionalText(markdownPath, originalMarkdown),
|
|
42667
|
-
|
|
43029
|
+
writeFile44(metadataPath3, originalMetadata, "utf-8")
|
|
42668
43030
|
]);
|
|
42669
43031
|
rollbackIncomplete = rollback.some(
|
|
42670
43032
|
(result2) => result2.status === "rejected"
|
|
@@ -42752,7 +43114,7 @@ async function workflowVerify(rootDir, args, options) {
|
|
|
42752
43114
|
);
|
|
42753
43115
|
}
|
|
42754
43116
|
if (options.evidenceFile) {
|
|
42755
|
-
const evidencePath =
|
|
43117
|
+
const evidencePath = path62.isAbsolute(options.evidenceFile) ? options.evidenceFile : path62.resolve(rootDir, options.evidenceFile);
|
|
42756
43118
|
if (!await pathExists16(evidencePath)) {
|
|
42757
43119
|
return invalidArg(
|
|
42758
43120
|
options,
|
|
@@ -42812,17 +43174,17 @@ async function workflowVerify(rootDir, args, options) {
|
|
|
42812
43174
|
}
|
|
42813
43175
|
async function commitVerificationTransition(rootDir, meta, ledger) {
|
|
42814
43176
|
const ledgerPath = verificationLedgerPath(rootDir, meta.taskId);
|
|
42815
|
-
const metadataPath3 =
|
|
43177
|
+
const metadataPath3 = path62.join(
|
|
42816
43178
|
rootDir,
|
|
42817
43179
|
".mancode",
|
|
42818
43180
|
"workflows",
|
|
42819
43181
|
meta.taskId,
|
|
42820
43182
|
"metadata.json"
|
|
42821
43183
|
);
|
|
42822
|
-
const specPath =
|
|
43184
|
+
const specPath = path62.join(rootDir, ".mancode", "memory", "spec.md");
|
|
42823
43185
|
const [originalLedger, originalMetadata, originalSpec] = await Promise.all([
|
|
42824
43186
|
readOptionalText2(ledgerPath),
|
|
42825
|
-
|
|
43187
|
+
readFile43(metadataPath3, "utf-8"),
|
|
42826
43188
|
readOptionalText2(specPath)
|
|
42827
43189
|
]);
|
|
42828
43190
|
const wasVerificationBlocked = meta.status === "blocked" && meta.blockingReason?.startsWith("[verification]");
|
|
@@ -42851,7 +43213,7 @@ async function commitVerificationTransition(rootDir, meta, ledger) {
|
|
|
42851
43213
|
} catch (error) {
|
|
42852
43214
|
const rollback = await Promise.allSettled([
|
|
42853
43215
|
restoreOptionalText(ledgerPath, originalLedger),
|
|
42854
|
-
|
|
43216
|
+
writeFile44(metadataPath3, originalMetadata, "utf-8"),
|
|
42855
43217
|
restoreOptionalText(specPath, originalSpec)
|
|
42856
43218
|
]);
|
|
42857
43219
|
const message = error instanceof Error ? error.message : "verification transition failed";
|
|
@@ -42983,7 +43345,7 @@ async function workflowReview(rootDir, args, options) {
|
|
|
42983
43345
|
}
|
|
42984
43346
|
async function commitReviewSkip(rootDir, meta, reason) {
|
|
42985
43347
|
const ledgerPath = reviewLedgerPath(rootDir, meta.taskId);
|
|
42986
|
-
const metadataPath3 =
|
|
43348
|
+
const metadataPath3 = path62.join(
|
|
42987
43349
|
rootDir,
|
|
42988
43350
|
".mancode",
|
|
42989
43351
|
"workflows",
|
|
@@ -42992,7 +43354,7 @@ async function commitReviewSkip(rootDir, meta, reason) {
|
|
|
42992
43354
|
);
|
|
42993
43355
|
const [originalLedger, originalMetadata] = await Promise.all([
|
|
42994
43356
|
readOptionalText2(ledgerPath),
|
|
42995
|
-
|
|
43357
|
+
readFile43(metadataPath3, "utf-8")
|
|
42996
43358
|
]);
|
|
42997
43359
|
try {
|
|
42998
43360
|
await initializeSkippedReview(rootDir, meta.taskId, reason);
|
|
@@ -43003,7 +43365,7 @@ async function commitReviewSkip(rootDir, meta, reason) {
|
|
|
43003
43365
|
} catch (error) {
|
|
43004
43366
|
const rollback = await Promise.allSettled([
|
|
43005
43367
|
restoreOptionalText(ledgerPath, originalLedger),
|
|
43006
|
-
|
|
43368
|
+
writeFile44(metadataPath3, originalMetadata, "utf-8")
|
|
43007
43369
|
]);
|
|
43008
43370
|
const message = error instanceof Error ? error.message : "review skip failed";
|
|
43009
43371
|
return rollback.some((result2) => result2.status === "rejected") ? `${message}; rollback was incomplete` : message;
|
|
@@ -43223,18 +43585,18 @@ async function workflowHandoff(rootDir, taskId, options) {
|
|
|
43223
43585
|
"solo handoff requires an undecided in-progress workflow at step 4 with ready requirements"
|
|
43224
43586
|
);
|
|
43225
43587
|
}
|
|
43226
|
-
const workflowPath =
|
|
43227
|
-
if (!await pathExists16(
|
|
43588
|
+
const workflowPath = path62.join(rootDir, ".mancode", "workflows", taskId);
|
|
43589
|
+
if (!await pathExists16(path62.join(workflowPath, "requirements.md")) || !await pathExists16(path62.join(workflowPath, "plan.md"))) {
|
|
43228
43590
|
return invalidArg(
|
|
43229
43591
|
options,
|
|
43230
43592
|
"solo handoff requires requirements.md and plan.md"
|
|
43231
43593
|
);
|
|
43232
43594
|
}
|
|
43233
|
-
const statePath =
|
|
43595
|
+
const statePath = path62.join(rootDir, ".mancode", "state.json");
|
|
43234
43596
|
let originalState;
|
|
43235
43597
|
let state;
|
|
43236
43598
|
try {
|
|
43237
|
-
originalState = await
|
|
43599
|
+
originalState = await readFile43(statePath, "utf-8");
|
|
43238
43600
|
state = JSON.parse(originalState);
|
|
43239
43601
|
} catch {
|
|
43240
43602
|
return invalidArg(
|
|
@@ -43305,11 +43667,11 @@ async function workflowCompleteHandoff(rootDir, taskId, options) {
|
|
|
43305
43667
|
`workflow is not an active solo handoff: ${taskId}`
|
|
43306
43668
|
);
|
|
43307
43669
|
}
|
|
43308
|
-
const statePath =
|
|
43670
|
+
const statePath = path62.join(rootDir, ".mancode", "state.json");
|
|
43309
43671
|
let originalState;
|
|
43310
43672
|
let state;
|
|
43311
43673
|
try {
|
|
43312
|
-
originalState = await
|
|
43674
|
+
originalState = await readFile43(statePath, "utf-8");
|
|
43313
43675
|
state = JSON.parse(originalState);
|
|
43314
43676
|
} catch {
|
|
43315
43677
|
return invalidArg(
|
|
@@ -43372,18 +43734,18 @@ async function workflowDecide(rootDir, taskId, options) {
|
|
|
43372
43734
|
`workflow is not ready for a plan-only decision: ${taskId}`
|
|
43373
43735
|
);
|
|
43374
43736
|
}
|
|
43375
|
-
const workflowPath =
|
|
43376
|
-
if (!await pathExists16(
|
|
43737
|
+
const workflowPath = path62.join(rootDir, ".mancode", "workflows", taskId);
|
|
43738
|
+
if (!await pathExists16(path62.join(workflowPath, "requirements.md")) || !await pathExists16(path62.join(workflowPath, "plan.md"))) {
|
|
43377
43739
|
return invalidArg(
|
|
43378
43740
|
options,
|
|
43379
43741
|
"plan-only requires requirements.md and plan.md"
|
|
43380
43742
|
);
|
|
43381
43743
|
}
|
|
43382
|
-
const statePath =
|
|
43744
|
+
const statePath = path62.join(rootDir, ".mancode", "state.json");
|
|
43383
43745
|
let originalState;
|
|
43384
43746
|
let state;
|
|
43385
43747
|
try {
|
|
43386
|
-
originalState = await
|
|
43748
|
+
originalState = await readFile43(statePath, "utf-8");
|
|
43387
43749
|
state = JSON.parse(originalState);
|
|
43388
43750
|
} catch {
|
|
43389
43751
|
return invalidArg(
|
|
@@ -43435,25 +43797,25 @@ async function workflowDecide(rootDir, taskId, options) {
|
|
|
43435
43797
|
return EXIT_OK10;
|
|
43436
43798
|
}
|
|
43437
43799
|
async function commitPlanningTransition(args) {
|
|
43438
|
-
const metadataPath3 =
|
|
43800
|
+
const metadataPath3 = path62.join(
|
|
43439
43801
|
args.rootDir,
|
|
43440
43802
|
".mancode",
|
|
43441
43803
|
"workflows",
|
|
43442
43804
|
args.taskId,
|
|
43443
43805
|
"metadata.json"
|
|
43444
43806
|
);
|
|
43445
|
-
const specPath =
|
|
43807
|
+
const specPath = path62.join(args.rootDir, ".mancode", "memory", "spec.md");
|
|
43446
43808
|
let originalMetadata;
|
|
43447
43809
|
let originalSpec;
|
|
43448
43810
|
try {
|
|
43449
|
-
originalMetadata = await
|
|
43811
|
+
originalMetadata = await readFile43(metadataPath3, "utf-8");
|
|
43450
43812
|
originalSpec = await readOptionalText2(specPath);
|
|
43451
43813
|
} catch (error) {
|
|
43452
43814
|
return error instanceof Error ? `unable to prepare planning transition: ${error.message}` : "unable to prepare planning transition";
|
|
43453
43815
|
}
|
|
43454
43816
|
try {
|
|
43455
43817
|
await updateWorkflow(args.rootDir, args.taskId, args.workflowPatch);
|
|
43456
|
-
await
|
|
43818
|
+
await writeFile44(
|
|
43457
43819
|
args.statePath,
|
|
43458
43820
|
`${JSON.stringify(args.nextState, null, 2)}
|
|
43459
43821
|
`,
|
|
@@ -43467,9 +43829,9 @@ async function commitPlanningTransition(args) {
|
|
|
43467
43829
|
return null;
|
|
43468
43830
|
} catch (error) {
|
|
43469
43831
|
const rollback = await Promise.allSettled([
|
|
43470
|
-
|
|
43471
|
-
|
|
43472
|
-
originalSpec === null ? rm19(specPath, { force: true }) :
|
|
43832
|
+
writeFile44(metadataPath3, originalMetadata, "utf-8"),
|
|
43833
|
+
writeFile44(args.statePath, args.originalState, "utf-8"),
|
|
43834
|
+
originalSpec === null ? rm19(specPath, { force: true }) : writeFile44(specPath, originalSpec, "utf-8")
|
|
43473
43835
|
]);
|
|
43474
43836
|
const message = error instanceof Error ? error.message : "planning transition failed";
|
|
43475
43837
|
return rollback.some((result2) => result2.status === "rejected") ? `${message}; rollback was incomplete` : message;
|
|
@@ -43477,7 +43839,7 @@ async function commitPlanningTransition(args) {
|
|
|
43477
43839
|
}
|
|
43478
43840
|
async function readOptionalText2(filePath) {
|
|
43479
43841
|
try {
|
|
43480
|
-
return await
|
|
43842
|
+
return await readFile43(filePath, "utf-8");
|
|
43481
43843
|
} catch (error) {
|
|
43482
43844
|
if (isNodeError10(error) && error.code === "ENOENT") return null;
|
|
43483
43845
|
throw error;
|
|
@@ -43488,7 +43850,7 @@ async function restoreOptionalText(filePath, content) {
|
|
|
43488
43850
|
await rm19(filePath, { force: true });
|
|
43489
43851
|
return;
|
|
43490
43852
|
}
|
|
43491
|
-
await
|
|
43853
|
+
await writeFile44(filePath, content, "utf-8");
|
|
43492
43854
|
}
|
|
43493
43855
|
function readActiveSoloPlan(value) {
|
|
43494
43856
|
if (!value || typeof value !== "object") return null;
|