mancode 0.3.16 → 0.3.18
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 +1150 -768
- 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
|
);
|
|
@@ -18567,10 +18954,10 @@ async function materializeGitRefTaskBundle(input) {
|
|
|
18567
18954
|
const store = resolveCoordinationEntityHomeStore(
|
|
18568
18955
|
runtime.entityHomeStoreContext
|
|
18569
18956
|
);
|
|
18570
|
-
const locks = await acquireEntityLocks(
|
|
18957
|
+
const locks = input.taskLockHeld ? [] : await acquireEntityLocks(
|
|
18571
18958
|
store,
|
|
18572
18959
|
operationId,
|
|
18573
|
-
[
|
|
18960
|
+
[taskEntityKey(bundle.taskRef)],
|
|
18574
18961
|
{ now }
|
|
18575
18962
|
);
|
|
18576
18963
|
try {
|
|
@@ -18580,16 +18967,42 @@ 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;
|
|
18996
|
+
if (status2 === "unchanged" && currentFence !== null && taskHeadFenceMatchesTarget({
|
|
18997
|
+
currentFence,
|
|
18998
|
+
runtime,
|
|
18999
|
+
remoteRevision,
|
|
19000
|
+
ownershipFence,
|
|
19001
|
+
bundle
|
|
19002
|
+
})) {
|
|
19003
|
+
await recordGitRefTaskRemoteBase(projectRoot, remoteRevision, bundle);
|
|
19004
|
+
return result(status2, bundle, null, currentFence);
|
|
19005
|
+
}
|
|
18593
19006
|
const targetFence = buildTargetFence({
|
|
18594
19007
|
runtime,
|
|
18595
19008
|
remoteRevision,
|
|
@@ -18600,7 +19013,13 @@ async function materializeGitRefTaskBundle(input) {
|
|
|
18600
19013
|
now
|
|
18601
19014
|
});
|
|
18602
19015
|
if (status2 === "unchanged") {
|
|
18603
|
-
await writeTargetFence(
|
|
19016
|
+
await writeTargetFence(
|
|
19017
|
+
store,
|
|
19018
|
+
currentFence,
|
|
19019
|
+
targetFence,
|
|
19020
|
+
materializedPredecessor
|
|
19021
|
+
);
|
|
19022
|
+
await recordGitRefTaskRemoteBase(projectRoot, remoteRevision, bundle);
|
|
18604
19023
|
return result(status2, bundle, null, targetFence);
|
|
18605
19024
|
}
|
|
18606
19025
|
const timestamp4 = now.toISOString();
|
|
@@ -18621,6 +19040,7 @@ async function materializeGitRefTaskBundle(input) {
|
|
|
18621
19040
|
journal = { ...journal, state: "applying", updatedAt: timestamp4 };
|
|
18622
19041
|
await replaceJournal(projectRoot, journal);
|
|
18623
19042
|
await applyJournal(projectRoot, journal);
|
|
19043
|
+
await recordGitRefTaskRemoteBase(projectRoot, remoteRevision, bundle);
|
|
18624
19044
|
journal = {
|
|
18625
19045
|
...journal,
|
|
18626
19046
|
state: "committed",
|
|
@@ -18646,6 +19066,11 @@ async function recoverTaskMaterializationsWhileLocked(projectRoot, taskId) {
|
|
|
18646
19066
|
continue;
|
|
18647
19067
|
}
|
|
18648
19068
|
await applyJournal(projectRoot, journal);
|
|
19069
|
+
await recordGitRefTaskRemoteBase(
|
|
19070
|
+
projectRoot,
|
|
19071
|
+
journal.remoteRevision,
|
|
19072
|
+
journal.targetBundle
|
|
19073
|
+
);
|
|
18649
19074
|
await replaceJournal(projectRoot, {
|
|
18650
19075
|
...journal,
|
|
18651
19076
|
state: "committed",
|
|
@@ -18758,6 +19183,9 @@ function buildTargetFence(input) {
|
|
|
18758
19183
|
updatedAt: input.now.toISOString()
|
|
18759
19184
|
});
|
|
18760
19185
|
}
|
|
19186
|
+
function taskHeadFenceMatchesTarget(input) {
|
|
19187
|
+
return input.currentFence.workspaceId === input.runtime.workspaceId && sameTaskRef(input.currentFence.taskRef, input.bundle.taskRef) && input.currentFence.taskRevision === input.bundle.taskRevision && input.currentFence.aggregateDigest === input.bundle.aggregateDigest && input.currentFence.ownershipEpoch === input.bundle.ownershipEpoch && input.currentFence.codeRef.head === input.bundle.codeRef.head && input.currentFence.checkoutId === input.runtime.checkoutId && input.currentFence.remoteRevision === input.remoteRevision && input.currentFence.lastOperationId === input.ownershipFence.lastOperationId;
|
|
19188
|
+
}
|
|
18761
19189
|
async function writeTargetFence(store, current, target, predecessor) {
|
|
18762
19190
|
if (current !== null && digestCanonicalJson(current) === digestCanonicalJson(target)) {
|
|
18763
19191
|
return;
|
|
@@ -18812,7 +19240,7 @@ async function replaceVerifiedFile(taskRoot2, relativePath, targetContent, prede
|
|
|
18812
19240
|
const target = safeTaskPath(taskRoot2, relativePath);
|
|
18813
19241
|
await ensureSafeDirectory(
|
|
18814
19242
|
taskRoot2,
|
|
18815
|
-
|
|
19243
|
+
path32.dirname(relativePath).split(path32.sep)
|
|
18816
19244
|
);
|
|
18817
19245
|
const current = await readSafeFileOrNull(target);
|
|
18818
19246
|
if (contentMatches(relativePath, current, targetContent)) return;
|
|
@@ -18822,11 +19250,11 @@ async function replaceVerifiedFile(taskRoot2, relativePath, targetContent, prede
|
|
|
18822
19250
|
if (current === null && (predecessorContent !== null || alternatePredecessorContent !== null) && relativePath !== "summary.md") {
|
|
18823
19251
|
throw new Error("MANCODE_SPLIT_BRAIN");
|
|
18824
19252
|
}
|
|
18825
|
-
const temporary =
|
|
18826
|
-
|
|
18827
|
-
`.${
|
|
19253
|
+
const temporary = path32.join(
|
|
19254
|
+
path32.dirname(target),
|
|
19255
|
+
`.${path32.basename(target)}.${process.pid}.${Date.now()}.tmp`
|
|
18828
19256
|
);
|
|
18829
|
-
await
|
|
19257
|
+
await writeFile28(temporary, targetContent, { encoding: "utf8", flag: "wx" });
|
|
18830
19258
|
await replaceFileAtomically(temporary, target);
|
|
18831
19259
|
}
|
|
18832
19260
|
function contentMatches(relativePath, current, expected) {
|
|
@@ -18876,44 +19304,44 @@ async function removeVerifiedFile(taskRoot2, relativePath, predecessorContent) {
|
|
|
18876
19304
|
}
|
|
18877
19305
|
async function readSafeFileOrNull(target) {
|
|
18878
19306
|
try {
|
|
18879
|
-
const before = await
|
|
19307
|
+
const before = await lstat16(target);
|
|
18880
19308
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
18881
19309
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18882
19310
|
}
|
|
18883
|
-
const content = await
|
|
18884
|
-
const after = await
|
|
19311
|
+
const content = await readFile28(target, "utf8");
|
|
19312
|
+
const after = await lstat16(target);
|
|
18885
19313
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
18886
19314
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18887
19315
|
}
|
|
18888
19316
|
return content;
|
|
18889
19317
|
} catch (error) {
|
|
18890
|
-
if (
|
|
19318
|
+
if (isNotFound24(error)) return null;
|
|
18891
19319
|
throw error;
|
|
18892
19320
|
}
|
|
18893
19321
|
}
|
|
18894
19322
|
async function ensureSafeDirectory(root, segments) {
|
|
18895
|
-
let current =
|
|
19323
|
+
let current = path32.resolve(root);
|
|
18896
19324
|
for (const segment of segments) {
|
|
18897
19325
|
if (!segment || segment === ".") continue;
|
|
18898
19326
|
if (segment === ".." || segment.includes("/") || segment.includes("\\")) {
|
|
18899
19327
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18900
19328
|
}
|
|
18901
|
-
current =
|
|
19329
|
+
current = path32.join(current, segment);
|
|
18902
19330
|
try {
|
|
18903
|
-
await
|
|
19331
|
+
await mkdir25(current);
|
|
18904
19332
|
} catch (error) {
|
|
18905
|
-
if (!
|
|
19333
|
+
if (!isAlreadyExists20(error)) throw error;
|
|
18906
19334
|
}
|
|
18907
|
-
const entry = await
|
|
19335
|
+
const entry = await lstat16(current);
|
|
18908
19336
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
18909
19337
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18910
19338
|
}
|
|
18911
19339
|
}
|
|
18912
19340
|
}
|
|
18913
19341
|
function safeTaskPath(taskRoot2, relativePath) {
|
|
18914
|
-
const target =
|
|
18915
|
-
const relative =
|
|
18916
|
-
if (!relative || relative.startsWith("..") ||
|
|
19342
|
+
const target = path32.resolve(taskRoot2, relativePath);
|
|
19343
|
+
const relative = path32.relative(taskRoot2, target);
|
|
19344
|
+
if (!relative || relative.startsWith("..") || path32.isAbsolute(relative)) {
|
|
18917
19345
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
18918
19346
|
}
|
|
18919
19347
|
return target;
|
|
@@ -18925,7 +19353,7 @@ async function createJournal(projectRoot, journal) {
|
|
|
18925
19353
|
"journals",
|
|
18926
19354
|
"git-ref-materialize"
|
|
18927
19355
|
]);
|
|
18928
|
-
await
|
|
19356
|
+
await writeFile28(
|
|
18929
19357
|
journalPath(projectRoot, journal.operationId),
|
|
18930
19358
|
serialize11(journal),
|
|
18931
19359
|
{
|
|
@@ -18936,11 +19364,11 @@ async function createJournal(projectRoot, journal) {
|
|
|
18936
19364
|
}
|
|
18937
19365
|
async function replaceJournal(projectRoot, journal) {
|
|
18938
19366
|
const target = journalPath(projectRoot, journal.operationId);
|
|
18939
|
-
const temporary =
|
|
18940
|
-
|
|
19367
|
+
const temporary = path32.join(
|
|
19368
|
+
path32.dirname(target),
|
|
18941
19369
|
`.${journal.operationId}.${process.pid}.${Date.now()}.tmp`
|
|
18942
19370
|
);
|
|
18943
|
-
await
|
|
19371
|
+
await writeFile28(temporary, serialize11(journal), {
|
|
18944
19372
|
encoding: "utf8",
|
|
18945
19373
|
flag: "wx"
|
|
18946
19374
|
});
|
|
@@ -18948,7 +19376,7 @@ async function replaceJournal(projectRoot, journal) {
|
|
|
18948
19376
|
}
|
|
18949
19377
|
async function readJournal(target) {
|
|
18950
19378
|
try {
|
|
18951
|
-
const raw = JSON.parse(await
|
|
19379
|
+
const raw = JSON.parse(await readFile28(target, "utf8"));
|
|
18952
19380
|
return parseJournal(raw);
|
|
18953
19381
|
} catch (error) {
|
|
18954
19382
|
if (error instanceof SyntaxError) {
|
|
@@ -18961,15 +19389,15 @@ async function listJournals(projectRoot) {
|
|
|
18961
19389
|
const directory = journalDirectory(projectRoot);
|
|
18962
19390
|
let entries;
|
|
18963
19391
|
try {
|
|
18964
|
-
entries = await
|
|
19392
|
+
entries = await readdir13(directory);
|
|
18965
19393
|
} catch (error) {
|
|
18966
|
-
if (
|
|
19394
|
+
if (isNotFound24(error)) return [];
|
|
18967
19395
|
throw error;
|
|
18968
19396
|
}
|
|
18969
19397
|
const journals = [];
|
|
18970
19398
|
for (const entry of entries.sort()) {
|
|
18971
19399
|
if (!entry.endsWith(".json")) continue;
|
|
18972
|
-
journals.push(await readJournal(
|
|
19400
|
+
journals.push(await readJournal(path32.join(directory, entry)));
|
|
18973
19401
|
}
|
|
18974
19402
|
return journals;
|
|
18975
19403
|
}
|
|
@@ -19012,7 +19440,7 @@ function parseJournal(value) {
|
|
|
19012
19440
|
schemaVersion: 1,
|
|
19013
19441
|
operationId: value.operationId,
|
|
19014
19442
|
workspaceId: value.workspaceId,
|
|
19015
|
-
remoteRevision:
|
|
19443
|
+
remoteRevision: positiveInteger3(
|
|
19016
19444
|
value.remoteRevision,
|
|
19017
19445
|
"git-ref materialization remoteRevision"
|
|
19018
19446
|
),
|
|
@@ -19035,8 +19463,8 @@ function result(status2, bundle, localJournalPath, taskHeadFence) {
|
|
|
19035
19463
|
};
|
|
19036
19464
|
}
|
|
19037
19465
|
function journalDirectory(projectRoot) {
|
|
19038
|
-
return
|
|
19039
|
-
|
|
19466
|
+
return path32.join(
|
|
19467
|
+
path32.resolve(projectRoot),
|
|
19040
19468
|
".mancode",
|
|
19041
19469
|
"local",
|
|
19042
19470
|
"journals",
|
|
@@ -19045,13 +19473,13 @@ function journalDirectory(projectRoot) {
|
|
|
19045
19473
|
}
|
|
19046
19474
|
function journalPath(projectRoot, operationId) {
|
|
19047
19475
|
assertUlid(operationId, "git-ref materialization operationId");
|
|
19048
|
-
return
|
|
19476
|
+
return path32.join(journalDirectory(projectRoot), `${operationId}.json`);
|
|
19049
19477
|
}
|
|
19050
19478
|
function serialize11(value) {
|
|
19051
19479
|
return `${JSON.stringify(value, null, 2)}
|
|
19052
19480
|
`;
|
|
19053
19481
|
}
|
|
19054
|
-
function
|
|
19482
|
+
function positiveInteger3(value, label) {
|
|
19055
19483
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1) {
|
|
19056
19484
|
throw new Error(`${label} must be a positive integer`);
|
|
19057
19485
|
}
|
|
@@ -19065,23 +19493,23 @@ function timestamp2(value) {
|
|
|
19065
19493
|
}
|
|
19066
19494
|
async function pathExists2(target) {
|
|
19067
19495
|
try {
|
|
19068
|
-
await
|
|
19496
|
+
await lstat16(target);
|
|
19069
19497
|
return true;
|
|
19070
19498
|
} catch (error) {
|
|
19071
|
-
if (
|
|
19499
|
+
if (isNotFound24(error)) return false;
|
|
19072
19500
|
throw error;
|
|
19073
19501
|
}
|
|
19074
19502
|
}
|
|
19075
|
-
function
|
|
19503
|
+
function isAlreadyExists20(error) {
|
|
19076
19504
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
19077
19505
|
}
|
|
19078
|
-
function
|
|
19506
|
+
function isNotFound24(error) {
|
|
19079
19507
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
19080
19508
|
}
|
|
19081
19509
|
|
|
19082
19510
|
// src/team/git-ref-workflow-repair.ts
|
|
19083
19511
|
async function prepareGitRefWorkflowRepair(input) {
|
|
19084
|
-
const root =
|
|
19512
|
+
const root = path33.resolve(input.projectRoot);
|
|
19085
19513
|
const prepared2 = parsePrepared(input.prepared);
|
|
19086
19514
|
const pendingMetadata = parseWorkflowMetadata(input.pendingMetadata);
|
|
19087
19515
|
assertPendingMetadata2(prepared2, pendingMetadata);
|
|
@@ -19116,7 +19544,7 @@ async function prepareGitRefWorkflowRepair(input) {
|
|
|
19116
19544
|
}
|
|
19117
19545
|
async function recoverGitRefWorkflowRepair(projectRoot, operationId, transportReceipt = null, options = {}) {
|
|
19118
19546
|
assertUlid(operationId, "git-ref workflow repair operationId");
|
|
19119
|
-
const root =
|
|
19547
|
+
const root = path33.resolve(projectRoot);
|
|
19120
19548
|
let journal = await requireJournal(root, operationId);
|
|
19121
19549
|
await assertRecoveryAuthorized(root, journal, options);
|
|
19122
19550
|
if (journal.state === "committed" || journal.state === "aborted") {
|
|
@@ -19188,6 +19616,7 @@ async function recoverGitRefWorkflowRepair(projectRoot, operationId, transportRe
|
|
|
19188
19616
|
bundle: targetBundle,
|
|
19189
19617
|
predecessorBundle: journal.prepared.predecessorBundle,
|
|
19190
19618
|
pendingMetadata: journal.pendingMetadata,
|
|
19619
|
+
taskLockHeld: true,
|
|
19191
19620
|
operationId: createUlid()
|
|
19192
19621
|
});
|
|
19193
19622
|
journal = await transitionJournal(
|
|
@@ -19348,21 +19777,21 @@ function parsePrepared(value) {
|
|
|
19348
19777
|
throw new Error("MANCODE_REMOTE_WORKFLOW_REPAIR_JOURNAL_CORRUPT");
|
|
19349
19778
|
}
|
|
19350
19779
|
assertUlid(value.operationId, "git-ref workflow prepared operationId");
|
|
19351
|
-
const expectedRemoteRevision =
|
|
19780
|
+
const expectedRemoteRevision = positiveInteger4(
|
|
19352
19781
|
value.expectedRemoteRevision,
|
|
19353
19782
|
"git-ref workflow expectedRemoteRevision",
|
|
19354
19783
|
true
|
|
19355
19784
|
);
|
|
19356
|
-
const expectedOwnershipEpoch =
|
|
19785
|
+
const expectedOwnershipEpoch = positiveInteger4(
|
|
19357
19786
|
value.expectedOwnershipEpoch,
|
|
19358
19787
|
"git-ref workflow expectedOwnershipEpoch",
|
|
19359
19788
|
true
|
|
19360
19789
|
);
|
|
19361
|
-
const targetRemoteRevision =
|
|
19790
|
+
const targetRemoteRevision = positiveInteger4(
|
|
19362
19791
|
value.targetRemoteRevision,
|
|
19363
19792
|
"git-ref workflow targetRemoteRevision"
|
|
19364
19793
|
);
|
|
19365
|
-
const targetOwnershipEpoch =
|
|
19794
|
+
const targetOwnershipEpoch = positiveInteger4(
|
|
19366
19795
|
value.targetOwnershipEpoch,
|
|
19367
19796
|
"git-ref workflow targetOwnershipEpoch",
|
|
19368
19797
|
true
|
|
@@ -19482,12 +19911,12 @@ async function createJournal2(projectRoot, journal) {
|
|
|
19482
19911
|
await ensureJournalDirectory(projectRoot);
|
|
19483
19912
|
const target = gitRefWorkflowRepairJournalPath(projectRoot, journal.operationId);
|
|
19484
19913
|
try {
|
|
19485
|
-
await
|
|
19914
|
+
await writeFile29(target, serialize12(journal), {
|
|
19486
19915
|
encoding: "utf8",
|
|
19487
19916
|
flag: "wx"
|
|
19488
19917
|
});
|
|
19489
19918
|
} catch (error) {
|
|
19490
|
-
if (!
|
|
19919
|
+
if (!isAlreadyExists21(error)) throw error;
|
|
19491
19920
|
const existing = await requireJournal(projectRoot, journal.operationId);
|
|
19492
19921
|
if (digestCanonicalJson(existing) !== digestCanonicalJson(journal)) {
|
|
19493
19922
|
throw new Error("MANCODE_REMOTE_WORKFLOW_REPAIR_JOURNAL_CONFLICT");
|
|
@@ -19503,10 +19932,10 @@ async function replaceJournal2(projectRoot, journal) {
|
|
|
19503
19932
|
async function requireJournal(projectRoot, operationId) {
|
|
19504
19933
|
try {
|
|
19505
19934
|
return parseJournal2(
|
|
19506
|
-
JSON.parse(await
|
|
19935
|
+
JSON.parse(await readFile29(gitRefWorkflowRepairJournalPath(projectRoot, operationId), "utf8"))
|
|
19507
19936
|
);
|
|
19508
19937
|
} catch (error) {
|
|
19509
|
-
if (error instanceof SyntaxError ||
|
|
19938
|
+
if (error instanceof SyntaxError || isNotFound25(error)) {
|
|
19510
19939
|
throw new Error("MANCODE_REMOTE_WORKFLOW_REPAIR_JOURNAL_NOT_FOUND");
|
|
19511
19940
|
}
|
|
19512
19941
|
throw error;
|
|
@@ -19522,44 +19951,44 @@ function metadataFromBundle(bundle) {
|
|
|
19522
19951
|
return parseWorkflowMetadata(artifact2.content);
|
|
19523
19952
|
}
|
|
19524
19953
|
function metadataPath2(projectRoot, taskRef) {
|
|
19525
|
-
return
|
|
19954
|
+
return path33.join(taskRootPath(projectRoot, taskRef), "metadata.json");
|
|
19526
19955
|
}
|
|
19527
19956
|
async function readSafeFile(target) {
|
|
19528
|
-
const before = await
|
|
19957
|
+
const before = await lstat17(target);
|
|
19529
19958
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
19530
19959
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
19531
19960
|
}
|
|
19532
|
-
const content = await
|
|
19533
|
-
const after = await
|
|
19961
|
+
const content = await readFile29(target, "utf8");
|
|
19962
|
+
const after = await lstat17(target);
|
|
19534
19963
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
19535
19964
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
19536
19965
|
}
|
|
19537
19966
|
return content;
|
|
19538
19967
|
}
|
|
19539
19968
|
async function atomicWrite(target, content) {
|
|
19540
|
-
const temporary =
|
|
19541
|
-
|
|
19542
|
-
`.${
|
|
19969
|
+
const temporary = path33.join(
|
|
19970
|
+
path33.dirname(target),
|
|
19971
|
+
`.${path33.basename(target)}.${process.pid}.${Date.now()}.tmp`
|
|
19543
19972
|
);
|
|
19544
|
-
await
|
|
19973
|
+
await writeFile29(temporary, content, { encoding: "utf8", flag: "wx" });
|
|
19545
19974
|
await replaceFileAtomically(temporary, target);
|
|
19546
19975
|
}
|
|
19547
19976
|
async function ensureJournalDirectory(projectRoot) {
|
|
19548
|
-
let current =
|
|
19977
|
+
let current = path33.resolve(projectRoot);
|
|
19549
19978
|
for (const segment of [".mancode", "local", "journals", "git-ref-workflow"]) {
|
|
19550
|
-
current =
|
|
19979
|
+
current = path33.join(current, segment);
|
|
19551
19980
|
try {
|
|
19552
|
-
await
|
|
19981
|
+
await mkdir26(current);
|
|
19553
19982
|
} catch (error) {
|
|
19554
|
-
if (!
|
|
19983
|
+
if (!isAlreadyExists21(error)) throw error;
|
|
19555
19984
|
}
|
|
19556
|
-
const entry = await
|
|
19985
|
+
const entry = await lstat17(current);
|
|
19557
19986
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
19558
19987
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
19559
19988
|
}
|
|
19560
19989
|
}
|
|
19561
19990
|
}
|
|
19562
|
-
function
|
|
19991
|
+
function positiveInteger4(value, label, allowZero = false) {
|
|
19563
19992
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < (allowZero ? 0 : 1)) {
|
|
19564
19993
|
throw new Error(`${label} is invalid`);
|
|
19565
19994
|
}
|
|
@@ -19578,15 +20007,15 @@ function serialize12(value) {
|
|
|
19578
20007
|
return `${JSON.stringify(value, null, 2)}
|
|
19579
20008
|
`;
|
|
19580
20009
|
}
|
|
19581
|
-
function
|
|
20010
|
+
function isAlreadyExists21(error) {
|
|
19582
20011
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
19583
20012
|
}
|
|
19584
|
-
function
|
|
20013
|
+
function isNotFound25(error) {
|
|
19585
20014
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
19586
20015
|
}
|
|
19587
20016
|
|
|
19588
20017
|
// src/commands/v3-support.ts
|
|
19589
|
-
import
|
|
20018
|
+
import path34 from "path";
|
|
19590
20019
|
|
|
19591
20020
|
// src/runtime/session-identity.ts
|
|
19592
20021
|
import { createHash as createHash7 } from "crypto";
|
|
@@ -19673,7 +20102,7 @@ var EXIT_V3_OK = 0;
|
|
|
19673
20102
|
var EXIT_V3_INVALID_ARGUMENT = 2;
|
|
19674
20103
|
var EXIT_V3_BLOCKED = 3;
|
|
19675
20104
|
async function readV3CommandProject(projectRoot) {
|
|
19676
|
-
const root =
|
|
20105
|
+
const root = path34.resolve(projectRoot);
|
|
19677
20106
|
const runtime = await readProjectRuntimeContext(root);
|
|
19678
20107
|
const store = new V3ContextStore(root);
|
|
19679
20108
|
return {
|
|
@@ -20381,19 +20810,19 @@ function parseExpectedRevision2(value) {
|
|
|
20381
20810
|
// src/commands/init.ts
|
|
20382
20811
|
import { promises as fs4 } from "fs";
|
|
20383
20812
|
import os from "os";
|
|
20384
|
-
import
|
|
20813
|
+
import path48 from "path";
|
|
20385
20814
|
import process5 from "process";
|
|
20386
20815
|
|
|
20387
20816
|
// src/installers/claude-code.ts
|
|
20388
20817
|
import {
|
|
20389
20818
|
access,
|
|
20390
|
-
mkdir as
|
|
20391
|
-
readFile as
|
|
20392
|
-
readdir as
|
|
20819
|
+
mkdir as mkdir28,
|
|
20820
|
+
readFile as readFile31,
|
|
20821
|
+
readdir as readdir15,
|
|
20393
20822
|
rm as rm13,
|
|
20394
|
-
writeFile as
|
|
20823
|
+
writeFile as writeFile31
|
|
20395
20824
|
} from "fs/promises";
|
|
20396
|
-
import
|
|
20825
|
+
import path36 from "path";
|
|
20397
20826
|
|
|
20398
20827
|
// src/templates/agents/scout.ts
|
|
20399
20828
|
var SCOUT_AGENT = {
|
|
@@ -21714,8 +22143,8 @@ ${spec.body}
|
|
|
21714
22143
|
}
|
|
21715
22144
|
|
|
21716
22145
|
// src/installers/common.ts
|
|
21717
|
-
import { mkdir as
|
|
21718
|
-
import
|
|
22146
|
+
import { mkdir as mkdir27, readFile as readFile30, stat as stat3, writeFile as writeFile30 } from "fs/promises";
|
|
22147
|
+
import path35 from "path";
|
|
21719
22148
|
|
|
21720
22149
|
// src/templates/defaults.ts
|
|
21721
22150
|
var DEFAULT_CONFIG = {
|
|
@@ -21750,50 +22179,50 @@ var EMPTY_STYLE_TOKENS = {
|
|
|
21750
22179
|
|
|
21751
22180
|
// src/installers/common.ts
|
|
21752
22181
|
async function installMancodeCore(projectRoot) {
|
|
21753
|
-
const mancodeDir =
|
|
21754
|
-
await
|
|
21755
|
-
await
|
|
21756
|
-
await
|
|
21757
|
-
await
|
|
22182
|
+
const mancodeDir = path35.join(projectRoot, ".mancode");
|
|
22183
|
+
await mkdir27(path35.join(mancodeDir, "hooks"), { recursive: true });
|
|
22184
|
+
await mkdir27(path35.join(mancodeDir, "aesthetics"), { recursive: true });
|
|
22185
|
+
await mkdir27(path35.join(mancodeDir, "logs"), { recursive: true });
|
|
22186
|
+
await mkdir27(path35.join(mancodeDir, "workflows"), { recursive: true });
|
|
21758
22187
|
await ensureTeamMemory(projectRoot);
|
|
21759
|
-
await
|
|
21760
|
-
const configPath =
|
|
22188
|
+
await mkdir27(path35.join(mancodeDir, "preseason-reports"), { recursive: true });
|
|
22189
|
+
const configPath = path35.join(mancodeDir, "config.json");
|
|
21761
22190
|
if (!await pathExists3(configPath)) {
|
|
21762
|
-
await
|
|
22191
|
+
await writeFile30(
|
|
21763
22192
|
configPath,
|
|
21764
22193
|
`${JSON.stringify(DEFAULT_CONFIG, null, 2)}
|
|
21765
22194
|
`,
|
|
21766
22195
|
"utf-8"
|
|
21767
22196
|
);
|
|
21768
22197
|
}
|
|
21769
|
-
await installHooks(
|
|
21770
|
-
const tokensPath =
|
|
22198
|
+
await installHooks(path35.join(mancodeDir, "hooks"));
|
|
22199
|
+
const tokensPath = path35.join(mancodeDir, "aesthetics", "style-tokens.json");
|
|
21771
22200
|
if (!await pathExists3(tokensPath)) {
|
|
21772
|
-
await
|
|
22201
|
+
await writeFile30(
|
|
21773
22202
|
tokensPath,
|
|
21774
22203
|
`${JSON.stringify(EMPTY_STYLE_TOKENS, null, 2)}
|
|
21775
22204
|
`,
|
|
21776
22205
|
"utf-8"
|
|
21777
22206
|
);
|
|
21778
22207
|
}
|
|
21779
|
-
const logPath =
|
|
22208
|
+
const logPath = path35.join(mancodeDir, "logs", "hooks.log");
|
|
21780
22209
|
if (!await pathExists3(logPath)) {
|
|
21781
|
-
await
|
|
22210
|
+
await writeFile30(logPath, "", "utf-8");
|
|
21782
22211
|
}
|
|
21783
22212
|
}
|
|
21784
22213
|
async function readTextIfExists(filePath) {
|
|
21785
22214
|
try {
|
|
21786
|
-
return await
|
|
22215
|
+
return await readFile30(filePath, "utf-8");
|
|
21787
22216
|
} catch (err) {
|
|
21788
22217
|
if (isNodeError2(err) && err.code === "ENOENT") return "";
|
|
21789
22218
|
throw err;
|
|
21790
22219
|
}
|
|
21791
22220
|
}
|
|
21792
22221
|
async function installHooks(hooksDir) {
|
|
21793
|
-
const sessionStartDst =
|
|
21794
|
-
await
|
|
21795
|
-
const userPromptDst =
|
|
21796
|
-
await
|
|
22222
|
+
const sessionStartDst = path35.join(hooksDir, "session-start.mjs");
|
|
22223
|
+
await writeFile30(sessionStartDst, SESSION_START_HOOK, "utf-8");
|
|
22224
|
+
const userPromptDst = path35.join(hooksDir, "user-prompt-submit.mjs");
|
|
22225
|
+
await writeFile30(userPromptDst, USER_PROMPT_SUBMIT_HOOK, "utf-8");
|
|
21797
22226
|
}
|
|
21798
22227
|
async function pathExists3(p) {
|
|
21799
22228
|
try {
|
|
@@ -21832,39 +22261,39 @@ var LEGACY_CLAUDE_SKILL_SETTINGS = {
|
|
|
21832
22261
|
};
|
|
21833
22262
|
var LEGACY_MVP2_SKILL_NAMES = ["mamba", "man8"];
|
|
21834
22263
|
async function validateClaudeCodeSettings(projectRoot) {
|
|
21835
|
-
await readClaudeSettings(
|
|
22264
|
+
await readClaudeSettings(path36.join(projectRoot, ".claude"));
|
|
21836
22265
|
}
|
|
21837
22266
|
async function installClaudeCode(projectRoot, options) {
|
|
21838
|
-
const claudeDir =
|
|
22267
|
+
const claudeDir = path36.join(projectRoot, ".claude");
|
|
21839
22268
|
const settings = await readClaudeSettings(claudeDir);
|
|
21840
22269
|
const force = options.force ?? false;
|
|
21841
22270
|
await validateClaudeWriteTargets(claudeDir, options.minimal ?? false, force);
|
|
21842
22271
|
await installMancodeCore(projectRoot);
|
|
21843
|
-
await
|
|
21844
|
-
await installSoloSkill(
|
|
22272
|
+
await mkdir28(path36.join(claudeDir, "skills"), { recursive: true });
|
|
22273
|
+
await installSoloSkill(path36.join(claudeDir, "skills"), force);
|
|
21845
22274
|
if (options.minimal) {
|
|
21846
|
-
await uninstallMvp2Skills(
|
|
22275
|
+
await uninstallMvp2Skills(path36.join(claudeDir, "skills"));
|
|
21847
22276
|
} else {
|
|
21848
|
-
await installMvp2Skills(
|
|
22277
|
+
await installMvp2Skills(path36.join(claudeDir, "skills"), force);
|
|
21849
22278
|
}
|
|
21850
22279
|
if (options.minimal) {
|
|
21851
|
-
await uninstallAgents(
|
|
22280
|
+
await uninstallAgents(path36.join(claudeDir, "agents"));
|
|
21852
22281
|
} else {
|
|
21853
|
-
await installAgents(
|
|
22282
|
+
await installAgents(path36.join(claudeDir, "agents"), force);
|
|
21854
22283
|
}
|
|
21855
22284
|
await updateClaudeSettings(claudeDir, settings);
|
|
21856
22285
|
await removeLegacyHookFiles(projectRoot);
|
|
21857
22286
|
}
|
|
21858
22287
|
async function validateClaudeWriteTargets(claudeDir, minimal, force) {
|
|
21859
22288
|
if (!force) return;
|
|
21860
|
-
const skillsDir =
|
|
22289
|
+
const skillsDir = path36.join(claudeDir, "skills");
|
|
21861
22290
|
await assertWritableClaudeSkill(skillsDir, "solo");
|
|
21862
22291
|
if (minimal) return;
|
|
21863
22292
|
for (const skill of MVP2_SKILLS) {
|
|
21864
22293
|
await assertWritableClaudeSkill(skillsDir, skill.name);
|
|
21865
22294
|
}
|
|
21866
22295
|
for (const agent of ALL_AGENTS) {
|
|
21867
|
-
const agentPath =
|
|
22296
|
+
const agentPath = path36.join(claudeDir, "agents", `${agent.name}.md`);
|
|
21868
22297
|
const existing = await readTextIfExists2(agentPath);
|
|
21869
22298
|
if (existing !== null && !isGeneratedClaudeAgent(existing, agent.name)) {
|
|
21870
22299
|
throw new Error(
|
|
@@ -21874,7 +22303,7 @@ async function validateClaudeWriteTargets(claudeDir, minimal, force) {
|
|
|
21874
22303
|
}
|
|
21875
22304
|
}
|
|
21876
22305
|
async function assertWritableClaudeSkill(skillsDir, modeName) {
|
|
21877
|
-
const skillPath =
|
|
22306
|
+
const skillPath = path36.join(skillsDir, modeName, "SKILL.md");
|
|
21878
22307
|
const existing = await readTextIfExists2(skillPath);
|
|
21879
22308
|
if (existing !== null && !isGeneratedClaudeSkill(existing, modeName)) {
|
|
21880
22309
|
throw new Error(
|
|
@@ -21883,10 +22312,10 @@ async function assertWritableClaudeSkill(skillsDir, modeName) {
|
|
|
21883
22312
|
}
|
|
21884
22313
|
}
|
|
21885
22314
|
async function removeLegacyHookFiles(projectRoot) {
|
|
21886
|
-
const hooksDir =
|
|
22315
|
+
const hooksDir = path36.join(projectRoot, ".mancode", "hooks");
|
|
21887
22316
|
await Promise.all([
|
|
21888
|
-
rm13(
|
|
21889
|
-
rm13(
|
|
22317
|
+
rm13(path36.join(hooksDir, "session-start.sh"), { force: true }),
|
|
22318
|
+
rm13(path36.join(hooksDir, "user-prompt-submit.sh"), { force: true })
|
|
21890
22319
|
]);
|
|
21891
22320
|
}
|
|
21892
22321
|
async function installSoloSkill(skillsDir, force) {
|
|
@@ -21922,8 +22351,8 @@ async function uninstallMvp2Skills(skillsDir) {
|
|
|
21922
22351
|
await removeManagedLegacyMvp2Skills(skillsDir);
|
|
21923
22352
|
}
|
|
21924
22353
|
async function installProjectSkill(skillsDir, skill, force = true) {
|
|
21925
|
-
const skillDir =
|
|
21926
|
-
const skillPath =
|
|
22354
|
+
const skillDir = path36.join(skillsDir, skill.name);
|
|
22355
|
+
const skillPath = path36.join(skillDir, "SKILL.md");
|
|
21927
22356
|
const existing = await readTextIfExists2(skillPath);
|
|
21928
22357
|
if (existing !== null && !force) {
|
|
21929
22358
|
return;
|
|
@@ -21933,24 +22362,24 @@ async function installProjectSkill(skillsDir, skill, force = true) {
|
|
|
21933
22362
|
`refusing to overwrite user-authored Claude Code skill: ${skillPath}`
|
|
21934
22363
|
);
|
|
21935
22364
|
}
|
|
21936
|
-
await
|
|
21937
|
-
await
|
|
22365
|
+
await mkdir28(skillDir, { recursive: true });
|
|
22366
|
+
await writeFile31(
|
|
21938
22367
|
skillPath,
|
|
21939
22368
|
addManagedMarker(renderSkill(skill), CLAUDE_SKILL_MANAGED_MARKER),
|
|
21940
22369
|
"utf-8"
|
|
21941
22370
|
);
|
|
21942
22371
|
}
|
|
21943
22372
|
async function removeLegacyFlatSkill(skillsDir, legacyName, modeName) {
|
|
21944
|
-
const legacyPath =
|
|
22373
|
+
const legacyPath = path36.join(skillsDir, `${legacyName}.md`);
|
|
21945
22374
|
const content = await readTextIfExists2(legacyPath);
|
|
21946
22375
|
if (content && isGeneratedClaudeSkill(content, modeName)) {
|
|
21947
22376
|
await rm13(legacyPath, { force: true });
|
|
21948
22377
|
}
|
|
21949
22378
|
}
|
|
21950
22379
|
async function installAgents(agentsDir, force) {
|
|
21951
|
-
await
|
|
22380
|
+
await mkdir28(agentsDir, { recursive: true });
|
|
21952
22381
|
for (const agent of ALL_AGENTS) {
|
|
21953
|
-
const agentPath =
|
|
22382
|
+
const agentPath = path36.join(agentsDir, `${agent.name}.md`);
|
|
21954
22383
|
if (!force) {
|
|
21955
22384
|
try {
|
|
21956
22385
|
await access(agentPath);
|
|
@@ -21968,12 +22397,12 @@ async function installAgents(agentsDir, force) {
|
|
|
21968
22397
|
renderAgent(agent),
|
|
21969
22398
|
CLAUDE_AGENT_MANAGED_MARKER
|
|
21970
22399
|
);
|
|
21971
|
-
await
|
|
22400
|
+
await writeFile31(agentPath, content, "utf-8");
|
|
21972
22401
|
}
|
|
21973
22402
|
}
|
|
21974
22403
|
async function uninstallAgents(agentsDir) {
|
|
21975
22404
|
for (const agent of ALL_AGENTS) {
|
|
21976
|
-
const agentPath =
|
|
22405
|
+
const agentPath = path36.join(agentsDir, `${agent.name}.md`);
|
|
21977
22406
|
const content = await readTextIfExists2(agentPath);
|
|
21978
22407
|
if (content && isGeneratedClaudeAgent(content, agent.name)) {
|
|
21979
22408
|
await rm13(agentPath, { force: true });
|
|
@@ -21981,8 +22410,8 @@ async function uninstallAgents(agentsDir) {
|
|
|
21981
22410
|
}
|
|
21982
22411
|
}
|
|
21983
22412
|
async function removeClaudeGeneratedContent(projectRoot) {
|
|
21984
|
-
const claudeDir =
|
|
21985
|
-
const skillsDir =
|
|
22413
|
+
const claudeDir = path36.join(projectRoot, ".claude");
|
|
22414
|
+
const skillsDir = path36.join(claudeDir, "skills");
|
|
21986
22415
|
for (const modeName of [
|
|
21987
22416
|
"solo",
|
|
21988
22417
|
...LEGACY_MVP2_SKILL_NAMES,
|
|
@@ -21991,11 +22420,11 @@ async function removeClaudeGeneratedContent(projectRoot) {
|
|
|
21991
22420
|
await removeGeneratedSkillDir(skillsDir, modeName);
|
|
21992
22421
|
await removeLegacyFlatSkill(skillsDir, `mancode-${modeName}`, modeName);
|
|
21993
22422
|
}
|
|
21994
|
-
await uninstallAgents(
|
|
22423
|
+
await uninstallAgents(path36.join(claudeDir, "agents"));
|
|
21995
22424
|
}
|
|
21996
22425
|
async function removeGeneratedSkillDir(skillsDir, modeName) {
|
|
21997
|
-
const skillDir =
|
|
21998
|
-
const skillPath =
|
|
22426
|
+
const skillDir = path36.join(skillsDir, modeName);
|
|
22427
|
+
const skillPath = path36.join(skillDir, "SKILL.md");
|
|
21999
22428
|
const content = await readTextIfExists2(skillPath);
|
|
22000
22429
|
if (!content || !isGeneratedClaudeSkill(content, modeName)) return;
|
|
22001
22430
|
await rm13(skillPath, { force: true });
|
|
@@ -22019,7 +22448,7 @@ ${marker}
|
|
|
22019
22448
|
}
|
|
22020
22449
|
async function readTextIfExists2(filePath) {
|
|
22021
22450
|
try {
|
|
22022
|
-
return await
|
|
22451
|
+
return await readFile31(filePath, "utf-8");
|
|
22023
22452
|
} catch (error) {
|
|
22024
22453
|
if (isNodeError3(error) && error.code === "ENOENT") return null;
|
|
22025
22454
|
throw error;
|
|
@@ -22027,16 +22456,16 @@ async function readTextIfExists2(filePath) {
|
|
|
22027
22456
|
}
|
|
22028
22457
|
async function removeIfEmpty(dir) {
|
|
22029
22458
|
try {
|
|
22030
|
-
if ((await
|
|
22459
|
+
if ((await readdir15(dir)).length === 0) {
|
|
22031
22460
|
await rm13(dir, { recursive: true, force: true });
|
|
22032
22461
|
}
|
|
22033
22462
|
} catch {
|
|
22034
22463
|
}
|
|
22035
22464
|
}
|
|
22036
22465
|
async function readClaudeSettings(claudeDir) {
|
|
22037
|
-
const settingsPath =
|
|
22466
|
+
const settingsPath = path36.join(claudeDir, "settings.json");
|
|
22038
22467
|
try {
|
|
22039
|
-
const raw = await
|
|
22468
|
+
const raw = await readFile31(settingsPath, "utf-8");
|
|
22040
22469
|
return JSON.parse(raw);
|
|
22041
22470
|
} catch (err) {
|
|
22042
22471
|
if (isNodeError3(err) && err.code === "ENOENT") {
|
|
@@ -22049,7 +22478,7 @@ async function readClaudeSettings(claudeDir) {
|
|
|
22049
22478
|
}
|
|
22050
22479
|
}
|
|
22051
22480
|
async function updateClaudeSettings(claudeDir, settings) {
|
|
22052
|
-
const settingsPath =
|
|
22481
|
+
const settingsPath = path36.join(claudeDir, "settings.json");
|
|
22053
22482
|
settings.hooks = settings.hooks || {};
|
|
22054
22483
|
settings.hooks.SessionStart = [
|
|
22055
22484
|
...normalizeHookGroups(settings.hooks.SessionStart),
|
|
@@ -22062,7 +22491,7 @@ async function updateClaudeSettings(claudeDir, settings) {
|
|
|
22062
22491
|
removeLegacyMancodeSkillSettings(settings);
|
|
22063
22492
|
const content = `${JSON.stringify(settings, null, 2)}
|
|
22064
22493
|
`;
|
|
22065
|
-
await
|
|
22494
|
+
await writeFile31(settingsPath, content, "utf-8");
|
|
22066
22495
|
}
|
|
22067
22496
|
function removeLegacyMancodeSkillSettings(settings) {
|
|
22068
22497
|
if (!settings.skills) return;
|
|
@@ -22147,12 +22576,12 @@ function isNodeError3(err) {
|
|
|
22147
22576
|
}
|
|
22148
22577
|
|
|
22149
22578
|
// src/installers/cursor.ts
|
|
22150
|
-
import { mkdir as
|
|
22151
|
-
import
|
|
22579
|
+
import { mkdir as mkdir30, readFile as readFile34, rm as rm15, writeFile as writeFile33 } from "fs/promises";
|
|
22580
|
+
import path39 from "path";
|
|
22152
22581
|
|
|
22153
22582
|
// src/installers/mode-skills.ts
|
|
22154
|
-
import { mkdir as
|
|
22155
|
-
import
|
|
22583
|
+
import { mkdir as mkdir29, readFile as readFile32, readdir as readdir16, rm as rm14, writeFile as writeFile32 } from "fs/promises";
|
|
22584
|
+
import path37 from "path";
|
|
22156
22585
|
var MODE_NAMES = [
|
|
22157
22586
|
"manba",
|
|
22158
22587
|
"man",
|
|
@@ -22210,10 +22639,10 @@ async function installCodexSkills(projectRoot, minimal) {
|
|
|
22210
22639
|
await removeCodexSkills(projectRoot);
|
|
22211
22640
|
return;
|
|
22212
22641
|
}
|
|
22213
|
-
const skillsDir =
|
|
22642
|
+
const skillsDir = path37.join(projectRoot, ".agents", "skills");
|
|
22214
22643
|
for (const mode of MODE_NAMES) {
|
|
22215
|
-
const modeDir =
|
|
22216
|
-
await
|
|
22644
|
+
const modeDir = path37.join(skillsDir, mode);
|
|
22645
|
+
await mkdir29(modeDir, { recursive: true });
|
|
22217
22646
|
const meta = MODE_META[mode];
|
|
22218
22647
|
const content = [
|
|
22219
22648
|
"---",
|
|
@@ -22227,7 +22656,7 @@ async function installCodexSkills(projectRoot, minimal) {
|
|
|
22227
22656
|
""
|
|
22228
22657
|
].join("\n");
|
|
22229
22658
|
await writeManagedSkill(
|
|
22230
|
-
|
|
22659
|
+
path37.join(modeDir, "SKILL.md"),
|
|
22231
22660
|
content,
|
|
22232
22661
|
CODEX_SKILL_MANAGED_MARKER,
|
|
22233
22662
|
"Codex",
|
|
@@ -22241,10 +22670,10 @@ async function installZcodeSkills(projectRoot, minimal) {
|
|
|
22241
22670
|
await removeZcodeSkills(projectRoot);
|
|
22242
22671
|
return;
|
|
22243
22672
|
}
|
|
22244
|
-
const skillsDir =
|
|
22673
|
+
const skillsDir = path37.join(projectRoot, ".agents", "skills");
|
|
22245
22674
|
for (const mode of MODE_NAMES) {
|
|
22246
|
-
const modeDir =
|
|
22247
|
-
await
|
|
22675
|
+
const modeDir = path37.join(skillsDir, mode);
|
|
22676
|
+
await mkdir29(modeDir, { recursive: true });
|
|
22248
22677
|
const meta = MODE_META[mode];
|
|
22249
22678
|
const content = [
|
|
22250
22679
|
"---",
|
|
@@ -22258,7 +22687,7 @@ async function installZcodeSkills(projectRoot, minimal) {
|
|
|
22258
22687
|
""
|
|
22259
22688
|
].join("\n");
|
|
22260
22689
|
await writeManagedSkill(
|
|
22261
|
-
|
|
22690
|
+
path37.join(modeDir, "SKILL.md"),
|
|
22262
22691
|
content,
|
|
22263
22692
|
ZCODE_SKILL_MANAGED_MARKER,
|
|
22264
22693
|
"ZCode",
|
|
@@ -22272,8 +22701,8 @@ async function installCursorCommands(projectRoot, minimal) {
|
|
|
22272
22701
|
await removeCursorCommands(projectRoot);
|
|
22273
22702
|
return;
|
|
22274
22703
|
}
|
|
22275
|
-
const commandsDir =
|
|
22276
|
-
await
|
|
22704
|
+
const commandsDir = path37.join(projectRoot, ".cursor", "commands");
|
|
22705
|
+
await mkdir29(commandsDir, { recursive: true });
|
|
22277
22706
|
for (const mode of MODE_NAMES) {
|
|
22278
22707
|
const meta = MODE_META[mode];
|
|
22279
22708
|
const content = [
|
|
@@ -22287,22 +22716,22 @@ async function installCursorCommands(projectRoot, minimal) {
|
|
|
22287
22716
|
""
|
|
22288
22717
|
].join("\n");
|
|
22289
22718
|
await writeManagedModeFile(
|
|
22290
|
-
|
|
22719
|
+
path37.join(commandsDir, `${mode}.md`),
|
|
22291
22720
|
content,
|
|
22292
22721
|
mode,
|
|
22293
22722
|
"Cursor"
|
|
22294
22723
|
);
|
|
22295
22724
|
}
|
|
22296
|
-
await removeManagedModeFile(
|
|
22297
|
-
await removeLegacyGeneratedModeFile(
|
|
22725
|
+
await removeManagedModeFile(path37.join(commandsDir, "mamba.md"), "mamba");
|
|
22726
|
+
await removeLegacyGeneratedModeFile(path37.join(commandsDir, "man8.md"));
|
|
22298
22727
|
}
|
|
22299
22728
|
async function installCopilotPrompts(projectRoot, minimal) {
|
|
22300
22729
|
if (minimal) {
|
|
22301
22730
|
await removeCopilotPrompts(projectRoot);
|
|
22302
22731
|
return;
|
|
22303
22732
|
}
|
|
22304
|
-
const promptsDir =
|
|
22305
|
-
await
|
|
22733
|
+
const promptsDir = path37.join(projectRoot, ".github", "prompts");
|
|
22734
|
+
await mkdir29(promptsDir, { recursive: true });
|
|
22306
22735
|
for (const mode of MODE_NAMES) {
|
|
22307
22736
|
const meta = MODE_META[mode];
|
|
22308
22737
|
const content = [
|
|
@@ -22317,33 +22746,33 @@ async function installCopilotPrompts(projectRoot, minimal) {
|
|
|
22317
22746
|
""
|
|
22318
22747
|
].join("\n");
|
|
22319
22748
|
await writeManagedModeFile(
|
|
22320
|
-
|
|
22749
|
+
path37.join(promptsDir, `${mode}.prompt.md`),
|
|
22321
22750
|
content,
|
|
22322
22751
|
mode,
|
|
22323
22752
|
"GitHub Copilot"
|
|
22324
22753
|
);
|
|
22325
22754
|
}
|
|
22326
22755
|
await removeManagedModeFile(
|
|
22327
|
-
|
|
22756
|
+
path37.join(promptsDir, "mamba.prompt.md"),
|
|
22328
22757
|
"mamba"
|
|
22329
22758
|
);
|
|
22330
|
-
await removeLegacyGeneratedModeFile(
|
|
22759
|
+
await removeLegacyGeneratedModeFile(path37.join(promptsDir, "man8.prompt.md"));
|
|
22331
22760
|
}
|
|
22332
22761
|
async function removeCodexSkills(projectRoot) {
|
|
22333
22762
|
if (!await platformNeedsSharedSkills(projectRoot, "zcode")) {
|
|
22334
22763
|
await cleanManagedSkills(
|
|
22335
|
-
|
|
22764
|
+
path37.join(projectRoot, ".agents", "skills"),
|
|
22336
22765
|
MANCODE_AGENT_SKILL_MARKERS
|
|
22337
22766
|
);
|
|
22338
22767
|
}
|
|
22339
|
-
await cleanManagedSkills(
|
|
22768
|
+
await cleanManagedSkills(path37.join(projectRoot, ".codex", "skills"), [
|
|
22340
22769
|
CODEX_SKILL_MANAGED_MARKER
|
|
22341
22770
|
]);
|
|
22342
22771
|
}
|
|
22343
22772
|
async function cleanManagedSkills(skillsDir, markers) {
|
|
22344
22773
|
for (const mode of [...MODE_NAMES, ...LEGACY_MODE_NAMES]) {
|
|
22345
|
-
const modeDir =
|
|
22346
|
-
const skillPath =
|
|
22774
|
+
const modeDir = path37.join(skillsDir, mode);
|
|
22775
|
+
const skillPath = path37.join(modeDir, "SKILL.md");
|
|
22347
22776
|
if (await isManagedByAnyMarker(skillPath, markers)) {
|
|
22348
22777
|
await rm14(skillPath, { force: true });
|
|
22349
22778
|
await removeIfEmpty2(modeDir);
|
|
@@ -22354,17 +22783,17 @@ async function cleanManagedSkills(skillsDir, markers) {
|
|
|
22354
22783
|
async function removeZcodeSkills(projectRoot) {
|
|
22355
22784
|
if (!await platformNeedsSharedSkills(projectRoot, "codex")) {
|
|
22356
22785
|
await cleanManagedSkills(
|
|
22357
|
-
|
|
22786
|
+
path37.join(projectRoot, ".agents", "skills"),
|
|
22358
22787
|
MANCODE_AGENT_SKILL_MARKERS
|
|
22359
22788
|
);
|
|
22360
22789
|
}
|
|
22361
|
-
await cleanManagedSkills(
|
|
22790
|
+
await cleanManagedSkills(path37.join(projectRoot, ".zcode", "skills"), [
|
|
22362
22791
|
ZCODE_SKILL_MANAGED_MARKER
|
|
22363
22792
|
]);
|
|
22364
22793
|
}
|
|
22365
22794
|
async function removeCursorCommands(projectRoot) {
|
|
22366
22795
|
for (const mode of [...MODE_NAMES, ...LEGACY_MODE_NAMES]) {
|
|
22367
|
-
const filePath =
|
|
22796
|
+
const filePath = path37.join(
|
|
22368
22797
|
projectRoot,
|
|
22369
22798
|
".cursor",
|
|
22370
22799
|
"commands",
|
|
@@ -22376,7 +22805,7 @@ async function removeCursorCommands(projectRoot) {
|
|
|
22376
22805
|
}
|
|
22377
22806
|
async function removeCopilotPrompts(projectRoot) {
|
|
22378
22807
|
for (const mode of [...MODE_NAMES, ...LEGACY_MODE_NAMES]) {
|
|
22379
|
-
const filePath =
|
|
22808
|
+
const filePath = path37.join(
|
|
22380
22809
|
projectRoot,
|
|
22381
22810
|
".github",
|
|
22382
22811
|
"prompts",
|
|
@@ -22393,7 +22822,7 @@ async function writeManagedModeFile(filePath, content, mode, platformLabel) {
|
|
|
22393
22822
|
`refusing to overwrite user-authored ${platformLabel} mode file: ${filePath}`
|
|
22394
22823
|
);
|
|
22395
22824
|
}
|
|
22396
|
-
await
|
|
22825
|
+
await writeFile32(filePath, content, "utf-8");
|
|
22397
22826
|
}
|
|
22398
22827
|
async function removeManagedModeFile(filePath, mode) {
|
|
22399
22828
|
const content = await readTextIfExists3(filePath);
|
|
@@ -22412,8 +22841,8 @@ function isGeneratedModeFile(content, mode) {
|
|
|
22412
22841
|
}
|
|
22413
22842
|
async function removeLegacyManagedSkills(skillsDir, markers) {
|
|
22414
22843
|
for (const mode of LEGACY_MODE_NAMES) {
|
|
22415
|
-
const modeDir =
|
|
22416
|
-
const skillPath =
|
|
22844
|
+
const modeDir = path37.join(skillsDir, mode);
|
|
22845
|
+
const skillPath = path37.join(modeDir, "SKILL.md");
|
|
22417
22846
|
const content = await readTextIfExists3(skillPath);
|
|
22418
22847
|
if (content && markers.some((marker) => content.includes(marker))) {
|
|
22419
22848
|
await rm14(skillPath, { force: true });
|
|
@@ -22423,7 +22852,7 @@ async function removeLegacyManagedSkills(skillsDir, markers) {
|
|
|
22423
22852
|
}
|
|
22424
22853
|
async function removeIfEmpty2(dir) {
|
|
22425
22854
|
try {
|
|
22426
|
-
const entries = await
|
|
22855
|
+
const entries = await readdir16(dir);
|
|
22427
22856
|
if (entries.length === 0) {
|
|
22428
22857
|
await rm14(dir, { recursive: true, force: true });
|
|
22429
22858
|
}
|
|
@@ -22437,7 +22866,7 @@ async function writeManagedSkill(skillPath, content, marker, platformLabel, reco
|
|
|
22437
22866
|
`refusing to overwrite user-authored ${platformLabel} skill: ${skillPath}`
|
|
22438
22867
|
);
|
|
22439
22868
|
}
|
|
22440
|
-
await
|
|
22869
|
+
await writeFile32(skillPath, content, "utf-8");
|
|
22441
22870
|
}
|
|
22442
22871
|
async function isManagedByAnyMarker(skillPath, markers) {
|
|
22443
22872
|
const content = await readTextIfExists3(skillPath);
|
|
@@ -22445,8 +22874,8 @@ async function isManagedByAnyMarker(skillPath, markers) {
|
|
|
22445
22874
|
}
|
|
22446
22875
|
async function platformNeedsSharedSkills(projectRoot, platform) {
|
|
22447
22876
|
try {
|
|
22448
|
-
const raw = await
|
|
22449
|
-
|
|
22877
|
+
const raw = await readFile32(
|
|
22878
|
+
path37.join(projectRoot, ".mancode", "config.json"),
|
|
22450
22879
|
"utf-8"
|
|
22451
22880
|
);
|
|
22452
22881
|
const config = JSON.parse(raw);
|
|
@@ -22465,7 +22894,7 @@ function isRecord5(value) {
|
|
|
22465
22894
|
}
|
|
22466
22895
|
async function readTextIfExists3(filePath) {
|
|
22467
22896
|
try {
|
|
22468
|
-
return await
|
|
22897
|
+
return await readFile32(filePath, "utf-8");
|
|
22469
22898
|
} catch (error) {
|
|
22470
22899
|
if (isNodeError4(error) && error.code === "ENOENT") return null;
|
|
22471
22900
|
throw error;
|
|
@@ -22584,18 +23013,18 @@ var MODE_META = {
|
|
|
22584
23013
|
};
|
|
22585
23014
|
|
|
22586
23015
|
// src/installers/shared-content.ts
|
|
22587
|
-
import { readFile as
|
|
22588
|
-
import
|
|
23016
|
+
import { readFile as readFile33 } from "fs/promises";
|
|
23017
|
+
import path38 from "path";
|
|
22589
23018
|
async function generateSharedContent(projectRoot, options) {
|
|
22590
23019
|
const [state, tokens, profile] = await Promise.all([
|
|
22591
23020
|
readJson(
|
|
22592
|
-
|
|
23021
|
+
path38.join(projectRoot, ".mancode", "state.json")
|
|
22593
23022
|
),
|
|
22594
23023
|
readJson(
|
|
22595
|
-
|
|
23024
|
+
path38.join(projectRoot, ".mancode", "aesthetics", "style-tokens.json")
|
|
22596
23025
|
),
|
|
22597
23026
|
readJson(
|
|
22598
|
-
|
|
23027
|
+
path38.join(projectRoot, ".mancode", "project-profile.json")
|
|
22599
23028
|
)
|
|
22600
23029
|
]);
|
|
22601
23030
|
const currentProfile = options.projectProfile ?? profile;
|
|
@@ -22725,7 +23154,7 @@ function renderPlatformDowngrade(options) {
|
|
|
22725
23154
|
}
|
|
22726
23155
|
async function readJson(filePath) {
|
|
22727
23156
|
try {
|
|
22728
|
-
return JSON.parse(await
|
|
23157
|
+
return JSON.parse(await readFile33(filePath, "utf-8"));
|
|
22729
23158
|
} catch {
|
|
22730
23159
|
return null;
|
|
22731
23160
|
}
|
|
@@ -22770,8 +23199,8 @@ var MANCODE_CURSOR_RULE_FILES = [
|
|
|
22770
23199
|
];
|
|
22771
23200
|
async function installCursor(projectRoot, options) {
|
|
22772
23201
|
await installMancodeCore(projectRoot);
|
|
22773
|
-
const rulesDir =
|
|
22774
|
-
await
|
|
23202
|
+
const rulesDir = path39.join(projectRoot, ".cursor", "rules");
|
|
23203
|
+
await mkdir30(rulesDir, { recursive: true });
|
|
22775
23204
|
const sharedContent = await generateSharedContent(projectRoot, {
|
|
22776
23205
|
platform: "cursor",
|
|
22777
23206
|
displayName: "Cursor",
|
|
@@ -22859,14 +23288,14 @@ async function writeRule(rulesDir, fileName, description, alwaysApply, body) {
|
|
|
22859
23288
|
|
|
22860
23289
|
${body.trim()}
|
|
22861
23290
|
`;
|
|
22862
|
-
const rulePath =
|
|
23291
|
+
const rulePath = path39.join(rulesDir, fileName);
|
|
22863
23292
|
const existing = await readTextIfExists4(rulePath);
|
|
22864
23293
|
if (existing !== null && !isGeneratedCursorRule(existing, fileName)) {
|
|
22865
23294
|
throw new Error(
|
|
22866
23295
|
`refusing to overwrite user-authored Cursor rule: ${rulePath}`
|
|
22867
23296
|
);
|
|
22868
23297
|
}
|
|
22869
|
-
await
|
|
23298
|
+
await writeFile33(
|
|
22870
23299
|
rulePath,
|
|
22871
23300
|
content.replace("---\n\n", `---
|
|
22872
23301
|
|
|
@@ -22880,23 +23309,23 @@ async function removeAdvancedRules(rulesDir) {
|
|
|
22880
23309
|
for (const fileName of MANCODE_CURSOR_ADVANCED_RULE_FILES) {
|
|
22881
23310
|
await removeGeneratedCursorRule(rulesDir, fileName);
|
|
22882
23311
|
}
|
|
22883
|
-
await removeLegacyCursorRules(
|
|
23312
|
+
await removeLegacyCursorRules(path39.dirname(path39.dirname(rulesDir)));
|
|
22884
23313
|
}
|
|
22885
23314
|
async function removeCursorGeneratedRules(projectRoot) {
|
|
22886
|
-
const rulesDir =
|
|
23315
|
+
const rulesDir = path39.join(projectRoot, ".cursor", "rules");
|
|
22887
23316
|
for (const fileName of MANCODE_CURSOR_RULE_FILES) {
|
|
22888
23317
|
await removeGeneratedCursorRule(rulesDir, fileName);
|
|
22889
23318
|
}
|
|
22890
23319
|
await removeLegacyCursorRules(projectRoot);
|
|
22891
23320
|
}
|
|
22892
23321
|
async function removeLegacyCursorRules(projectRoot) {
|
|
22893
|
-
const rulesDir =
|
|
23322
|
+
const rulesDir = path39.join(projectRoot, ".cursor", "rules");
|
|
22894
23323
|
for (const fileName of MANCODE_CURSOR_LEGACY_RULE_FILES) {
|
|
22895
23324
|
await removeGeneratedCursorRule(rulesDir, fileName);
|
|
22896
23325
|
}
|
|
22897
23326
|
}
|
|
22898
23327
|
async function removeGeneratedCursorRule(rulesDir, fileName) {
|
|
22899
|
-
const rulePath =
|
|
23328
|
+
const rulePath = path39.join(rulesDir, fileName);
|
|
22900
23329
|
const content = await readTextIfExists4(rulePath);
|
|
22901
23330
|
if (content && isGeneratedCursorRule(content, fileName)) {
|
|
22902
23331
|
await rm15(rulePath, { force: true });
|
|
@@ -22918,7 +23347,7 @@ function isGeneratedCursorRule(content, fileName) {
|
|
|
22918
23347
|
}
|
|
22919
23348
|
async function readTextIfExists4(filePath) {
|
|
22920
23349
|
try {
|
|
22921
|
-
return await
|
|
23350
|
+
return await readFile34(filePath, "utf-8");
|
|
22922
23351
|
} catch (error) {
|
|
22923
23352
|
if (isNodeError5(error) && error.code === "ENOENT") return null;
|
|
22924
23353
|
throw error;
|
|
@@ -22972,16 +23401,16 @@ function renderManpsRule() {
|
|
|
22972
23401
|
|
|
22973
23402
|
// src/installers/platform-status.ts
|
|
22974
23403
|
import { promises as fs } from "fs";
|
|
22975
|
-
import
|
|
23404
|
+
import path41 from "path";
|
|
22976
23405
|
|
|
22977
23406
|
// src/installers/zcode.ts
|
|
22978
|
-
import { writeFile as
|
|
22979
|
-
import
|
|
23407
|
+
import { writeFile as writeFile34 } from "fs/promises";
|
|
23408
|
+
import path40 from "path";
|
|
22980
23409
|
var ZCODE_MANCODE_START_MARKER = "<!-- mancode:zcode:start -->";
|
|
22981
23410
|
var ZCODE_MANCODE_END_MARKER = "<!-- mancode:zcode:end -->";
|
|
22982
23411
|
async function installZcode(projectRoot, options) {
|
|
22983
23412
|
await installMancodeCore(projectRoot);
|
|
22984
|
-
const agentsPath =
|
|
23413
|
+
const agentsPath = path40.join(projectRoot, "AGENTS.md");
|
|
22985
23414
|
const existing = await readTextIfExists(agentsPath);
|
|
22986
23415
|
const sharedContent = await generateSharedContent(projectRoot, {
|
|
22987
23416
|
platform: "zcode",
|
|
@@ -23006,7 +23435,7 @@ async function installZcode(projectRoot, options) {
|
|
|
23006
23435
|
sharedContent.trim(),
|
|
23007
23436
|
ZCODE_MANCODE_END_MARKER
|
|
23008
23437
|
].join("\n");
|
|
23009
|
-
await
|
|
23438
|
+
await writeFile34(
|
|
23010
23439
|
agentsPath,
|
|
23011
23440
|
replaceManagedBlock(
|
|
23012
23441
|
existing,
|
|
@@ -23036,13 +23465,13 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23036
23465
|
if (platform === "claude-code") {
|
|
23037
23466
|
const [hasSoloSkill, registered, hasHookFiles] = await Promise.all([
|
|
23038
23467
|
fileMatches(
|
|
23039
|
-
|
|
23468
|
+
path41.join(rootDir, ".claude", "skills", "solo", "SKILL.md"),
|
|
23040
23469
|
(content) => isGeneratedClaudeSkill(content, "solo")
|
|
23041
23470
|
),
|
|
23042
23471
|
claudeHooksRegistered(rootDir),
|
|
23043
23472
|
pathsExist([
|
|
23044
|
-
|
|
23045
|
-
|
|
23473
|
+
path41.join(rootDir, ".mancode", "hooks", "session-start.mjs"),
|
|
23474
|
+
path41.join(rootDir, ".mancode", "hooks", "user-prompt-submit.mjs")
|
|
23046
23475
|
])
|
|
23047
23476
|
]);
|
|
23048
23477
|
const present = hasSoloSkill && registered && hasHookFiles;
|
|
@@ -23058,7 +23487,7 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23058
23487
|
if (platform === "cursor") {
|
|
23059
23488
|
const hasCoreRules = await allManagedSkills(
|
|
23060
23489
|
MANCODE_CURSOR_CORE_RULE_FILES.map(
|
|
23061
|
-
(file) =>
|
|
23490
|
+
(file) => path41.join(rootDir, ".cursor", "rules", file)
|
|
23062
23491
|
),
|
|
23063
23492
|
[CURSOR_RULE_MANAGED_MARKER]
|
|
23064
23493
|
);
|
|
@@ -23073,13 +23502,13 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23073
23502
|
const [hasRules, hasCommands] = await Promise.all([
|
|
23074
23503
|
allManagedSkills(
|
|
23075
23504
|
MANCODE_CURSOR_RULE_FILES.map(
|
|
23076
|
-
(file) =>
|
|
23505
|
+
(file) => path41.join(rootDir, ".cursor", "rules", file)
|
|
23077
23506
|
),
|
|
23078
23507
|
[CURSOR_RULE_MANAGED_MARKER]
|
|
23079
23508
|
),
|
|
23080
23509
|
allManagedSkills(
|
|
23081
23510
|
MODE_NAMES.map(
|
|
23082
|
-
(mode) =>
|
|
23511
|
+
(mode) => path41.join(rootDir, ".cursor", "commands", `${mode}.md`)
|
|
23083
23512
|
),
|
|
23084
23513
|
[MODE_FILE_MANAGED_MARKER]
|
|
23085
23514
|
)
|
|
@@ -23092,7 +23521,7 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23092
23521
|
};
|
|
23093
23522
|
}
|
|
23094
23523
|
if (platform === "codex") {
|
|
23095
|
-
const hasBlock2 = await fileHasManagedBlock(
|
|
23524
|
+
const hasBlock2 = await fileHasManagedBlock(path41.join(rootDir, "AGENTS.md"));
|
|
23096
23525
|
if (!hasBlock2) {
|
|
23097
23526
|
return {
|
|
23098
23527
|
present: false,
|
|
@@ -23109,9 +23538,9 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23109
23538
|
readyDetail: "managed block present"
|
|
23110
23539
|
};
|
|
23111
23540
|
}
|
|
23112
|
-
const skillsDir =
|
|
23541
|
+
const skillsDir = path41.join(rootDir, ".agents", "skills");
|
|
23113
23542
|
const hasSkills = await allManagedSkills(
|
|
23114
|
-
MODE_NAMES.map((mode) =>
|
|
23543
|
+
MODE_NAMES.map((mode) => path41.join(skillsDir, mode, "SKILL.md")),
|
|
23115
23544
|
MANCODE_AGENT_SKILL_MARKERS
|
|
23116
23545
|
);
|
|
23117
23546
|
return {
|
|
@@ -23123,7 +23552,7 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23123
23552
|
}
|
|
23124
23553
|
if (platform === "zcode") {
|
|
23125
23554
|
const hasBlock2 = await fileHasManagedBlock(
|
|
23126
|
-
|
|
23555
|
+
path41.join(rootDir, "AGENTS.md"),
|
|
23127
23556
|
ZCODE_MANCODE_START_MARKER,
|
|
23128
23557
|
ZCODE_MANCODE_END_MARKER
|
|
23129
23558
|
);
|
|
@@ -23143,9 +23572,9 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23143
23572
|
readyDetail: "managed block present"
|
|
23144
23573
|
};
|
|
23145
23574
|
}
|
|
23146
|
-
const skillsDir =
|
|
23575
|
+
const skillsDir = path41.join(rootDir, ".agents", "skills");
|
|
23147
23576
|
const hasSkills = await allManagedSkills(
|
|
23148
|
-
MODE_NAMES.map((mode) =>
|
|
23577
|
+
MODE_NAMES.map((mode) => path41.join(skillsDir, mode, "SKILL.md")),
|
|
23149
23578
|
MANCODE_AGENT_SKILL_MARKERS
|
|
23150
23579
|
);
|
|
23151
23580
|
return {
|
|
@@ -23156,7 +23585,7 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23156
23585
|
};
|
|
23157
23586
|
}
|
|
23158
23587
|
const hasBlock = await fileHasManagedBlock(
|
|
23159
|
-
|
|
23588
|
+
path41.join(rootDir, ".github", "copilot-instructions.md")
|
|
23160
23589
|
);
|
|
23161
23590
|
if (!hasBlock) {
|
|
23162
23591
|
return {
|
|
@@ -23167,9 +23596,9 @@ async function checkPlatformReadiness(rootDir, platform) {
|
|
|
23167
23596
|
};
|
|
23168
23597
|
}
|
|
23169
23598
|
if (!await isPlatformMinimal(rootDir, "copilot")) {
|
|
23170
|
-
const promptsDir =
|
|
23599
|
+
const promptsDir = path41.join(rootDir, ".github", "prompts");
|
|
23171
23600
|
const hasPrompts = await allManagedSkills(
|
|
23172
|
-
MODE_NAMES.map((mode) =>
|
|
23601
|
+
MODE_NAMES.map((mode) => path41.join(promptsDir, `${mode}.prompt.md`)),
|
|
23173
23602
|
[MODE_FILE_MANAGED_MARKER]
|
|
23174
23603
|
);
|
|
23175
23604
|
return {
|
|
@@ -23202,13 +23631,13 @@ async function allManagedSkills(paths, markers) {
|
|
|
23202
23631
|
async function claudeFullContentReady(rootDir) {
|
|
23203
23632
|
const skillChecks = MVP2_SKILLS.map(
|
|
23204
23633
|
(skill) => fileMatches(
|
|
23205
|
-
|
|
23634
|
+
path41.join(rootDir, ".claude", "skills", skill.name, "SKILL.md"),
|
|
23206
23635
|
(content) => isGeneratedClaudeSkill(content, skill.name)
|
|
23207
23636
|
)
|
|
23208
23637
|
);
|
|
23209
23638
|
const agentChecks = ALL_AGENTS.map(
|
|
23210
23639
|
(agent) => fileMatches(
|
|
23211
|
-
|
|
23640
|
+
path41.join(rootDir, ".claude", "agents", `${agent.name}.md`),
|
|
23212
23641
|
(content) => isGeneratedClaudeAgent(content, agent.name)
|
|
23213
23642
|
)
|
|
23214
23643
|
);
|
|
@@ -23236,7 +23665,7 @@ async function fileHasAnyMarker(filePath, needles) {
|
|
|
23236
23665
|
async function isPlatformMinimal(rootDir, platform) {
|
|
23237
23666
|
try {
|
|
23238
23667
|
const raw = await fs.readFile(
|
|
23239
|
-
|
|
23668
|
+
path41.join(rootDir, ".mancode", "config.json"),
|
|
23240
23669
|
"utf-8"
|
|
23241
23670
|
);
|
|
23242
23671
|
const config = JSON.parse(raw);
|
|
@@ -23258,7 +23687,7 @@ async function fileHasManagedBlock(filePath, startMarker = DEFAULT_MANCODE_START
|
|
|
23258
23687
|
async function claudeHooksRegistered(rootDir) {
|
|
23259
23688
|
try {
|
|
23260
23689
|
const raw = await fs.readFile(
|
|
23261
|
-
|
|
23690
|
+
path41.join(rootDir, ".claude", "settings.json"),
|
|
23262
23691
|
"utf-8"
|
|
23263
23692
|
);
|
|
23264
23693
|
const settings = JSON.parse(raw);
|
|
@@ -23299,11 +23728,11 @@ function isRecord6(value) {
|
|
|
23299
23728
|
}
|
|
23300
23729
|
|
|
23301
23730
|
// src/installers/codex.ts
|
|
23302
|
-
import { writeFile as
|
|
23303
|
-
import
|
|
23731
|
+
import { writeFile as writeFile35 } from "fs/promises";
|
|
23732
|
+
import path42 from "path";
|
|
23304
23733
|
async function installCodex(projectRoot, options) {
|
|
23305
23734
|
await installMancodeCore(projectRoot);
|
|
23306
|
-
const agentsPath =
|
|
23735
|
+
const agentsPath = path42.join(projectRoot, "AGENTS.md");
|
|
23307
23736
|
const existing = await readTextIfExists(agentsPath);
|
|
23308
23737
|
const sharedContent = await generateSharedContent(projectRoot, {
|
|
23309
23738
|
platform: "codex",
|
|
@@ -23328,18 +23757,18 @@ async function installCodex(projectRoot, options) {
|
|
|
23328
23757
|
sharedContent.trim(),
|
|
23329
23758
|
DEFAULT_MANCODE_END_MARKER
|
|
23330
23759
|
].join("\n");
|
|
23331
|
-
await
|
|
23760
|
+
await writeFile35(agentsPath, replaceManagedBlock(existing, block), "utf-8");
|
|
23332
23761
|
await installCodexSkills(projectRoot, options.minimal ?? false);
|
|
23333
23762
|
}
|
|
23334
23763
|
|
|
23335
23764
|
// src/installers/copilot.ts
|
|
23336
|
-
import { mkdir as
|
|
23337
|
-
import
|
|
23765
|
+
import { mkdir as mkdir31, writeFile as writeFile36 } from "fs/promises";
|
|
23766
|
+
import path43 from "path";
|
|
23338
23767
|
async function installCopilot(projectRoot, options) {
|
|
23339
23768
|
await installMancodeCore(projectRoot);
|
|
23340
|
-
const githubDir =
|
|
23341
|
-
await
|
|
23342
|
-
const instructionsPath =
|
|
23769
|
+
const githubDir = path43.join(projectRoot, ".github");
|
|
23770
|
+
await mkdir31(githubDir, { recursive: true });
|
|
23771
|
+
const instructionsPath = path43.join(githubDir, "copilot-instructions.md");
|
|
23343
23772
|
const existing = await readTextIfExists(instructionsPath);
|
|
23344
23773
|
const sharedContent = await generateSharedContent(projectRoot, {
|
|
23345
23774
|
platform: "copilot",
|
|
@@ -23367,7 +23796,7 @@ async function installCopilot(projectRoot, options) {
|
|
|
23367
23796
|
sections.push("", renderCopilotPromptConventions());
|
|
23368
23797
|
}
|
|
23369
23798
|
sections.push(DEFAULT_MANCODE_END_MARKER);
|
|
23370
|
-
await
|
|
23799
|
+
await writeFile36(
|
|
23371
23800
|
instructionsPath,
|
|
23372
23801
|
replaceManagedBlock(existing, sections.join("\n")),
|
|
23373
23802
|
"utf-8"
|
|
@@ -23463,12 +23892,12 @@ function isPlatformName(platform) {
|
|
|
23463
23892
|
}
|
|
23464
23893
|
|
|
23465
23894
|
// src/system/detect-team.ts
|
|
23466
|
-
import { execFile as
|
|
23895
|
+
import { execFile as execFile6 } from "child_process";
|
|
23467
23896
|
import { access as access2 } from "fs/promises";
|
|
23468
|
-
import
|
|
23897
|
+
import path44 from "path";
|
|
23469
23898
|
import process2 from "process";
|
|
23470
|
-
import { promisify as
|
|
23471
|
-
var execFileAsync =
|
|
23899
|
+
import { promisify as promisify6 } from "util";
|
|
23900
|
+
var execFileAsync = promisify6(execFile6);
|
|
23472
23901
|
var NO_TEAM = {
|
|
23473
23902
|
isTeam: false,
|
|
23474
23903
|
contributors: 1,
|
|
@@ -23575,7 +24004,7 @@ async function anyPathExists(projectRoot, candidates) {
|
|
|
23575
24004
|
const results = await Promise.all(
|
|
23576
24005
|
candidates.map(async (candidate) => {
|
|
23577
24006
|
try {
|
|
23578
|
-
await access2(
|
|
24007
|
+
await access2(path44.join(projectRoot, candidate));
|
|
23579
24008
|
return true;
|
|
23580
24009
|
} catch {
|
|
23581
24010
|
return false;
|
|
@@ -23597,10 +24026,10 @@ function emptySignals(isGitRepository) {
|
|
|
23597
24026
|
}
|
|
23598
24027
|
|
|
23599
24028
|
// src/system/detect.ts
|
|
23600
|
-
import { execFile as
|
|
24029
|
+
import { execFile as execFile7 } from "child_process";
|
|
23601
24030
|
import process3 from "process";
|
|
23602
|
-
import { promisify as
|
|
23603
|
-
var execFileAsync2 =
|
|
24031
|
+
import { promisify as promisify7 } from "util";
|
|
24032
|
+
var execFileAsync2 = promisify7(execFile7);
|
|
23604
24033
|
async function detectSystemDeps(env = process3.env) {
|
|
23605
24034
|
try {
|
|
23606
24035
|
await execFileAsync2("git", ["--version"], {
|
|
@@ -23616,7 +24045,7 @@ async function detectSystemDeps(env = process3.env) {
|
|
|
23616
24045
|
// src/system/init-onboarding.ts
|
|
23617
24046
|
import { execFileSync } from "child_process";
|
|
23618
24047
|
import { promises as fs2 } from "fs";
|
|
23619
|
-
import
|
|
24048
|
+
import path45 from "path";
|
|
23620
24049
|
import process4 from "process";
|
|
23621
24050
|
import { stdin, stdout } from "process";
|
|
23622
24051
|
import { createInterface } from "readline/promises";
|
|
@@ -23721,7 +24150,7 @@ async function detectPlatformHints(rootDir, environment = process4.env) {
|
|
|
23721
24150
|
hints.add("copilot");
|
|
23722
24151
|
const exists = async (relative) => {
|
|
23723
24152
|
try {
|
|
23724
|
-
await fs2.access(
|
|
24153
|
+
await fs2.access(path45.join(rootDir, relative));
|
|
23725
24154
|
return true;
|
|
23726
24155
|
} catch {
|
|
23727
24156
|
return false;
|
|
@@ -23797,7 +24226,7 @@ function createTerminalPrompter() {
|
|
|
23797
24226
|
|
|
23798
24227
|
// src/system/scan-aesthetics.ts
|
|
23799
24228
|
import { promises as fs3 } from "fs";
|
|
23800
|
-
import
|
|
24229
|
+
import path46 from "path";
|
|
23801
24230
|
var MAX_COMPONENT_SCAN_DEPTH = 12;
|
|
23802
24231
|
var MAX_COMPONENT_FILES = 2e3;
|
|
23803
24232
|
async function scanAesthetics(projectRoot, uiLibrary = null) {
|
|
@@ -23833,7 +24262,7 @@ async function scanAesthetics(projectRoot, uiLibrary = null) {
|
|
|
23833
24262
|
} else if (await hasTailwindDep(projectRoot) || uiLibrary) {
|
|
23834
24263
|
matchLevel = "low";
|
|
23835
24264
|
}
|
|
23836
|
-
if (uiLibrary && await pathExists5(
|
|
24265
|
+
if (uiLibrary && await pathExists5(path46.join(projectRoot, "package.json"))) {
|
|
23837
24266
|
sourceFiles.push("package.json");
|
|
23838
24267
|
}
|
|
23839
24268
|
sourceFiles.push(...cssScan.sourceFiles);
|
|
@@ -23858,7 +24287,7 @@ async function findTailwindConfig(projectRoot) {
|
|
|
23858
24287
|
"tailwind.config.mjs"
|
|
23859
24288
|
];
|
|
23860
24289
|
for (const name of candidates) {
|
|
23861
|
-
const absPath =
|
|
24290
|
+
const absPath = path46.join(projectRoot, name);
|
|
23862
24291
|
if (await pathExists5(absPath)) {
|
|
23863
24292
|
return { absPath, relPath: name };
|
|
23864
24293
|
}
|
|
@@ -24085,7 +24514,7 @@ async function scanComponents(projectRoot) {
|
|
|
24085
24514
|
const names = /* @__PURE__ */ new Set();
|
|
24086
24515
|
let visitedFiles = 0;
|
|
24087
24516
|
for (const relRoot of roots) {
|
|
24088
|
-
const absRoot =
|
|
24517
|
+
const absRoot = path46.join(projectRoot, relRoot);
|
|
24089
24518
|
if (!await pathExists5(absRoot)) continue;
|
|
24090
24519
|
visitedFiles = await collectComponentNames(absRoot, names, 0, visitedFiles);
|
|
24091
24520
|
if (visitedFiles >= MAX_COMPONENT_FILES) break;
|
|
@@ -24105,7 +24534,7 @@ async function collectComponentNames(dir, names, depth, visitedFiles) {
|
|
|
24105
24534
|
}
|
|
24106
24535
|
for (const entry of entries) {
|
|
24107
24536
|
if (fileCount >= MAX_COMPONENT_FILES) return fileCount;
|
|
24108
|
-
const abs =
|
|
24537
|
+
const abs = path46.join(dir, entry);
|
|
24109
24538
|
let info;
|
|
24110
24539
|
try {
|
|
24111
24540
|
info = await fs3.lstat(abs);
|
|
@@ -24126,7 +24555,7 @@ async function collectComponentNames(dir, names, depth, visitedFiles) {
|
|
|
24126
24555
|
""
|
|
24127
24556
|
);
|
|
24128
24557
|
if (base === "index") {
|
|
24129
|
-
base =
|
|
24558
|
+
base = path46.basename(dir);
|
|
24130
24559
|
}
|
|
24131
24560
|
if (base.startsWith(".")) continue;
|
|
24132
24561
|
const componentName = toPascalCase(base);
|
|
@@ -24148,7 +24577,7 @@ async function scanCssVariables(projectRoot) {
|
|
|
24148
24577
|
const variables = {};
|
|
24149
24578
|
const sourceFiles = [];
|
|
24150
24579
|
for (const relPath of candidates) {
|
|
24151
|
-
const absPath =
|
|
24580
|
+
const absPath = path46.join(projectRoot, relPath);
|
|
24152
24581
|
if (!await pathExists5(absPath)) continue;
|
|
24153
24582
|
const content = await fs3.readFile(absPath, "utf-8");
|
|
24154
24583
|
const found = extractCssVariables(content);
|
|
@@ -24194,7 +24623,7 @@ function toPascalCase(value) {
|
|
|
24194
24623
|
async function hasTailwindDep(projectRoot) {
|
|
24195
24624
|
try {
|
|
24196
24625
|
const raw = await fs3.readFile(
|
|
24197
|
-
|
|
24626
|
+
path46.join(projectRoot, "package.json"),
|
|
24198
24627
|
"utf-8"
|
|
24199
24628
|
);
|
|
24200
24629
|
const pkg = JSON.parse(raw);
|
|
@@ -24219,15 +24648,15 @@ async function pathExists5(p) {
|
|
|
24219
24648
|
|
|
24220
24649
|
// src/context/greenfield-init.ts
|
|
24221
24650
|
import {
|
|
24222
|
-
lstat as
|
|
24223
|
-
mkdir as
|
|
24224
|
-
readFile as
|
|
24651
|
+
lstat as lstat18,
|
|
24652
|
+
mkdir as mkdir32,
|
|
24653
|
+
readFile as readFile35,
|
|
24225
24654
|
rename as rename8,
|
|
24226
24655
|
rm as rm16,
|
|
24227
|
-
writeFile as
|
|
24656
|
+
writeFile as writeFile37
|
|
24228
24657
|
} from "fs/promises";
|
|
24229
|
-
import
|
|
24230
|
-
var JOURNAL_RELATIVE_DIRECTORY =
|
|
24658
|
+
import path47 from "path";
|
|
24659
|
+
var JOURNAL_RELATIVE_DIRECTORY = path47.join(
|
|
24231
24660
|
"local",
|
|
24232
24661
|
"runtime",
|
|
24233
24662
|
"initialization"
|
|
@@ -24250,9 +24679,9 @@ async function stageGreenfieldInitialization(input) {
|
|
|
24250
24679
|
normalized.operationId
|
|
24251
24680
|
);
|
|
24252
24681
|
try {
|
|
24253
|
-
await
|
|
24682
|
+
await mkdir32(stagingRoot);
|
|
24254
24683
|
} catch (error) {
|
|
24255
|
-
if (
|
|
24684
|
+
if (isAlreadyExists22(error)) {
|
|
24256
24685
|
throw new Error("MANCODE_GREENFIELD_STAGING_EXISTS");
|
|
24257
24686
|
}
|
|
24258
24687
|
throw error;
|
|
@@ -24271,7 +24700,7 @@ async function stageGreenfieldInitialization(input) {
|
|
|
24271
24700
|
operationId: normalized.operationId,
|
|
24272
24701
|
workspaceId: normalized.workspaceId,
|
|
24273
24702
|
state: "staged",
|
|
24274
|
-
stagingDirectoryName:
|
|
24703
|
+
stagingDirectoryName: path47.basename(stagingRoot),
|
|
24275
24704
|
targetDirectoryName: ".mancode",
|
|
24276
24705
|
manifestDigest: digestCanonicalJson(manifest),
|
|
24277
24706
|
configDigest: digestCanonicalJson(config),
|
|
@@ -24301,7 +24730,7 @@ async function stageGreenfieldInitialization(input) {
|
|
|
24301
24730
|
return journal;
|
|
24302
24731
|
}
|
|
24303
24732
|
async function publishGreenfieldInitialization(input) {
|
|
24304
|
-
const root =
|
|
24733
|
+
const root = path47.resolve(input.projectRoot);
|
|
24305
24734
|
assertUlid(input.operationId, "greenfield operationId");
|
|
24306
24735
|
const stagingRoot = greenfieldStagingPath(root, input.operationId);
|
|
24307
24736
|
const targetRoot = greenfieldTargetPath(root);
|
|
@@ -24330,10 +24759,10 @@ async function initializeGreenfield(input, publication) {
|
|
|
24330
24759
|
}
|
|
24331
24760
|
function greenfieldStagingPath(projectRoot, operationId) {
|
|
24332
24761
|
assertUlid(operationId, "greenfield operationId");
|
|
24333
|
-
return
|
|
24762
|
+
return path47.join(path47.resolve(projectRoot), `.mancode.init-${operationId}`);
|
|
24334
24763
|
}
|
|
24335
24764
|
function greenfieldTargetPath(projectRoot) {
|
|
24336
|
-
return
|
|
24765
|
+
return path47.join(path47.resolve(projectRoot), ".mancode");
|
|
24337
24766
|
}
|
|
24338
24767
|
function parseGreenfieldInitializationJournal(value) {
|
|
24339
24768
|
assertRecord(value, "greenfield initialization journal");
|
|
@@ -24436,7 +24865,7 @@ async function finishPublishedInitialization(input, stagedJournal) {
|
|
|
24436
24865
|
activatedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString()
|
|
24437
24866
|
};
|
|
24438
24867
|
assertSchemaManifestTransition(manifest, activeManifest);
|
|
24439
|
-
await writeJson(
|
|
24868
|
+
await writeJson(path47.join(targetRoot, "schema.json"), activeManifest);
|
|
24440
24869
|
throwIfOperationCrashInjected(
|
|
24441
24870
|
"greenfield_initialize",
|
|
24442
24871
|
"activate-v3-manifest"
|
|
@@ -24452,46 +24881,46 @@ async function finishPublishedInitialization(input, stagedJournal) {
|
|
|
24452
24881
|
}
|
|
24453
24882
|
async function writeGreenfieldLayout(stagingRoot, manifest, config, policy, projectFacts, journal) {
|
|
24454
24883
|
await Promise.all([
|
|
24455
|
-
|
|
24456
|
-
|
|
24884
|
+
mkdir32(path47.join(stagingRoot, "shared", "context"), { recursive: true }),
|
|
24885
|
+
mkdir32(path47.join(stagingRoot, "shared", "memory", "decisions"), {
|
|
24457
24886
|
recursive: true
|
|
24458
24887
|
}),
|
|
24459
|
-
|
|
24888
|
+
mkdir32(path47.join(stagingRoot, "shared", "team", "actors"), {
|
|
24460
24889
|
recursive: true
|
|
24461
24890
|
}),
|
|
24462
|
-
|
|
24891
|
+
mkdir32(path47.join(stagingRoot, "shared", "team", "handoffs"), {
|
|
24463
24892
|
recursive: true
|
|
24464
24893
|
}),
|
|
24465
|
-
|
|
24894
|
+
mkdir32(path47.join(stagingRoot, "shared", "team", "events"), {
|
|
24466
24895
|
recursive: true
|
|
24467
24896
|
}),
|
|
24468
|
-
|
|
24897
|
+
mkdir32(path47.join(stagingRoot, "shared", "team", "transport"), {
|
|
24469
24898
|
recursive: true
|
|
24470
24899
|
}),
|
|
24471
|
-
|
|
24472
|
-
|
|
24900
|
+
mkdir32(path47.join(stagingRoot, "local", "sessions"), { recursive: true }),
|
|
24901
|
+
mkdir32(path47.join(stagingRoot, JOURNAL_RELATIVE_DIRECTORY), {
|
|
24473
24902
|
recursive: true
|
|
24474
24903
|
}),
|
|
24475
|
-
|
|
24476
|
-
|
|
24477
|
-
|
|
24478
|
-
|
|
24479
|
-
|
|
24480
|
-
|
|
24904
|
+
mkdir32(path47.join(stagingRoot, "local", "workflows"), { recursive: true }),
|
|
24905
|
+
mkdir32(path47.join(stagingRoot, "local", "overlays"), { recursive: true }),
|
|
24906
|
+
mkdir32(path47.join(stagingRoot, "local", "quarantine"), { recursive: true }),
|
|
24907
|
+
mkdir32(path47.join(stagingRoot, "local", "publish"), { recursive: true }),
|
|
24908
|
+
mkdir32(path47.join(stagingRoot, "local", "cache"), { recursive: true }),
|
|
24909
|
+
mkdir32(path47.join(stagingRoot, "runtime", "non-git", journal.workspaceId), {
|
|
24481
24910
|
recursive: true
|
|
24482
24911
|
})
|
|
24483
24912
|
]);
|
|
24484
24913
|
await Promise.all([
|
|
24485
|
-
writeJson(
|
|
24486
|
-
writeJson(
|
|
24487
|
-
writeJson(
|
|
24914
|
+
writeJson(path47.join(stagingRoot, "schema.json"), manifest),
|
|
24915
|
+
writeJson(path47.join(stagingRoot, "shared", "config.json"), config),
|
|
24916
|
+
writeJson(path47.join(stagingRoot, "shared", "team", "policy.json"), policy),
|
|
24488
24917
|
writeJson(
|
|
24489
|
-
|
|
24918
|
+
path47.join(stagingRoot, "shared", "context", "project.json"),
|
|
24490
24919
|
projectFacts
|
|
24491
24920
|
),
|
|
24492
24921
|
writeJson(journalPath2(stagingRoot, journal.operationId), journal),
|
|
24493
|
-
|
|
24494
|
-
|
|
24922
|
+
writeFile37(
|
|
24923
|
+
path47.join(stagingRoot, ".gitignore"),
|
|
24495
24924
|
`${V3_IGNORE.join("\n")}
|
|
24496
24925
|
`,
|
|
24497
24926
|
{ encoding: "utf8", flag: "wx" }
|
|
@@ -24500,14 +24929,14 @@ async function writeGreenfieldLayout(stagingRoot, manifest, config, policy, proj
|
|
|
24500
24929
|
}
|
|
24501
24930
|
async function readGreenfieldJournal(root, operationId) {
|
|
24502
24931
|
try {
|
|
24503
|
-
const raw = await
|
|
24932
|
+
const raw = await readFile35(journalPath2(root, operationId), "utf8");
|
|
24504
24933
|
const journal = parseGreenfieldInitializationJournal(JSON.parse(raw));
|
|
24505
24934
|
if (journal.operationId !== operationId) {
|
|
24506
24935
|
throw new Error("MANCODE_GREENFIELD_JOURNAL_CORRUPT");
|
|
24507
24936
|
}
|
|
24508
24937
|
return journal;
|
|
24509
24938
|
} catch (error) {
|
|
24510
|
-
if (error instanceof SyntaxError ||
|
|
24939
|
+
if (error instanceof SyntaxError || isNotFound26(error)) {
|
|
24511
24940
|
throw new Error("MANCODE_GREENFIELD_JOURNAL_CORRUPT");
|
|
24512
24941
|
}
|
|
24513
24942
|
throw error;
|
|
@@ -24516,10 +24945,10 @@ async function readGreenfieldJournal(root, operationId) {
|
|
|
24516
24945
|
async function readManifest(root) {
|
|
24517
24946
|
try {
|
|
24518
24947
|
return parseSchemaManifest(
|
|
24519
|
-
JSON.parse(await
|
|
24948
|
+
JSON.parse(await readFile35(path47.join(root, "schema.json"), "utf8"))
|
|
24520
24949
|
);
|
|
24521
24950
|
} catch (error) {
|
|
24522
|
-
if (error instanceof SyntaxError ||
|
|
24951
|
+
if (error instanceof SyntaxError || isNotFound26(error)) {
|
|
24523
24952
|
throw new Error("MANCODE_GREENFIELD_REPAIR_REQUIRED");
|
|
24524
24953
|
}
|
|
24525
24954
|
throw error;
|
|
@@ -24554,7 +24983,7 @@ async function readConfig(root) {
|
|
|
24554
24983
|
try {
|
|
24555
24984
|
config = parseProjectConfig(
|
|
24556
24985
|
JSON.parse(
|
|
24557
|
-
await
|
|
24986
|
+
await readFile35(path47.join(root, "shared", "config.json"), "utf8")
|
|
24558
24987
|
)
|
|
24559
24988
|
);
|
|
24560
24989
|
} catch (error) {
|
|
@@ -24570,8 +24999,8 @@ async function readPolicy(root) {
|
|
|
24570
24999
|
try {
|
|
24571
25000
|
policy = parseTeamPolicy(
|
|
24572
25001
|
JSON.parse(
|
|
24573
|
-
await
|
|
24574
|
-
|
|
25002
|
+
await readFile35(
|
|
25003
|
+
path47.join(root, "shared", "team", "policy.json"),
|
|
24575
25004
|
"utf8"
|
|
24576
25005
|
)
|
|
24577
25006
|
)
|
|
@@ -24588,14 +25017,14 @@ async function readProjectFactsAt(root) {
|
|
|
24588
25017
|
try {
|
|
24589
25018
|
return parseProjectFacts(
|
|
24590
25019
|
JSON.parse(
|
|
24591
|
-
await
|
|
24592
|
-
|
|
25020
|
+
await readFile35(
|
|
25021
|
+
path47.join(root, "shared", "context", "project.json"),
|
|
24593
25022
|
"utf8"
|
|
24594
25023
|
)
|
|
24595
25024
|
)
|
|
24596
25025
|
);
|
|
24597
25026
|
} catch (error) {
|
|
24598
|
-
if (error instanceof SyntaxError ||
|
|
25027
|
+
if (error instanceof SyntaxError || isNotFound26(error)) {
|
|
24599
25028
|
throw new Error("MANCODE_GREENFIELD_REPAIR_REQUIRED");
|
|
24600
25029
|
}
|
|
24601
25030
|
throw error;
|
|
@@ -24628,7 +25057,7 @@ function normalizeInput(input) {
|
|
|
24628
25057
|
parseSchemaManifest(manifest);
|
|
24629
25058
|
return {
|
|
24630
25059
|
...input,
|
|
24631
|
-
projectRoot:
|
|
25060
|
+
projectRoot: path47.resolve(input.projectRoot),
|
|
24632
25061
|
projectConfig: config,
|
|
24633
25062
|
teamPolicy: policy,
|
|
24634
25063
|
projectFacts: input.projectFacts === void 0 ? void 0 : parseProjectFacts(input.projectFacts)
|
|
@@ -24677,16 +25106,16 @@ function initializationProjectFacts(input, now) {
|
|
|
24677
25106
|
}
|
|
24678
25107
|
function journalPath2(root, operationId) {
|
|
24679
25108
|
assertUlid(operationId, "greenfield operationId");
|
|
24680
|
-
return
|
|
25109
|
+
return path47.join(root, JOURNAL_RELATIVE_DIRECTORY, `${operationId}.json`);
|
|
24681
25110
|
}
|
|
24682
25111
|
async function writeJson(target, value) {
|
|
24683
|
-
const directory =
|
|
24684
|
-
await
|
|
24685
|
-
const temporary =
|
|
25112
|
+
const directory = path47.dirname(target);
|
|
25113
|
+
await mkdir32(directory, { recursive: true });
|
|
25114
|
+
const temporary = path47.join(
|
|
24686
25115
|
directory,
|
|
24687
|
-
`.${
|
|
25116
|
+
`.${path47.basename(target)}.${process.pid}.${Date.now()}.tmp`
|
|
24688
25117
|
);
|
|
24689
|
-
await
|
|
25118
|
+
await writeFile37(temporary, `${JSON.stringify(value, null, 2)}
|
|
24690
25119
|
`, {
|
|
24691
25120
|
encoding: "utf8",
|
|
24692
25121
|
flag: "wx"
|
|
@@ -24710,16 +25139,16 @@ function isState(value) {
|
|
|
24710
25139
|
}
|
|
24711
25140
|
async function lstatOrNull4(target) {
|
|
24712
25141
|
try {
|
|
24713
|
-
return await
|
|
25142
|
+
return await lstat18(target);
|
|
24714
25143
|
} catch (error) {
|
|
24715
|
-
if (
|
|
25144
|
+
if (isNotFound26(error)) return null;
|
|
24716
25145
|
throw error;
|
|
24717
25146
|
}
|
|
24718
25147
|
}
|
|
24719
|
-
function
|
|
25148
|
+
function isNotFound26(error) {
|
|
24720
25149
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
24721
25150
|
}
|
|
24722
|
-
function
|
|
25151
|
+
function isAlreadyExists22(error) {
|
|
24723
25152
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
24724
25153
|
}
|
|
24725
25154
|
|
|
@@ -24813,9 +25242,9 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
24813
25242
|
return EXIT_INIT_FAILED;
|
|
24814
25243
|
}
|
|
24815
25244
|
const authority = resolveInitAuthority(options);
|
|
24816
|
-
const mancodeDir =
|
|
24817
|
-
const stateFile =
|
|
24818
|
-
const v3SchemaFile =
|
|
25245
|
+
const mancodeDir = path48.join(rootDir, ".mancode");
|
|
25246
|
+
const stateFile = path48.join(mancodeDir, "state.json");
|
|
25247
|
+
const v3SchemaFile = path48.join(mancodeDir, "schema.json");
|
|
24819
25248
|
const wasInitialized = await pathExists6(stateFile);
|
|
24820
25249
|
let mutationSnapshots = [];
|
|
24821
25250
|
let directorySnapshots = [];
|
|
@@ -24883,7 +25312,7 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
24883
25312
|
}
|
|
24884
25313
|
return initializeV3(rootDir, options);
|
|
24885
25314
|
}
|
|
24886
|
-
const isGitRepo = await pathExists6(
|
|
25315
|
+
const isGitRepo = await pathExists6(path48.join(rootDir, ".git"));
|
|
24887
25316
|
const hasManifest = await hasProjectManifest(rootDir);
|
|
24888
25317
|
let isGenericProject = false;
|
|
24889
25318
|
if (!isGitRepo && !hasManifest) {
|
|
@@ -25001,8 +25430,8 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
25001
25430
|
const managedFiles = getInitManagedFilePaths(rootDir, selectedPlatforms);
|
|
25002
25431
|
mutationSnapshots = await snapshotFiles(managedFiles);
|
|
25003
25432
|
directorySnapshots = await snapshotDirectories(managedFiles, [
|
|
25004
|
-
|
|
25005
|
-
|
|
25433
|
+
path48.join(mancodeDir, "workflows"),
|
|
25434
|
+
path48.join(mancodeDir, "preseason-reports")
|
|
25006
25435
|
]);
|
|
25007
25436
|
const team = await detectTeamStatus(rootDir);
|
|
25008
25437
|
const platformMinimal = Object.fromEntries(
|
|
@@ -25063,7 +25492,7 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
25063
25492
|
`;
|
|
25064
25493
|
await fs4.writeFile(stateFile, stateContent, "utf-8");
|
|
25065
25494
|
await fs4.writeFile(
|
|
25066
|
-
|
|
25495
|
+
path48.join(mancodeDir, "project-profile.json"),
|
|
25067
25496
|
`${JSON.stringify(profile, null, 2)}
|
|
25068
25497
|
`,
|
|
25069
25498
|
"utf-8"
|
|
@@ -25100,7 +25529,7 @@ async function init(rootDir = process5.cwd(), options = {}) {
|
|
|
25100
25529
|
)
|
|
25101
25530
|
);
|
|
25102
25531
|
const tokens = await scanAesthetics(rootDir, uiLibrary);
|
|
25103
|
-
const tokensPath =
|
|
25532
|
+
const tokensPath = path48.join(
|
|
25104
25533
|
mancodeDir,
|
|
25105
25534
|
"aesthetics",
|
|
25106
25535
|
"style-tokens.json"
|
|
@@ -25264,7 +25693,7 @@ async function initializeV3(rootDir, options) {
|
|
|
25264
25693
|
);
|
|
25265
25694
|
return EXIT_INIT_FAILED;
|
|
25266
25695
|
}
|
|
25267
|
-
const schemaPath =
|
|
25696
|
+
const schemaPath = path48.join(rootDir, ".mancode", "schema.json");
|
|
25268
25697
|
let existingV3 = false;
|
|
25269
25698
|
if (await pathExists6(schemaPath)) {
|
|
25270
25699
|
try {
|
|
@@ -25356,7 +25785,7 @@ function printV3InitError(error) {
|
|
|
25356
25785
|
}
|
|
25357
25786
|
}
|
|
25358
25787
|
async function updateConfigOptions(mancodeDir, patch, preserveInstalledPlatforms) {
|
|
25359
|
-
const configPath =
|
|
25788
|
+
const configPath = path48.join(mancodeDir, "config.json");
|
|
25360
25789
|
let config = {};
|
|
25361
25790
|
try {
|
|
25362
25791
|
config = JSON.parse(await fs4.readFile(configPath, "utf-8"));
|
|
@@ -25389,7 +25818,7 @@ async function updateConfigOptions(mancodeDir, patch, preserveInstalledPlatforms
|
|
|
25389
25818
|
async function readExistingInitPreferences(mancodeDir) {
|
|
25390
25819
|
try {
|
|
25391
25820
|
const config = JSON.parse(
|
|
25392
|
-
await fs4.readFile(
|
|
25821
|
+
await fs4.readFile(path48.join(mancodeDir, "config.json"), "utf-8")
|
|
25393
25822
|
);
|
|
25394
25823
|
const preferences = {
|
|
25395
25824
|
platforms: Array.isArray(config.platforms) ? config.platforms.filter(
|
|
@@ -25455,13 +25884,13 @@ async function selectInitPlatforms(input) {
|
|
|
25455
25884
|
}
|
|
25456
25885
|
async function hasProjectManifest(rootDir) {
|
|
25457
25886
|
for (const name of PROJECT_MANIFESTS) {
|
|
25458
|
-
if (await pathExists6(
|
|
25887
|
+
if (await pathExists6(path48.join(rootDir, name))) return true;
|
|
25459
25888
|
}
|
|
25460
25889
|
return false;
|
|
25461
25890
|
}
|
|
25462
25891
|
async function canInitializeGenericProject(rootDir) {
|
|
25463
|
-
const resolved =
|
|
25464
|
-
if (resolved ===
|
|
25892
|
+
const resolved = path48.resolve(rootDir);
|
|
25893
|
+
if (resolved === path48.parse(resolved).root || resolved === path48.resolve(os.homedir())) {
|
|
25465
25894
|
return { ok: false, reason: "unsafe" };
|
|
25466
25895
|
}
|
|
25467
25896
|
try {
|
|
@@ -25475,11 +25904,11 @@ async function canInitializeGenericProject(rootDir) {
|
|
|
25475
25904
|
}
|
|
25476
25905
|
}
|
|
25477
25906
|
async function validateV3CliProjectBoundary(rootDir, options, locale, legacyInitialized) {
|
|
25478
|
-
const isGitRepo = await pathExists6(
|
|
25907
|
+
const isGitRepo = await pathExists6(path48.join(rootDir, ".git"));
|
|
25479
25908
|
const hasManifest = await hasProjectManifest(rootDir);
|
|
25480
25909
|
if (isGitRepo || hasManifest) return null;
|
|
25481
25910
|
const v3Initialized = await pathExists6(
|
|
25482
|
-
|
|
25911
|
+
path48.join(rootDir, ".mancode", "schema.json")
|
|
25483
25912
|
);
|
|
25484
25913
|
const legacyAuthorityPresent = legacyInitialized || (await scanLegacyAuthority(rootDir)).authorityPresent;
|
|
25485
25914
|
const genericSafety = await canInitializeGenericProject(rootDir);
|
|
@@ -25608,7 +26037,7 @@ function getInitManagedFilePaths(rootDir, platforms) {
|
|
|
25608
26037
|
files.push(`.github/prompts/${mode}.prompt.md`);
|
|
25609
26038
|
}
|
|
25610
26039
|
}
|
|
25611
|
-
return [...new Set(files.map((file) =>
|
|
26040
|
+
return [...new Set(files.map((file) => path48.join(rootDir, file)))];
|
|
25612
26041
|
}
|
|
25613
26042
|
async function snapshotFiles(filePaths) {
|
|
25614
26043
|
return Promise.all(
|
|
@@ -25627,10 +26056,10 @@ async function snapshotFiles(filePaths) {
|
|
|
25627
26056
|
async function snapshotDirectories(filePaths, additionalDirectories = []) {
|
|
25628
26057
|
const directories = new Set(additionalDirectories);
|
|
25629
26058
|
for (const filePath of filePaths) {
|
|
25630
|
-
let current =
|
|
25631
|
-
while (current !==
|
|
26059
|
+
let current = path48.dirname(filePath);
|
|
26060
|
+
while (current !== path48.dirname(current)) {
|
|
25632
26061
|
directories.add(current);
|
|
25633
|
-
current =
|
|
26062
|
+
current = path48.dirname(current);
|
|
25634
26063
|
}
|
|
25635
26064
|
}
|
|
25636
26065
|
return Promise.all(
|
|
@@ -25646,7 +26075,7 @@ async function restoreFiles(snapshots) {
|
|
|
25646
26075
|
await fs4.rm(snapshot.filePath, { force: true });
|
|
25647
26076
|
continue;
|
|
25648
26077
|
}
|
|
25649
|
-
await fs4.mkdir(
|
|
26078
|
+
await fs4.mkdir(path48.dirname(snapshot.filePath), { recursive: true });
|
|
25650
26079
|
await fs4.writeFile(snapshot.filePath, snapshot.content, "utf-8");
|
|
25651
26080
|
}
|
|
25652
26081
|
}
|
|
@@ -25713,15 +26142,15 @@ async function pathExists6(p) {
|
|
|
25713
26142
|
|
|
25714
26143
|
// src/commands/install.ts
|
|
25715
26144
|
import { promises as fs5 } from "fs";
|
|
25716
|
-
import
|
|
26145
|
+
import path49 from "path";
|
|
25717
26146
|
import process6 from "process";
|
|
25718
26147
|
var EXIT_OK2 = 0;
|
|
25719
26148
|
var EXIT_NOT_INITIALIZED = 1;
|
|
25720
26149
|
var EXIT_UNSUPPORTED_PLATFORM = 2;
|
|
25721
26150
|
var EXIT_INSTALL_FAILED = 3;
|
|
25722
26151
|
async function install(rootDir = process6.cwd(), platform = "claude-code", options = {}) {
|
|
25723
|
-
const stateFile =
|
|
25724
|
-
const v3SchemaFile =
|
|
26152
|
+
const stateFile = path49.join(rootDir, ".mancode", "state.json");
|
|
26153
|
+
const v3SchemaFile = path49.join(rootDir, ".mancode", "schema.json");
|
|
25725
26154
|
if (await pathExists7(v3SchemaFile)) {
|
|
25726
26155
|
return installV3(rootDir, platform, options);
|
|
25727
26156
|
}
|
|
@@ -25864,7 +26293,7 @@ function printUnsupportedPlatform(platform) {
|
|
|
25864
26293
|
}
|
|
25865
26294
|
}
|
|
25866
26295
|
async function readConfig2(rootDir) {
|
|
25867
|
-
const configPath =
|
|
26296
|
+
const configPath = path49.join(rootDir, ".mancode", "config.json");
|
|
25868
26297
|
try {
|
|
25869
26298
|
const raw = await fs5.readFile(configPath, "utf-8");
|
|
25870
26299
|
return { config: JSON.parse(raw), valid: true };
|
|
@@ -25879,7 +26308,7 @@ function isNodeError7(err) {
|
|
|
25879
26308
|
return err instanceof Error && "code" in err;
|
|
25880
26309
|
}
|
|
25881
26310
|
async function updateConfig(rootDir, config) {
|
|
25882
|
-
const configPath =
|
|
26311
|
+
const configPath = path49.join(rootDir, ".mancode", "config.json");
|
|
25883
26312
|
const content = `${JSON.stringify(config, null, 2)}
|
|
25884
26313
|
`;
|
|
25885
26314
|
await fs5.writeFile(configPath, content, "utf-8");
|
|
@@ -25915,7 +26344,7 @@ function readConfiguredMinimal(value, platform) {
|
|
|
25915
26344
|
async function readStatePlatform(rootDir) {
|
|
25916
26345
|
try {
|
|
25917
26346
|
const raw = await fs5.readFile(
|
|
25918
|
-
|
|
26347
|
+
path49.join(rootDir, ".mancode", "state.json"),
|
|
25919
26348
|
"utf-8"
|
|
25920
26349
|
);
|
|
25921
26350
|
const state = JSON.parse(raw);
|
|
@@ -25938,11 +26367,11 @@ function isRecord8(value) {
|
|
|
25938
26367
|
|
|
25939
26368
|
// src/commands/list-platforms.ts
|
|
25940
26369
|
import { promises as fs6 } from "fs";
|
|
25941
|
-
import
|
|
26370
|
+
import path50 from "path";
|
|
25942
26371
|
import process7 from "process";
|
|
25943
26372
|
var EXIT_OK3 = 0;
|
|
25944
26373
|
async function listPlatforms(rootDir = process7.cwd()) {
|
|
25945
|
-
if (await pathExists8(
|
|
26374
|
+
if (await pathExists8(path50.join(rootDir, ".mancode", "schema.json"))) {
|
|
25946
26375
|
return listV3Platforms(rootDir);
|
|
25947
26376
|
}
|
|
25948
26377
|
const installed = new Set(await readInstalledPlatforms(rootDir));
|
|
@@ -25978,7 +26407,7 @@ async function listV3Platforms(rootDir) {
|
|
|
25978
26407
|
async function readInstalledPlatforms(rootDir) {
|
|
25979
26408
|
try {
|
|
25980
26409
|
const raw = await fs6.readFile(
|
|
25981
|
-
|
|
26410
|
+
path50.join(rootDir, ".mancode", "config.json"),
|
|
25982
26411
|
"utf-8"
|
|
25983
26412
|
);
|
|
25984
26413
|
const config = JSON.parse(raw);
|
|
@@ -26010,24 +26439,24 @@ function describePlatform(platform) {
|
|
|
26010
26439
|
}
|
|
26011
26440
|
|
|
26012
26441
|
// src/commands/manps.ts
|
|
26013
|
-
import { access as access4, readFile as
|
|
26014
|
-
import
|
|
26442
|
+
import { access as access4, readFile as readFile37 } from "fs/promises";
|
|
26443
|
+
import path52 from "path";
|
|
26015
26444
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
26016
26445
|
|
|
26017
26446
|
// src/system/preseason.ts
|
|
26018
|
-
import { execFile as
|
|
26447
|
+
import { execFile as execFile8 } from "child_process";
|
|
26019
26448
|
import { createHash as createHash8 } from "crypto";
|
|
26020
26449
|
import { existsSync, readFileSync } from "fs";
|
|
26021
26450
|
import {
|
|
26022
26451
|
access as access3,
|
|
26023
|
-
lstat as
|
|
26024
|
-
mkdir as
|
|
26025
|
-
readFile as
|
|
26026
|
-
readdir as
|
|
26452
|
+
lstat as lstat19,
|
|
26453
|
+
mkdir as mkdir33,
|
|
26454
|
+
readFile as readFile36,
|
|
26455
|
+
readdir as readdir17,
|
|
26027
26456
|
rename as rename9,
|
|
26028
|
-
writeFile as
|
|
26457
|
+
writeFile as writeFile38
|
|
26029
26458
|
} from "fs/promises";
|
|
26030
|
-
import
|
|
26459
|
+
import path51 from "path";
|
|
26031
26460
|
var PRESEASON_AREAS = [
|
|
26032
26461
|
"all",
|
|
26033
26462
|
"deps",
|
|
@@ -26107,10 +26536,10 @@ async function runPreseasonScan(projectRoot, area = "all", options = {}) {
|
|
|
26107
26536
|
const needsFiles = normalizedArea === "all" || normalizedArea === "dead-code" || normalizedArea === "config";
|
|
26108
26537
|
const files = needsFiles ? await listProjectFiles(projectRoot) : [];
|
|
26109
26538
|
const issues = (await scanArea(projectRoot, normalizedArea, pkg, files)).slice(0, 20);
|
|
26110
|
-
const storageRoot = options.storageRoot ??
|
|
26111
|
-
const reportDir =
|
|
26112
|
-
await
|
|
26113
|
-
const issueDbPath =
|
|
26539
|
+
const storageRoot = options.storageRoot ?? path51.join(projectRoot, ".mancode");
|
|
26540
|
+
const reportDir = path51.join(storageRoot, "preseason-reports");
|
|
26541
|
+
await mkdir33(reportDir, { recursive: true });
|
|
26542
|
+
const issueDbPath = path51.join(storageRoot, "preseason-issues.json");
|
|
26114
26543
|
const reportPath = await allocateReportPath(
|
|
26115
26544
|
reportDir,
|
|
26116
26545
|
`${generatedAt.replace(/[:.]/g, "-")}-${normalizedArea}`
|
|
@@ -26124,9 +26553,9 @@ async function runPreseasonScan(projectRoot, area = "all", options = {}) {
|
|
|
26124
26553
|
issueDbPath
|
|
26125
26554
|
};
|
|
26126
26555
|
const database = await buildIssueDatabase(projectRoot, report);
|
|
26127
|
-
await
|
|
26128
|
-
await
|
|
26129
|
-
|
|
26556
|
+
await writeFile38(reportPath, renderPreseasonReport(report), "utf-8");
|
|
26557
|
+
await writeFile38(
|
|
26558
|
+
path51.join(storageRoot, "preseason-report.md"),
|
|
26130
26559
|
renderPreseasonReport(report),
|
|
26131
26560
|
"utf-8"
|
|
26132
26561
|
);
|
|
@@ -26134,7 +26563,7 @@ async function runPreseasonScan(projectRoot, area = "all", options = {}) {
|
|
|
26134
26563
|
return report;
|
|
26135
26564
|
}
|
|
26136
26565
|
async function runPreseasonRemediation(projectRoot, issues, options = {}) {
|
|
26137
|
-
const issueDbPath = options.issueDbPath ??
|
|
26566
|
+
const issueDbPath = options.issueDbPath ?? path51.join(projectRoot, ".mancode", "preseason-issues.json");
|
|
26138
26567
|
const database = await readIssueDatabase(issueDbPath);
|
|
26139
26568
|
const keys = new Set(issues.map((issue) => issueKey(issue)));
|
|
26140
26569
|
const targets = database.issues.filter(
|
|
@@ -26212,7 +26641,7 @@ async function runPreseasonRemediation(projectRoot, issues, options = {}) {
|
|
|
26212
26641
|
write2(" Decision: skipped.");
|
|
26213
26642
|
}
|
|
26214
26643
|
database.updatedAt = now;
|
|
26215
|
-
await
|
|
26644
|
+
await writeFile38(
|
|
26216
26645
|
issueDbPath,
|
|
26217
26646
|
`${JSON.stringify(database, null, 2)}
|
|
26218
26647
|
`,
|
|
@@ -26244,7 +26673,7 @@ async function scanArea(projectRoot, area, pkg, files) {
|
|
|
26244
26673
|
async function allocateReportPath(reportDir, baseName) {
|
|
26245
26674
|
for (let attempt = 0; attempt < 1e3; attempt++) {
|
|
26246
26675
|
const suffix = attempt === 0 ? "" : `-${attempt + 1}`;
|
|
26247
|
-
const candidate =
|
|
26676
|
+
const candidate = path51.join(reportDir, `${baseName}${suffix}.md`);
|
|
26248
26677
|
if (!existsSync(candidate)) return candidate;
|
|
26249
26678
|
}
|
|
26250
26679
|
throw new Error(`unable to allocate preseason report path: ${baseName}`);
|
|
@@ -26287,24 +26716,24 @@ async function walk(root, current, results, depth) {
|
|
|
26287
26716
|
if (depth > MAX_SCAN_DEPTH || results.length >= MAX_PROJECT_FILES) return;
|
|
26288
26717
|
let entries;
|
|
26289
26718
|
try {
|
|
26290
|
-
entries = await
|
|
26719
|
+
entries = await readdir17(current);
|
|
26291
26720
|
} catch {
|
|
26292
26721
|
return;
|
|
26293
26722
|
}
|
|
26294
26723
|
for (const entry of entries) {
|
|
26295
26724
|
if (IGNORE_DIRS.has(entry)) continue;
|
|
26296
|
-
const abs =
|
|
26297
|
-
const rel =
|
|
26725
|
+
const abs = path51.join(current, entry);
|
|
26726
|
+
const rel = path51.relative(root, abs);
|
|
26298
26727
|
let info;
|
|
26299
26728
|
try {
|
|
26300
|
-
info = await
|
|
26729
|
+
info = await lstat19(abs);
|
|
26301
26730
|
} catch {
|
|
26302
26731
|
continue;
|
|
26303
26732
|
}
|
|
26304
26733
|
if (info.isSymbolicLink()) continue;
|
|
26305
26734
|
if (info.isDirectory()) {
|
|
26306
26735
|
await walk(root, abs, results, depth + 1);
|
|
26307
|
-
} else if (SOURCE_EXTENSIONS.has(
|
|
26736
|
+
} else if (SOURCE_EXTENSIONS.has(path51.extname(entry)) || entry === "package.json") {
|
|
26308
26737
|
results.push(rel);
|
|
26309
26738
|
if (results.length >= MAX_PROJECT_FILES) return;
|
|
26310
26739
|
}
|
|
@@ -26312,7 +26741,7 @@ async function walk(root, current, results, depth) {
|
|
|
26312
26741
|
}
|
|
26313
26742
|
async function readPackageJson(projectRoot) {
|
|
26314
26743
|
try {
|
|
26315
|
-
const raw = await
|
|
26744
|
+
const raw = await readFile36(path51.join(projectRoot, "package.json"), "utf-8");
|
|
26316
26745
|
return JSON.parse(raw);
|
|
26317
26746
|
} catch {
|
|
26318
26747
|
return null;
|
|
@@ -26405,7 +26834,7 @@ function scanTodos(projectRoot, files) {
|
|
|
26405
26834
|
const matches = [];
|
|
26406
26835
|
for (const file of files) {
|
|
26407
26836
|
if (matches.length >= 7) break;
|
|
26408
|
-
const abs =
|
|
26837
|
+
const abs = path51.join(projectRoot, file);
|
|
26409
26838
|
matches.push(...readTodoIssues(abs, file, matches.length));
|
|
26410
26839
|
}
|
|
26411
26840
|
return matches.slice(0, 7);
|
|
@@ -26446,7 +26875,7 @@ function scanTestGaps(files) {
|
|
|
26446
26875
|
if (sourceFiles.length === 0) return [];
|
|
26447
26876
|
const tests = new Set(files.filter((file) => file.startsWith("tests/")));
|
|
26448
26877
|
const missing = sourceFiles.filter((file) => {
|
|
26449
|
-
const base =
|
|
26878
|
+
const base = path51.basename(file).replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
26450
26879
|
return !Array.from(tests).some((test) => test.includes(base));
|
|
26451
26880
|
}).slice(0, 4);
|
|
26452
26881
|
return missing.map((file, index) => ({
|
|
@@ -26455,13 +26884,13 @@ function scanTestGaps(files) {
|
|
|
26455
26884
|
type: "tests",
|
|
26456
26885
|
title: "Core source file has no obvious test",
|
|
26457
26886
|
file,
|
|
26458
|
-
detail: `No matching test file was found for ${
|
|
26887
|
+
detail: `No matching test file was found for ${path51.basename(file)}.`,
|
|
26459
26888
|
recommendation: "Add focused coverage for the public behavior or document why this module is exercised indirectly."
|
|
26460
26889
|
}));
|
|
26461
26890
|
}
|
|
26462
26891
|
function scanConfig(projectRoot, files) {
|
|
26463
26892
|
const issues = [];
|
|
26464
|
-
if (!files.includes(".gitignore") && !pathExistsSync(
|
|
26893
|
+
if (!files.includes(".gitignore") && !pathExistsSync(path51.join(projectRoot, ".gitignore"))) {
|
|
26465
26894
|
issues.push({
|
|
26466
26895
|
id: "config-gitignore",
|
|
26467
26896
|
severity: "P1",
|
|
@@ -26472,7 +26901,7 @@ function scanConfig(projectRoot, files) {
|
|
|
26472
26901
|
recommendation: "Add a .gitignore that excludes dependencies, build output, coverage, and local env files."
|
|
26473
26902
|
});
|
|
26474
26903
|
}
|
|
26475
|
-
if (!files.includes(".editorconfig") && !pathExistsSync(
|
|
26904
|
+
if (!files.includes(".editorconfig") && !pathExistsSync(path51.join(projectRoot, ".editorconfig"))) {
|
|
26476
26905
|
issues.push({
|
|
26477
26906
|
id: "config-editorconfig",
|
|
26478
26907
|
severity: "P2",
|
|
@@ -26491,7 +26920,7 @@ function scanAestheticDrift(projectRoot, files) {
|
|
|
26491
26920
|
for (const file of frontendFiles) {
|
|
26492
26921
|
let content;
|
|
26493
26922
|
try {
|
|
26494
|
-
content = readFileSyncSafe(
|
|
26923
|
+
content = readFileSyncSafe(path51.join(projectRoot, file));
|
|
26495
26924
|
} catch {
|
|
26496
26925
|
continue;
|
|
26497
26926
|
}
|
|
@@ -26511,7 +26940,7 @@ function scanAestheticDrift(projectRoot, files) {
|
|
|
26511
26940
|
return issues;
|
|
26512
26941
|
}
|
|
26513
26942
|
async function scanArchitecture(projectRoot) {
|
|
26514
|
-
const localBinary =
|
|
26943
|
+
const localBinary = path51.join(
|
|
26515
26944
|
projectRoot,
|
|
26516
26945
|
"node_modules",
|
|
26517
26946
|
".bin",
|
|
@@ -26559,7 +26988,7 @@ async function hasDependencyCruiserConfig(projectRoot) {
|
|
|
26559
26988
|
"dependency-cruiser.config.mjs"
|
|
26560
26989
|
];
|
|
26561
26990
|
const results = await Promise.all(
|
|
26562
|
-
files.map((file) => pathExists9(
|
|
26991
|
+
files.map((file) => pathExists9(path51.join(projectRoot, file)))
|
|
26563
26992
|
);
|
|
26564
26993
|
return results.some(Boolean);
|
|
26565
26994
|
}
|
|
@@ -26576,7 +27005,7 @@ function architectureScannerUnavailableIssue() {
|
|
|
26576
27005
|
function runDepcruise(binary, projectRoot) {
|
|
26577
27006
|
return new Promise((resolve) => {
|
|
26578
27007
|
const needsShell = process.platform === "win32";
|
|
26579
|
-
|
|
27008
|
+
execFile8(
|
|
26580
27009
|
binary,
|
|
26581
27010
|
["--output-type", "json", "."],
|
|
26582
27011
|
{
|
|
@@ -26665,9 +27094,9 @@ function inferCommands(pkg) {
|
|
|
26665
27094
|
return ["lint", "test", "build"].filter((name) => scripts[name]).map((name) => `npm run ${name}`);
|
|
26666
27095
|
}
|
|
26667
27096
|
async function buildIssueDatabase(projectRoot, report) {
|
|
26668
|
-
const reportRef =
|
|
27097
|
+
const reportRef = path51.relative(projectRoot, report.reportPath);
|
|
26669
27098
|
const run = {
|
|
26670
|
-
id:
|
|
27099
|
+
id: path51.basename(report.reportPath, ".md"),
|
|
26671
27100
|
generatedAt: report.generatedAt,
|
|
26672
27101
|
area: report.area,
|
|
26673
27102
|
reportPath: reportRef,
|
|
@@ -26709,7 +27138,7 @@ async function buildIssueDatabase(projectRoot, report) {
|
|
|
26709
27138
|
async function readIssueDatabase(issueDbPath) {
|
|
26710
27139
|
let raw;
|
|
26711
27140
|
try {
|
|
26712
|
-
raw = await
|
|
27141
|
+
raw = await readFile36(issueDbPath, "utf-8");
|
|
26713
27142
|
} catch (err) {
|
|
26714
27143
|
if (isNodeError8(err) && err.code === "ENOENT") {
|
|
26715
27144
|
return emptyIssueDatabase();
|
|
@@ -26730,7 +27159,7 @@ async function readIssueDatabase(issueDbPath) {
|
|
|
26730
27159
|
}
|
|
26731
27160
|
async function writeJsonAtomic3(file, value) {
|
|
26732
27161
|
const tmp = `${file}.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
26733
|
-
await
|
|
27162
|
+
await writeFile38(tmp, `${JSON.stringify(value, null, 2)}
|
|
26734
27163
|
`, "utf-8");
|
|
26735
27164
|
await rename9(tmp, file);
|
|
26736
27165
|
}
|
|
@@ -26773,20 +27202,20 @@ function compareIssueRecords(a, b) {
|
|
|
26773
27202
|
}
|
|
26774
27203
|
async function applySafeRemediation(projectRoot, issue) {
|
|
26775
27204
|
if (issue.id === "config-gitignore" && issue.file === ".gitignore") {
|
|
26776
|
-
const gitignorePath =
|
|
27205
|
+
const gitignorePath = path51.join(projectRoot, ".gitignore");
|
|
26777
27206
|
if (pathExistsSync(gitignorePath)) {
|
|
26778
27207
|
return { applied: false };
|
|
26779
27208
|
}
|
|
26780
|
-
await
|
|
27209
|
+
await writeFile38(gitignorePath, `${DEFAULT_GITIGNORE}
|
|
26781
27210
|
`, "utf-8");
|
|
26782
27211
|
return { applied: true, action: "created .gitignore" };
|
|
26783
27212
|
}
|
|
26784
27213
|
if (issue.id === "config-editorconfig" && issue.file === ".editorconfig") {
|
|
26785
|
-
const editorconfigPath =
|
|
27214
|
+
const editorconfigPath = path51.join(projectRoot, ".editorconfig");
|
|
26786
27215
|
if (pathExistsSync(editorconfigPath)) {
|
|
26787
27216
|
return { applied: false };
|
|
26788
27217
|
}
|
|
26789
|
-
await
|
|
27218
|
+
await writeFile38(editorconfigPath, `${DEFAULT_EDITORCONFIG}
|
|
26790
27219
|
`, "utf-8");
|
|
26791
27220
|
return { applied: true, action: "created .editorconfig" };
|
|
26792
27221
|
}
|
|
@@ -26822,10 +27251,10 @@ async function inferSafePackageScript(projectRoot, scriptName) {
|
|
|
26822
27251
|
}
|
|
26823
27252
|
}
|
|
26824
27253
|
async function addPackageScript(projectRoot, scriptName, script) {
|
|
26825
|
-
const packagePath =
|
|
27254
|
+
const packagePath = path51.join(projectRoot, "package.json");
|
|
26826
27255
|
let pkg;
|
|
26827
27256
|
try {
|
|
26828
|
-
pkg = JSON.parse(await
|
|
27257
|
+
pkg = JSON.parse(await readFile36(packagePath, "utf-8"));
|
|
26829
27258
|
} catch {
|
|
26830
27259
|
return false;
|
|
26831
27260
|
}
|
|
@@ -26835,7 +27264,7 @@ async function addPackageScript(projectRoot, scriptName, script) {
|
|
|
26835
27264
|
...scripts,
|
|
26836
27265
|
[scriptName]: script
|
|
26837
27266
|
};
|
|
26838
|
-
await
|
|
27267
|
+
await writeFile38(packagePath, `${JSON.stringify(pkg, null, 2)}
|
|
26839
27268
|
`, "utf-8");
|
|
26840
27269
|
return true;
|
|
26841
27270
|
}
|
|
@@ -26935,7 +27364,7 @@ var EXIT_NOT_INITIALIZED2 = 1;
|
|
|
26935
27364
|
var EXIT_SCAN_FAILED = 2;
|
|
26936
27365
|
var EXIT_INVALID_ARG = 3;
|
|
26937
27366
|
async function manps(rootDir, area = "all", options = {}) {
|
|
26938
|
-
const v3SchemaPath =
|
|
27367
|
+
const v3SchemaPath = path52.join(rootDir, ".mancode", "schema.json");
|
|
26939
27368
|
const v3Activation = await readV3ActivationState(v3SchemaPath);
|
|
26940
27369
|
if (v3Activation !== null && v3Activation !== "v3_active" && v3Activation !== "dual_read") {
|
|
26941
27370
|
const message = `manps is unavailable while mancode activation is ${v3Activation}`;
|
|
@@ -26948,7 +27377,7 @@ async function manps(rootDir, area = "all", options = {}) {
|
|
|
26948
27377
|
return EXIT_SCAN_FAILED;
|
|
26949
27378
|
}
|
|
26950
27379
|
const v3Initialized = v3Activation === "v3_active";
|
|
26951
|
-
const initialized = v3Initialized || await pathExists10(
|
|
27380
|
+
const initialized = v3Initialized || await pathExists10(path52.join(rootDir, ".mancode", "state.json"));
|
|
26952
27381
|
if (!initialized) {
|
|
26953
27382
|
if (options.json) {
|
|
26954
27383
|
console.log(JSON.stringify({ error: "not initialized" }, null, 2));
|
|
@@ -26961,7 +27390,7 @@ async function manps(rootDir, area = "all", options = {}) {
|
|
|
26961
27390
|
let report;
|
|
26962
27391
|
try {
|
|
26963
27392
|
report = await runPreseasonScan(rootDir, area, {
|
|
26964
|
-
storageRoot: v3Initialized ?
|
|
27393
|
+
storageRoot: v3Initialized ? path52.join(rootDir, ".mancode", "local") : void 0
|
|
26965
27394
|
});
|
|
26966
27395
|
} catch (err) {
|
|
26967
27396
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -27030,8 +27459,8 @@ async function manps(rootDir, area = "all", options = {}) {
|
|
|
27030
27459
|
console.log(
|
|
27031
27460
|
`Issues: ${report.issues.length} total (P0 ${p0}, P1 ${p1}, P2 ${p2})`
|
|
27032
27461
|
);
|
|
27033
|
-
console.log(`Report: ${
|
|
27034
|
-
console.log(`Issue DB: ${
|
|
27462
|
+
console.log(`Report: ${path52.relative(rootDir, report.reportPath)}`);
|
|
27463
|
+
console.log(`Issue DB: ${path52.relative(rootDir, report.issueDbPath)}`);
|
|
27035
27464
|
if (report.issues.length > 0) {
|
|
27036
27465
|
console.log("");
|
|
27037
27466
|
for (const issue of report.issues.slice(0, 7)) {
|
|
@@ -27047,7 +27476,7 @@ async function manps(rootDir, area = "all", options = {}) {
|
|
|
27047
27476
|
console.log(` Skipped: ${remediation.skipped}`);
|
|
27048
27477
|
console.log(` Fixed: ${remediation.fixed}`);
|
|
27049
27478
|
console.log(
|
|
27050
|
-
` Issue DB: ${
|
|
27479
|
+
` Issue DB: ${path52.relative(rootDir, remediation.issueDbPath)}`
|
|
27051
27480
|
);
|
|
27052
27481
|
}
|
|
27053
27482
|
return EXIT_OK4;
|
|
@@ -27108,7 +27537,7 @@ async function readV3ActivationState(schemaPath) {
|
|
|
27108
27537
|
if (!await pathExists10(schemaPath)) return null;
|
|
27109
27538
|
try {
|
|
27110
27539
|
const manifest = parseSchemaManifest(
|
|
27111
|
-
JSON.parse(await
|
|
27540
|
+
JSON.parse(await readFile37(schemaPath, "utf8"))
|
|
27112
27541
|
);
|
|
27113
27542
|
return manifest.activationState;
|
|
27114
27543
|
} catch {
|
|
@@ -27117,8 +27546,8 @@ async function readV3ActivationState(schemaPath) {
|
|
|
27117
27546
|
}
|
|
27118
27547
|
|
|
27119
27548
|
// src/commands/migrate.ts
|
|
27120
|
-
import { readFile as
|
|
27121
|
-
import
|
|
27549
|
+
import { readFile as readFile38 } from "fs/promises";
|
|
27550
|
+
import path53 from "path";
|
|
27122
27551
|
var EXIT_OK5 = 0;
|
|
27123
27552
|
var EXIT_INVALID_ARG2 = 2;
|
|
27124
27553
|
var EXIT_MIGRATION_BLOCKED = 3;
|
|
@@ -27244,14 +27673,14 @@ async function readScopeFile(rootDir, file) {
|
|
|
27244
27673
|
if (!file.trim() || file.includes("\0")) {
|
|
27245
27674
|
throw new Error("MANCODE_MIGRATION_SCOPE_FILE_INVALID");
|
|
27246
27675
|
}
|
|
27247
|
-
const resolved =
|
|
27248
|
-
const relative =
|
|
27249
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
27676
|
+
const resolved = path53.resolve(rootDir, file);
|
|
27677
|
+
const relative = path53.relative(path53.resolve(rootDir), resolved);
|
|
27678
|
+
if (relative === ".." || relative.startsWith(`..${path53.sep}`) || path53.isAbsolute(relative)) {
|
|
27250
27679
|
throw new Error("MANCODE_MIGRATION_SCOPE_FILE_INVALID");
|
|
27251
27680
|
}
|
|
27252
27681
|
try {
|
|
27253
27682
|
return JSON.parse(
|
|
27254
|
-
await
|
|
27683
|
+
await readFile38(resolved, "utf8")
|
|
27255
27684
|
);
|
|
27256
27685
|
} catch (error) {
|
|
27257
27686
|
if (error instanceof SyntaxError) {
|
|
@@ -27353,16 +27782,16 @@ async function runOperationMutation(rootDir, operationId, options, mode) {
|
|
|
27353
27782
|
// src/commands/refresh-project.ts
|
|
27354
27783
|
import { randomUUID } from "crypto";
|
|
27355
27784
|
import { promises as fs7 } from "fs";
|
|
27356
|
-
import
|
|
27785
|
+
import path54 from "path";
|
|
27357
27786
|
import process8 from "process";
|
|
27358
27787
|
var EXIT_OK6 = 0;
|
|
27359
27788
|
var EXIT_NOT_INITIALIZED3 = 1;
|
|
27360
27789
|
var EXIT_CORRUPT_STATE = 2;
|
|
27361
27790
|
var EXIT_REFRESH_FAILED = 3;
|
|
27362
27791
|
async function refreshProject(rootDir = process8.cwd()) {
|
|
27363
|
-
const mancodeDir =
|
|
27364
|
-
const statePath =
|
|
27365
|
-
if (await pathExists11(
|
|
27792
|
+
const mancodeDir = path54.join(rootDir, ".mancode");
|
|
27793
|
+
const statePath = path54.join(mancodeDir, "state.json");
|
|
27794
|
+
if (await pathExists11(path54.join(mancodeDir, "schema.json"))) {
|
|
27366
27795
|
return refreshV3Project(rootDir);
|
|
27367
27796
|
}
|
|
27368
27797
|
if (!await pathExists11(statePath)) {
|
|
@@ -27381,12 +27810,12 @@ async function refreshProject(rootDir = process8.cwd()) {
|
|
|
27381
27810
|
const [profile, team, hasGit, hasManifest] = await Promise.all([
|
|
27382
27811
|
detectProjectProfile(rootDir),
|
|
27383
27812
|
detectTeamStatus(rootDir),
|
|
27384
|
-
pathExists11(
|
|
27813
|
+
pathExists11(path54.join(rootDir, ".git")),
|
|
27385
27814
|
hasProjectManifest2(rootDir)
|
|
27386
27815
|
]);
|
|
27387
27816
|
const uiLibrary = primaryUiLibrary(profile);
|
|
27388
27817
|
const stack = [...profile.languages, ...profile.frameworks];
|
|
27389
|
-
const config = await readJson2(
|
|
27818
|
+
const config = await readJson2(path54.join(mancodeDir, "config.json"));
|
|
27390
27819
|
const configuredTeam = config.forceTeamMode === true ? true : config.teamMode === "on" ? true : config.teamMode === "off" ? false : team.isTeam;
|
|
27391
27820
|
const nextState = {
|
|
27392
27821
|
...state,
|
|
@@ -27398,7 +27827,7 @@ async function refreshProject(rootDir = process8.cwd()) {
|
|
|
27398
27827
|
};
|
|
27399
27828
|
await writeProjectFacts2(
|
|
27400
27829
|
statePath,
|
|
27401
|
-
|
|
27830
|
+
path54.join(mancodeDir, "project-profile.json"),
|
|
27402
27831
|
`${JSON.stringify(nextState, null, 2)}
|
|
27403
27832
|
`,
|
|
27404
27833
|
`${JSON.stringify(profile, null, 2)}
|
|
@@ -27465,7 +27894,7 @@ async function refreshV3Project(rootDir) {
|
|
|
27465
27894
|
}
|
|
27466
27895
|
async function hasProjectManifest2(rootDir) {
|
|
27467
27896
|
for (const manifest of PROJECT_MANIFESTS) {
|
|
27468
|
-
if (await pathExists11(
|
|
27897
|
+
if (await pathExists11(path54.join(rootDir, manifest))) return true;
|
|
27469
27898
|
}
|
|
27470
27899
|
return false;
|
|
27471
27900
|
}
|
|
@@ -27531,9 +27960,9 @@ async function readOptionalText(filePath) {
|
|
|
27531
27960
|
}
|
|
27532
27961
|
}
|
|
27533
27962
|
function temporaryPath(filePath) {
|
|
27534
|
-
return
|
|
27535
|
-
|
|
27536
|
-
`.${
|
|
27963
|
+
return path54.join(
|
|
27964
|
+
path54.dirname(filePath),
|
|
27965
|
+
`.${path54.basename(filePath)}.${process8.pid}.${randomUUID()}.tmp`
|
|
27537
27966
|
);
|
|
27538
27967
|
}
|
|
27539
27968
|
async function refreshStaticPlatforms(rootDir, config, fallbackPlatform, stack, uiLibrary, profile) {
|
|
@@ -27603,14 +28032,14 @@ async function pathExists11(filePath) {
|
|
|
27603
28032
|
|
|
27604
28033
|
// src/commands/refresh-style.ts
|
|
27605
28034
|
import { promises as fs8 } from "fs";
|
|
27606
|
-
import
|
|
28035
|
+
import path55 from "path";
|
|
27607
28036
|
import process9 from "process";
|
|
27608
28037
|
var EXIT_OK7 = 0;
|
|
27609
28038
|
var EXIT_NOT_INITIALIZED4 = 1;
|
|
27610
28039
|
var EXIT_V3_REFRESH_FAILED = 2;
|
|
27611
28040
|
async function refreshStyle(rootDir = process9.cwd()) {
|
|
27612
|
-
const stateFile =
|
|
27613
|
-
if (await pathExists12(
|
|
28041
|
+
const stateFile = path55.join(rootDir, ".mancode", "state.json");
|
|
28042
|
+
if (await pathExists12(path55.join(rootDir, ".mancode", "schema.json"))) {
|
|
27614
28043
|
return refreshV3Style(rootDir);
|
|
27615
28044
|
}
|
|
27616
28045
|
if (!await pathExists12(stateFile)) {
|
|
@@ -27620,7 +28049,7 @@ async function refreshStyle(rootDir = process9.cwd()) {
|
|
|
27620
28049
|
}
|
|
27621
28050
|
console.log("\u2713 \u5237\u65B0\u9879\u76EE profile...");
|
|
27622
28051
|
const profile = await detectProjectProfile(rootDir);
|
|
27623
|
-
const profilePath =
|
|
28052
|
+
const profilePath = path55.join(rootDir, ".mancode", "project-profile.json");
|
|
27624
28053
|
await fs8.writeFile(
|
|
27625
28054
|
profilePath,
|
|
27626
28055
|
`${JSON.stringify(profile, null, 2)}
|
|
@@ -27642,13 +28071,13 @@ async function refreshStyle(rootDir = process9.cwd()) {
|
|
|
27642
28071
|
}
|
|
27643
28072
|
console.log("\u2713 \u626B\u63CF\u9879\u76EE\u8BBE\u8BA1 token...");
|
|
27644
28073
|
const tokens = await scanAesthetics(rootDir, uiLibraryHint);
|
|
27645
|
-
const tokensPath =
|
|
28074
|
+
const tokensPath = path55.join(
|
|
27646
28075
|
rootDir,
|
|
27647
28076
|
".mancode",
|
|
27648
28077
|
"aesthetics",
|
|
27649
28078
|
"style-tokens.json"
|
|
27650
28079
|
);
|
|
27651
|
-
await fs8.mkdir(
|
|
28080
|
+
await fs8.mkdir(path55.dirname(tokensPath), { recursive: true });
|
|
27652
28081
|
await fs8.writeFile(
|
|
27653
28082
|
tokensPath,
|
|
27654
28083
|
`${JSON.stringify(tokens, null, 2)}
|
|
@@ -27720,7 +28149,7 @@ async function refreshV3Style(rootDir) {
|
|
|
27720
28149
|
console.log(
|
|
27721
28150
|
` \u7C7B\u578B: ${profile.projectKind} | UI: ${profile.uiAssets} | \u6D4F\u89C8\u5668: ${profile.browserAutomation}`
|
|
27722
28151
|
);
|
|
27723
|
-
const tokensPath =
|
|
28152
|
+
const tokensPath = path55.join(
|
|
27724
28153
|
rootDir,
|
|
27725
28154
|
".mancode",
|
|
27726
28155
|
"local",
|
|
@@ -27737,7 +28166,7 @@ async function refreshV3Style(rootDir) {
|
|
|
27737
28166
|
}
|
|
27738
28167
|
console.log("\u2713 \u626B\u63CF\u9879\u76EE\u8BBE\u8BA1 token...");
|
|
27739
28168
|
const tokens = await scanAesthetics(rootDir, uiLibraryHint);
|
|
27740
|
-
await fs8.mkdir(
|
|
28169
|
+
await fs8.mkdir(path55.dirname(tokensPath), { recursive: true });
|
|
27741
28170
|
await fs8.writeFile(
|
|
27742
28171
|
tokensPath,
|
|
27743
28172
|
`${JSON.stringify(tokens, null, 2)}
|
|
@@ -27771,7 +28200,7 @@ async function printStaticPlatformRefreshHint(rootDir) {
|
|
|
27771
28200
|
);
|
|
27772
28201
|
}
|
|
27773
28202
|
async function refreshLegacyStateContext(rootDir, profile, uiLibrary) {
|
|
27774
|
-
const statePath =
|
|
28203
|
+
const statePath = path55.join(rootDir, ".mancode", "state.json");
|
|
27775
28204
|
try {
|
|
27776
28205
|
const state = JSON.parse(await fs8.readFile(statePath, "utf-8"));
|
|
27777
28206
|
const stack = [...profile.languages, ...profile.frameworks];
|
|
@@ -27795,7 +28224,7 @@ async function refreshLegacyStateContext(rootDir, profile, uiLibrary) {
|
|
|
27795
28224
|
async function readInstalledPlatforms2(rootDir) {
|
|
27796
28225
|
try {
|
|
27797
28226
|
const raw = await fs8.readFile(
|
|
27798
|
-
|
|
28227
|
+
path55.join(rootDir, ".mancode", "config.json"),
|
|
27799
28228
|
"utf-8"
|
|
27800
28229
|
);
|
|
27801
28230
|
const config = JSON.parse(raw);
|
|
@@ -27818,7 +28247,7 @@ async function pathExists12(p) {
|
|
|
27818
28247
|
// src/commands/status.ts
|
|
27819
28248
|
import { spawn } from "child_process";
|
|
27820
28249
|
import { promises as fs9 } from "fs";
|
|
27821
|
-
import
|
|
28250
|
+
import path56 from "path";
|
|
27822
28251
|
import process10 from "process";
|
|
27823
28252
|
|
|
27824
28253
|
// src/team/assessment.ts
|
|
@@ -27974,8 +28403,8 @@ var EXIT_OK8 = 0;
|
|
|
27974
28403
|
var EXIT_NOT_INITIALIZED5 = 1;
|
|
27975
28404
|
var EXIT_CORRUPT_STATE2 = 2;
|
|
27976
28405
|
async function status(rootDir = process10.cwd(), options = {}) {
|
|
27977
|
-
const stateFile =
|
|
27978
|
-
const v3SchemaFile =
|
|
28406
|
+
const stateFile = path56.join(rootDir, ".mancode", "state.json");
|
|
28407
|
+
const v3SchemaFile = path56.join(rootDir, ".mancode", "schema.json");
|
|
27979
28408
|
if (await pathExists13(v3SchemaFile)) {
|
|
27980
28409
|
return statusV3(rootDir, options);
|
|
27981
28410
|
}
|
|
@@ -28207,10 +28636,10 @@ async function readV3StatusSession(rootDir) {
|
|
|
28207
28636
|
}
|
|
28208
28637
|
async function shouldRefreshProject(rootDir, state) {
|
|
28209
28638
|
if (state.projectMode !== "generic") return false;
|
|
28210
|
-
const hasGit = await pathExists13(
|
|
28639
|
+
const hasGit = await pathExists13(path56.join(rootDir, ".git"));
|
|
28211
28640
|
if (hasGit) return true;
|
|
28212
28641
|
for (const manifest of PROJECT_MANIFESTS) {
|
|
28213
|
-
if (await pathExists13(
|
|
28642
|
+
if (await pathExists13(path56.join(rootDir, manifest))) return true;
|
|
28214
28643
|
}
|
|
28215
28644
|
return false;
|
|
28216
28645
|
}
|
|
@@ -28254,19 +28683,19 @@ async function getCurrentWorkflow(rootDir, taskId) {
|
|
|
28254
28683
|
}
|
|
28255
28684
|
async function getProjectName(rootDir) {
|
|
28256
28685
|
try {
|
|
28257
|
-
const raw = await fs9.readFile(
|
|
28686
|
+
const raw = await fs9.readFile(path56.join(rootDir, "package.json"), "utf-8");
|
|
28258
28687
|
const pkg = JSON.parse(raw);
|
|
28259
28688
|
if (pkg.name && typeof pkg.name === "string") {
|
|
28260
28689
|
return pkg.name;
|
|
28261
28690
|
}
|
|
28262
28691
|
} catch {
|
|
28263
28692
|
}
|
|
28264
|
-
return
|
|
28693
|
+
return path56.basename(rootDir);
|
|
28265
28694
|
}
|
|
28266
28695
|
async function readConfig3(rootDir) {
|
|
28267
28696
|
try {
|
|
28268
28697
|
const raw = await fs9.readFile(
|
|
28269
|
-
|
|
28698
|
+
path56.join(rootDir, ".mancode", "config.json"),
|
|
28270
28699
|
"utf-8"
|
|
28271
28700
|
);
|
|
28272
28701
|
return JSON.parse(raw);
|
|
@@ -28294,9 +28723,9 @@ function getEffectiveTeamStatus(state, config, detected) {
|
|
|
28294
28723
|
}
|
|
28295
28724
|
async function checkHooks(rootDir) {
|
|
28296
28725
|
const [sessionStart, userPromptSubmit, registered] = await Promise.all([
|
|
28297
|
-
pathExists13(
|
|
28726
|
+
pathExists13(path56.join(rootDir, ".mancode", "hooks", "session-start.mjs")),
|
|
28298
28727
|
pathExists13(
|
|
28299
|
-
|
|
28728
|
+
path56.join(rootDir, ".mancode", "hooks", "user-prompt-submit.mjs")
|
|
28300
28729
|
),
|
|
28301
28730
|
isRegistered(rootDir)
|
|
28302
28731
|
]);
|
|
@@ -28305,7 +28734,7 @@ async function checkHooks(rootDir) {
|
|
|
28305
28734
|
async function isRegistered(rootDir) {
|
|
28306
28735
|
try {
|
|
28307
28736
|
const raw = await fs9.readFile(
|
|
28308
|
-
|
|
28737
|
+
path56.join(rootDir, ".claude", "settings.json"),
|
|
28309
28738
|
"utf-8"
|
|
28310
28739
|
);
|
|
28311
28740
|
const settings = JSON.parse(raw);
|
|
@@ -28334,7 +28763,7 @@ function hasHookCommand2(value, needle) {
|
|
|
28334
28763
|
});
|
|
28335
28764
|
}
|
|
28336
28765
|
async function estimateHookInjection(rootDir) {
|
|
28337
|
-
const hookPath =
|
|
28766
|
+
const hookPath = path56.join(
|
|
28338
28767
|
rootDir,
|
|
28339
28768
|
".mancode",
|
|
28340
28769
|
"hooks",
|
|
@@ -29825,162 +30254,24 @@ function assertPositiveRevision2(value, label) {
|
|
|
29825
30254
|
}
|
|
29826
30255
|
}
|
|
29827
30256
|
|
|
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
30257
|
// src/team/git-ref-handoff-repair.ts
|
|
29971
|
-
import { lstat as
|
|
29972
|
-
import
|
|
30258
|
+
import { lstat as lstat20, mkdir as mkdir34, readFile as readFile39, readdir as readdir18, writeFile as writeFile39 } from "fs/promises";
|
|
30259
|
+
import path57 from "path";
|
|
29973
30260
|
|
|
29974
30261
|
// src/team/git-ref-operation.ts
|
|
29975
|
-
import { execFile as
|
|
29976
|
-
import { promisify as
|
|
30262
|
+
import { execFile as execFileCallback6 } from "child_process";
|
|
30263
|
+
import { promisify as promisify8 } from "util";
|
|
29977
30264
|
|
|
29978
30265
|
// src/team/git-ref-coordination.ts
|
|
29979
30266
|
function prepareGitRefCoordinationMutation(manifest, input) {
|
|
29980
30267
|
const context = openMutationContext(manifest, input);
|
|
29981
30268
|
switch (input.kind) {
|
|
29982
30269
|
case "ownership_fence":
|
|
29983
|
-
return prepareOwnershipFence(
|
|
30270
|
+
return prepareOwnershipFence(
|
|
30271
|
+
context,
|
|
30272
|
+
input.taskBundle,
|
|
30273
|
+
input.expectedPredecessorBundleDigest
|
|
30274
|
+
);
|
|
29984
30275
|
case "claim_acquire":
|
|
29985
30276
|
return prepareClaimAcquire(
|
|
29986
30277
|
context,
|
|
@@ -30099,13 +30390,16 @@ function openMutationContext(manifest, input) {
|
|
|
30099
30390
|
metadata
|
|
30100
30391
|
};
|
|
30101
30392
|
}
|
|
30102
|
-
function prepareOwnershipFence(context, taskBundle) {
|
|
30393
|
+
function prepareOwnershipFence(context, taskBundle, expectedPredecessorBundleDigest) {
|
|
30103
30394
|
const metadata = metadataFromBundle2(taskBundle);
|
|
30104
30395
|
assertRemoteTaskEligible(metadata);
|
|
30105
30396
|
assertTaskBundleIdentity(taskBundle, context.taskRef);
|
|
30106
30397
|
if (metadata.ownerActorId === null) {
|
|
30107
30398
|
throw new Error("MANCODE_TASK_OWNER_REQUIRED");
|
|
30108
30399
|
}
|
|
30400
|
+
if ((context.taskBundle?.bundleDigest ?? null) !== expectedPredecessorBundleDigest) {
|
|
30401
|
+
throw new Error("MANCODE_TASK_BUNDLE_DIVERGED");
|
|
30402
|
+
}
|
|
30109
30403
|
if (context.fence === null) {
|
|
30110
30404
|
if (metadata.ownerActorId !== context.input.actorId || metadata.ownershipEpoch !== 0 || taskBundle.ownershipEpoch !== 0) {
|
|
30111
30405
|
throw new Error("MANCODE_TASK_OWNER_REQUIRED");
|
|
@@ -30119,14 +30413,45 @@ function prepareOwnershipFence(context, taskBundle) {
|
|
|
30119
30413
|
throw new Error("MANCODE_TASK_REVISION_CONFLICT");
|
|
30120
30414
|
}
|
|
30121
30415
|
if (taskBundle.taskRevision === context.fence.taskRevision) {
|
|
30122
|
-
if (taskBundle.aggregateDigest !== context.fence.aggregateDigest
|
|
30416
|
+
if (taskBundle.aggregateDigest !== context.fence.aggregateDigest) {
|
|
30123
30417
|
throw new Error("MANCODE_SPLIT_BRAIN");
|
|
30124
30418
|
}
|
|
30125
|
-
|
|
30419
|
+
if (taskBundle.codeRef.branch !== context.taskBundle?.codeRef.branch || taskBundle.codeRef.head === context.taskBundle?.codeRef.head) {
|
|
30420
|
+
throw new Error("MANCODE_REMOTE_FENCE_NO_CHANGE");
|
|
30421
|
+
}
|
|
30422
|
+
return prepared(
|
|
30423
|
+
context,
|
|
30424
|
+
buildFence(context, taskBundle, metadata.ownerActorId),
|
|
30425
|
+
refreshOwnerClaimsForCodeRef(context, taskBundle, metadata),
|
|
30426
|
+
context.handoffs,
|
|
30427
|
+
taskBundle
|
|
30428
|
+
);
|
|
30126
30429
|
}
|
|
30127
30430
|
}
|
|
30431
|
+
const codeHeadChanged = context.taskBundle !== null && (taskBundle.codeRef.branch !== context.taskBundle.codeRef.branch || taskBundle.codeRef.head !== context.taskBundle.codeRef.head);
|
|
30128
30432
|
const fence = buildFence(context, taskBundle, metadata.ownerActorId);
|
|
30129
|
-
return prepared(
|
|
30433
|
+
return prepared(
|
|
30434
|
+
context,
|
|
30435
|
+
fence,
|
|
30436
|
+
codeHeadChanged ? refreshOwnerClaimsForCodeRef(context, taskBundle, metadata) : context.claims,
|
|
30437
|
+
context.handoffs,
|
|
30438
|
+
taskBundle
|
|
30439
|
+
);
|
|
30440
|
+
}
|
|
30441
|
+
function refreshOwnerClaimsForCodeRef(context, taskBundle, metadata) {
|
|
30442
|
+
return context.claims.map((claim) => {
|
|
30443
|
+
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) {
|
|
30444
|
+
return claim;
|
|
30445
|
+
}
|
|
30446
|
+
const next = bindClaim(context, {
|
|
30447
|
+
...claim,
|
|
30448
|
+
revision: claim.revision + 1,
|
|
30449
|
+
lastValidatedTaskRevision: taskBundle.taskRevision,
|
|
30450
|
+
lastValidatedCodeRef: taskBundle.codeRef
|
|
30451
|
+
});
|
|
30452
|
+
assertClaimTransition(claim, next);
|
|
30453
|
+
return next;
|
|
30454
|
+
});
|
|
30130
30455
|
}
|
|
30131
30456
|
function prepareClaimAcquire(context, proposal, confirmScopeWarning) {
|
|
30132
30457
|
const { fence, taskBundle, metadata } = requireTaskContext(context);
|
|
@@ -30512,6 +30837,7 @@ function prepared(context, ownershipFence, claims, handoffs, taskBundle) {
|
|
|
30512
30837
|
claims: claims.map(parseClaim).sort(compareClaims2),
|
|
30513
30838
|
handoffs: handoffs.map(parseHandoff).sort(compareHandoffs2),
|
|
30514
30839
|
taskBundle,
|
|
30840
|
+
expectedTaskBundleDigest: context.taskBundle?.bundleDigest ?? null,
|
|
30515
30841
|
forwardRepair: null
|
|
30516
30842
|
};
|
|
30517
30843
|
}
|
|
@@ -31664,7 +31990,7 @@ function handoffSuccessorClaimId(operationId, predecessorClaimId, createdAt) {
|
|
|
31664
31990
|
}
|
|
31665
31991
|
|
|
31666
31992
|
// src/team/git-ref-operation.ts
|
|
31667
|
-
var
|
|
31993
|
+
var execFile9 = promisify8(execFileCallback6);
|
|
31668
31994
|
async function syncGitRefTask(input) {
|
|
31669
31995
|
const taskRef = requireSharedTask(input.taskRef);
|
|
31670
31996
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
@@ -31686,6 +32012,10 @@ async function syncGitRefTask(input) {
|
|
|
31686
32012
|
);
|
|
31687
32013
|
const snapshot = await transport.pull();
|
|
31688
32014
|
const bundle = await bundleFromContext(context, now);
|
|
32015
|
+
const remoteBase = await readGitRefTaskRemoteBase(
|
|
32016
|
+
context.projectRoot,
|
|
32017
|
+
taskRef
|
|
32018
|
+
);
|
|
31689
32019
|
const remoteTaskPublished = snapshot.manifest?.ownershipFences.some(
|
|
31690
32020
|
(fence) => sameTaskRef(fence.taskRef, taskRef)
|
|
31691
32021
|
) === true && snapshot.manifest.taskBundles.some(
|
|
@@ -31701,6 +32031,7 @@ async function syncGitRefTask(input) {
|
|
|
31701
32031
|
transport,
|
|
31702
32032
|
snapshot,
|
|
31703
32033
|
bundle,
|
|
32034
|
+
remoteBase?.bundle ?? null,
|
|
31704
32035
|
operationId,
|
|
31705
32036
|
now
|
|
31706
32037
|
);
|
|
@@ -31710,6 +32041,12 @@ async function syncGitRefTask(input) {
|
|
|
31710
32041
|
context.project.config,
|
|
31711
32042
|
refreshed
|
|
31712
32043
|
);
|
|
32044
|
+
const refreshedManifest = requireRemoteManifest(refreshed);
|
|
32045
|
+
await recordGitRefTaskRemoteBase(
|
|
32046
|
+
context.projectRoot,
|
|
32047
|
+
refreshedManifest.revision,
|
|
32048
|
+
requireRemoteBundle(refreshedManifest, taskRef)
|
|
32049
|
+
);
|
|
31713
32050
|
return { bundle, ...result2 };
|
|
31714
32051
|
} finally {
|
|
31715
32052
|
await context.release();
|
|
@@ -31741,6 +32078,10 @@ async function acquireGitRefClaim(input) {
|
|
|
31741
32078
|
);
|
|
31742
32079
|
let snapshot = await transport.pull();
|
|
31743
32080
|
const bundle = await bundleFromContext(context, now);
|
|
32081
|
+
const remoteBase = await readGitRefTaskRemoteBase(
|
|
32082
|
+
context.projectRoot,
|
|
32083
|
+
taskRef
|
|
32084
|
+
);
|
|
31744
32085
|
if (!remoteBundleMatches(snapshot, bundle)) {
|
|
31745
32086
|
await assertCleanGitWorktree(context.projectRoot);
|
|
31746
32087
|
const bootstrapOperationId = createUlid(now.getTime());
|
|
@@ -31749,6 +32090,7 @@ async function acquireGitRefClaim(input) {
|
|
|
31749
32090
|
transport,
|
|
31750
32091
|
snapshot,
|
|
31751
32092
|
bundle,
|
|
32093
|
+
remoteBase?.bundle ?? null,
|
|
31752
32094
|
bootstrapOperationId,
|
|
31753
32095
|
now
|
|
31754
32096
|
);
|
|
@@ -31756,6 +32098,11 @@ async function acquireGitRefClaim(input) {
|
|
|
31756
32098
|
}
|
|
31757
32099
|
const manifest = requireRemoteManifest(snapshot);
|
|
31758
32100
|
const fence = requireRemoteFence(manifest, taskRef);
|
|
32101
|
+
await recordGitRefTaskRemoteBase(
|
|
32102
|
+
context.projectRoot,
|
|
32103
|
+
manifest.revision,
|
|
32104
|
+
requireRemoteBundle(manifest, taskRef)
|
|
32105
|
+
);
|
|
31759
32106
|
const remote = context.project.config.transport.remote;
|
|
31760
32107
|
if (remote === null) throw new Error("MANCODE_TRANSPORT_UNAVAILABLE");
|
|
31761
32108
|
const remoteIdentityHash = await resolveGitRefRemoteIdentityHash(
|
|
@@ -31792,6 +32139,11 @@ async function acquireGitRefClaim(input) {
|
|
|
31792
32139
|
context.project.config,
|
|
31793
32140
|
refreshed
|
|
31794
32141
|
);
|
|
32142
|
+
await recordGitRefTaskRemoteBase(
|
|
32143
|
+
context.projectRoot,
|
|
32144
|
+
requireRemoteManifest(refreshed).revision,
|
|
32145
|
+
requireRemoteBundle(requireRemoteManifest(refreshed), taskRef)
|
|
32146
|
+
);
|
|
31795
32147
|
const claim = requireRemoteManifest(refreshed).claims.find(
|
|
31796
32148
|
(candidate) => candidate.claimId === claimId
|
|
31797
32149
|
);
|
|
@@ -32245,7 +32597,7 @@ async function assertCleanGitWorktree(projectRoot, materializedTaskRef) {
|
|
|
32245
32597
|
`:(exclude,top).mancode/shared/workflows/${materializedTaskRef.taskId}/**`
|
|
32246
32598
|
);
|
|
32247
32599
|
}
|
|
32248
|
-
const { stdout: stdout2 } = await
|
|
32600
|
+
const { stdout: stdout2 } = await execFile9("git", args, {
|
|
32249
32601
|
cwd: projectRoot,
|
|
32250
32602
|
windowsHide: true
|
|
32251
32603
|
});
|
|
@@ -32274,7 +32626,7 @@ function freezeDeep(value) {
|
|
|
32274
32626
|
for (const child of Object.values(value)) freezeDeep(child);
|
|
32275
32627
|
return Object.freeze(value);
|
|
32276
32628
|
}
|
|
32277
|
-
async function synchronizeBundle(context, transport, snapshot, bundle, operationId, now) {
|
|
32629
|
+
async function synchronizeBundle(context, transport, snapshot, bundle, remoteBase, operationId, now) {
|
|
32278
32630
|
const manifest = requireRemoteManifest(snapshot);
|
|
32279
32631
|
const fence = manifest.ownershipFences.find(
|
|
32280
32632
|
(candidate) => sameTaskRef(candidate.taskRef, context.taskRef)
|
|
@@ -32287,6 +32639,16 @@ async function synchronizeBundle(context, transport, snapshot, bundle, operation
|
|
|
32287
32639
|
changed: false
|
|
32288
32640
|
};
|
|
32289
32641
|
}
|
|
32642
|
+
if (fence !== void 0 && fence.ownerActorId !== context.session.actorId) {
|
|
32643
|
+
throw new Error("MANCODE_TASK_OWNER_REQUIRED");
|
|
32644
|
+
}
|
|
32645
|
+
const remoteBundle = fence === void 0 ? null : requireRemoteBundle(manifest, context.taskRef);
|
|
32646
|
+
if (remoteBundle === null !== (remoteBase === null) || remoteBundle !== null && (remoteBase === null || remoteBundle.bundleDigest !== remoteBase.bundleDigest)) {
|
|
32647
|
+
throw new Error("MANCODE_TASK_BUNDLE_DIVERGED");
|
|
32648
|
+
}
|
|
32649
|
+
if (remoteBundle !== null) {
|
|
32650
|
+
await assertCodeRefFastForward(context.projectRoot, remoteBundle, bundle);
|
|
32651
|
+
}
|
|
32290
32652
|
const mutation = prepareGitRefCoordinationMutation(manifest, {
|
|
32291
32653
|
kind: "ownership_fence",
|
|
32292
32654
|
operationId,
|
|
@@ -32294,6 +32656,7 @@ async function synchronizeBundle(context, transport, snapshot, bundle, operation
|
|
|
32294
32656
|
taskRef: context.taskRef,
|
|
32295
32657
|
expectedRemoteRevision: manifest.revision,
|
|
32296
32658
|
expectedOwnershipEpoch: fence?.ownershipEpoch ?? 0,
|
|
32659
|
+
expectedPredecessorBundleDigest: remoteBundle?.bundleDigest ?? null,
|
|
32297
32660
|
taskBundle: bundle,
|
|
32298
32661
|
now
|
|
32299
32662
|
});
|
|
@@ -32352,6 +32715,21 @@ function remoteBundleMatches(snapshot, bundle) {
|
|
|
32352
32715
|
);
|
|
32353
32716
|
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
32717
|
}
|
|
32718
|
+
async function assertCodeRefFastForward(projectRoot, previous, next) {
|
|
32719
|
+
if (previous.codeRef.branch !== next.codeRef.branch) {
|
|
32720
|
+
throw new Error("MANCODE_TASK_BUNDLE_DIVERGED");
|
|
32721
|
+
}
|
|
32722
|
+
if (previous.codeRef.head === next.codeRef.head) return;
|
|
32723
|
+
try {
|
|
32724
|
+
await execFile9(
|
|
32725
|
+
"git",
|
|
32726
|
+
["merge-base", "--is-ancestor", previous.codeRef.head, next.codeRef.head],
|
|
32727
|
+
{ cwd: projectRoot, windowsHide: true }
|
|
32728
|
+
);
|
|
32729
|
+
} catch {
|
|
32730
|
+
throw new Error("MANCODE_TASK_BUNDLE_DIVERGED");
|
|
32731
|
+
}
|
|
32732
|
+
}
|
|
32355
32733
|
function requireRemoteManifest(snapshot) {
|
|
32356
32734
|
if (snapshot.manifest === null) {
|
|
32357
32735
|
throw new Error("MANCODE_TRANSPORT_ACTOR_NOT_JOINED");
|
|
@@ -32441,7 +32819,7 @@ async function recoverGitRefHandoffRepairs(projectRoot) {
|
|
|
32441
32819
|
}
|
|
32442
32820
|
async function recoverGitRefHandoffRepair(projectRoot, operationId, transportReceipt) {
|
|
32443
32821
|
assertUlid(operationId, "git-ref handoff repair operationId");
|
|
32444
|
-
const root =
|
|
32822
|
+
const root = path57.resolve(projectRoot);
|
|
32445
32823
|
let journal = await requireJournal2(root, operationId);
|
|
32446
32824
|
if (journal.state === "committed" || journal.state === "aborted") {
|
|
32447
32825
|
return recoveryResult2(journal);
|
|
@@ -32502,6 +32880,7 @@ async function recoverGitRefHandoffRepair(projectRoot, operationId, transportRec
|
|
|
32502
32880
|
bundle: journal.prepared.targetBundle,
|
|
32503
32881
|
predecessorBundle: journal.prepared.predecessorBundle,
|
|
32504
32882
|
pendingMetadata: journal.pendingMetadata,
|
|
32883
|
+
taskLockHeld: true,
|
|
32505
32884
|
operationId: createUlid()
|
|
32506
32885
|
});
|
|
32507
32886
|
journal = await transitionJournal2(
|
|
@@ -32519,7 +32898,7 @@ async function recoverGitRefHandoffRepair(projectRoot, operationId, transportRec
|
|
|
32519
32898
|
}
|
|
32520
32899
|
}
|
|
32521
32900
|
async function prepareHandoffRepairWhileTaskLocked(projectRoot, rawPrepared) {
|
|
32522
|
-
const root =
|
|
32901
|
+
const root = path57.resolve(projectRoot);
|
|
32523
32902
|
const prepared2 = parsePrepared2(rawPrepared);
|
|
32524
32903
|
const runtime = await readProjectRuntimeContext(root);
|
|
32525
32904
|
const previousMetadata = bundleMetadata2(prepared2.predecessorBundle);
|
|
@@ -32582,7 +32961,7 @@ async function restorePredecessorMetadata2(projectRoot, journal) {
|
|
|
32582
32961
|
);
|
|
32583
32962
|
}
|
|
32584
32963
|
async function replaceMetadataVerified(projectRoot, expected, targetMetadata, alternateExpected) {
|
|
32585
|
-
const target =
|
|
32964
|
+
const target = path57.join(
|
|
32586
32965
|
taskRootPath(projectRoot, targetMetadata.taskRef),
|
|
32587
32966
|
"metadata.json"
|
|
32588
32967
|
);
|
|
@@ -32708,12 +33087,12 @@ async function createJournal3(projectRoot, journal) {
|
|
|
32708
33087
|
await ensureJournalDirectory2(projectRoot);
|
|
32709
33088
|
const target = journalPath3(projectRoot, journal.operationId);
|
|
32710
33089
|
try {
|
|
32711
|
-
await
|
|
33090
|
+
await writeFile39(target, serialize13(journal), {
|
|
32712
33091
|
encoding: "utf8",
|
|
32713
33092
|
flag: "wx"
|
|
32714
33093
|
});
|
|
32715
33094
|
} catch (error) {
|
|
32716
|
-
if (!
|
|
33095
|
+
if (!isAlreadyExists23(error)) throw error;
|
|
32717
33096
|
const existing = await requireJournal2(projectRoot, journal.operationId);
|
|
32718
33097
|
if (digestCanonicalJson(existing) !== digestCanonicalJson(journal)) {
|
|
32719
33098
|
throw new Error("MANCODE_HANDOFF_REPAIR_JOURNAL_CONFLICT");
|
|
@@ -32727,10 +33106,10 @@ async function replaceJournal3(projectRoot, journal) {
|
|
|
32727
33106
|
async function requireJournal2(projectRoot, operationId) {
|
|
32728
33107
|
try {
|
|
32729
33108
|
return parseJournal3(
|
|
32730
|
-
JSON.parse(await
|
|
33109
|
+
JSON.parse(await readFile39(journalPath3(projectRoot, operationId), "utf8"))
|
|
32731
33110
|
);
|
|
32732
33111
|
} catch (error) {
|
|
32733
|
-
if (error instanceof SyntaxError ||
|
|
33112
|
+
if (error instanceof SyntaxError || isNotFound27(error)) {
|
|
32734
33113
|
throw new Error("MANCODE_HANDOFF_REPAIR_JOURNAL_NOT_FOUND");
|
|
32735
33114
|
}
|
|
32736
33115
|
throw error;
|
|
@@ -32739,9 +33118,9 @@ async function requireJournal2(projectRoot, operationId) {
|
|
|
32739
33118
|
async function listJournals2(projectRoot) {
|
|
32740
33119
|
let entries;
|
|
32741
33120
|
try {
|
|
32742
|
-
entries = await
|
|
33121
|
+
entries = await readdir18(journalDirectory2(projectRoot));
|
|
32743
33122
|
} catch (error) {
|
|
32744
|
-
if (
|
|
33123
|
+
if (isNotFound27(error)) return [];
|
|
32745
33124
|
throw error;
|
|
32746
33125
|
}
|
|
32747
33126
|
const journals = [];
|
|
@@ -32750,8 +33129,8 @@ async function listJournals2(projectRoot) {
|
|
|
32750
33129
|
journals.push(
|
|
32751
33130
|
parseJournal3(
|
|
32752
33131
|
JSON.parse(
|
|
32753
|
-
await
|
|
32754
|
-
|
|
33132
|
+
await readFile39(
|
|
33133
|
+
path57.join(journalDirectory2(projectRoot), entry),
|
|
32755
33134
|
"utf8"
|
|
32756
33135
|
)
|
|
32757
33136
|
)
|
|
@@ -32761,43 +33140,43 @@ async function listJournals2(projectRoot) {
|
|
|
32761
33140
|
return journals;
|
|
32762
33141
|
}
|
|
32763
33142
|
async function readSafeFile2(target) {
|
|
32764
|
-
const before = await
|
|
33143
|
+
const before = await lstat20(target);
|
|
32765
33144
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
32766
33145
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
32767
33146
|
}
|
|
32768
|
-
const content = await
|
|
32769
|
-
const after = await
|
|
33147
|
+
const content = await readFile39(target, "utf8");
|
|
33148
|
+
const after = await lstat20(target);
|
|
32770
33149
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
32771
33150
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
32772
33151
|
}
|
|
32773
33152
|
return content;
|
|
32774
33153
|
}
|
|
32775
33154
|
async function atomicWrite2(target, content) {
|
|
32776
|
-
const temporary =
|
|
32777
|
-
|
|
32778
|
-
`.${
|
|
33155
|
+
const temporary = path57.join(
|
|
33156
|
+
path57.dirname(target),
|
|
33157
|
+
`.${path57.basename(target)}.${process.pid}.${Date.now()}.tmp`
|
|
32779
33158
|
);
|
|
32780
|
-
await
|
|
33159
|
+
await writeFile39(temporary, content, { encoding: "utf8", flag: "wx" });
|
|
32781
33160
|
await replaceFileAtomically(temporary, target);
|
|
32782
33161
|
}
|
|
32783
33162
|
async function ensureJournalDirectory2(projectRoot) {
|
|
32784
|
-
let current =
|
|
33163
|
+
let current = path57.resolve(projectRoot);
|
|
32785
33164
|
for (const segment of [".mancode", "local", "journals", "git-ref-handoff"]) {
|
|
32786
|
-
current =
|
|
33165
|
+
current = path57.join(current, segment);
|
|
32787
33166
|
try {
|
|
32788
|
-
await
|
|
33167
|
+
await mkdir34(current);
|
|
32789
33168
|
} catch (error) {
|
|
32790
|
-
if (!
|
|
33169
|
+
if (!isAlreadyExists23(error)) throw error;
|
|
32791
33170
|
}
|
|
32792
|
-
const entry = await
|
|
33171
|
+
const entry = await lstat20(current);
|
|
32793
33172
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
32794
33173
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
32795
33174
|
}
|
|
32796
33175
|
}
|
|
32797
33176
|
}
|
|
32798
33177
|
function journalDirectory2(projectRoot) {
|
|
32799
|
-
return
|
|
32800
|
-
|
|
33178
|
+
return path57.join(
|
|
33179
|
+
path57.resolve(projectRoot),
|
|
32801
33180
|
".mancode",
|
|
32802
33181
|
"local",
|
|
32803
33182
|
"journals",
|
|
@@ -32806,7 +33185,7 @@ function journalDirectory2(projectRoot) {
|
|
|
32806
33185
|
}
|
|
32807
33186
|
function journalPath3(projectRoot, operationId) {
|
|
32808
33187
|
assertUlid(operationId, "git-ref handoff repair operationId");
|
|
32809
|
-
return
|
|
33188
|
+
return path57.join(journalDirectory2(projectRoot), `${operationId}.json`);
|
|
32810
33189
|
}
|
|
32811
33190
|
function serialize13(value) {
|
|
32812
33191
|
return `${JSON.stringify(value, null, 2)}
|
|
@@ -32818,10 +33197,10 @@ function parseTimestamp14(value) {
|
|
|
32818
33197
|
}
|
|
32819
33198
|
return value;
|
|
32820
33199
|
}
|
|
32821
|
-
function
|
|
33200
|
+
function isAlreadyExists23(error) {
|
|
32822
33201
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
32823
33202
|
}
|
|
32824
|
-
function
|
|
33203
|
+
function isNotFound27(error) {
|
|
32825
33204
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
32826
33205
|
}
|
|
32827
33206
|
|
|
@@ -32905,8 +33284,8 @@ function parseReceipt(value) {
|
|
|
32905
33284
|
}
|
|
32906
33285
|
|
|
32907
33286
|
// src/team/policy-operation.ts
|
|
32908
|
-
import { lstat as
|
|
32909
|
-
import
|
|
33287
|
+
import { lstat as lstat21, mkdir as mkdir35, readdir as readdir19, unlink as unlink3, writeFile as writeFile40 } from "fs/promises";
|
|
33288
|
+
import path58 from "path";
|
|
32910
33289
|
async function updateTeamPolicy(input) {
|
|
32911
33290
|
const operationId = input.operationId ?? createUlid();
|
|
32912
33291
|
const eventId = createUlid();
|
|
@@ -32917,7 +33296,7 @@ async function updateTeamPolicy(input) {
|
|
|
32917
33296
|
throw new Error("MANCODE_TEAM_POLICY_INVALID");
|
|
32918
33297
|
}
|
|
32919
33298
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
32920
|
-
const root =
|
|
33299
|
+
const root = path58.resolve(input.projectRoot);
|
|
32921
33300
|
const runtime = await readProjectRuntimeContext(root);
|
|
32922
33301
|
const store = resolveCoordinationEntityHomeStore(
|
|
32923
33302
|
runtime.entityHomeStoreContext
|
|
@@ -32998,7 +33377,7 @@ async function applyTeamTransportSet(input, write2) {
|
|
|
32998
33377
|
}
|
|
32999
33378
|
const remote = transportRemote(input.mode, input.remote);
|
|
33000
33379
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
33001
|
-
const root =
|
|
33380
|
+
const root = path58.resolve(input.projectRoot);
|
|
33002
33381
|
const runtime = await readProjectRuntimeContext(root);
|
|
33003
33382
|
const store = resolveCoordinationEntityHomeStore(
|
|
33004
33383
|
runtime.entityHomeStoreContext
|
|
@@ -33131,9 +33510,9 @@ async function assertTransportAuthorityEmpty(projectRoot, store) {
|
|
|
33131
33510
|
listClaims(store),
|
|
33132
33511
|
listHandoffs(store),
|
|
33133
33512
|
directoryHasEntries(taskHeadDirectory(store)),
|
|
33134
|
-
directoryHasEntries(
|
|
33513
|
+
directoryHasEntries(path58.join(store.root, "transport-migrations")),
|
|
33135
33514
|
directoryHasEntries(
|
|
33136
|
-
|
|
33515
|
+
path58.join(projectRoot, ".mancode", "shared", "team", "transport")
|
|
33137
33516
|
),
|
|
33138
33517
|
pathExists14(gitRefCachePath(projectRoot))
|
|
33139
33518
|
]);
|
|
@@ -33163,21 +33542,21 @@ function assertPositiveRevision5(value, label) {
|
|
|
33163
33542
|
}
|
|
33164
33543
|
}
|
|
33165
33544
|
function teamPolicyPath(projectRoot) {
|
|
33166
|
-
return
|
|
33545
|
+
return path58.join(projectRoot, ".mancode", "shared", "team", "policy.json");
|
|
33167
33546
|
}
|
|
33168
33547
|
function projectConfigPath(projectRoot) {
|
|
33169
|
-
return
|
|
33548
|
+
return path58.join(projectRoot, ".mancode", "shared", "config.json");
|
|
33170
33549
|
}
|
|
33171
33550
|
async function writeJsonAtomic4(target, value) {
|
|
33172
|
-
await
|
|
33173
|
-
await assertPlainDirectory(
|
|
33551
|
+
await mkdir35(path58.dirname(target), { recursive: true });
|
|
33552
|
+
await assertPlainDirectory(path58.dirname(target));
|
|
33174
33553
|
await assertPlainFileOrMissing(target);
|
|
33175
|
-
const temporary =
|
|
33176
|
-
|
|
33177
|
-
`.${
|
|
33554
|
+
const temporary = path58.join(
|
|
33555
|
+
path58.dirname(target),
|
|
33556
|
+
`.${path58.basename(target)}.${process.pid}.${createUlid()}.tmp`
|
|
33178
33557
|
);
|
|
33179
33558
|
try {
|
|
33180
|
-
await
|
|
33559
|
+
await writeFile40(temporary, `${JSON.stringify(value, null, 2)}
|
|
33181
33560
|
`, {
|
|
33182
33561
|
encoding: "utf8",
|
|
33183
33562
|
flag: "wx"
|
|
@@ -33189,61 +33568,61 @@ async function writeJsonAtomic4(target, value) {
|
|
|
33189
33568
|
}
|
|
33190
33569
|
}
|
|
33191
33570
|
async function assertPlainDirectory(target) {
|
|
33192
|
-
const entry = await
|
|
33571
|
+
const entry = await lstat21(target);
|
|
33193
33572
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
33194
33573
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
33195
33574
|
}
|
|
33196
33575
|
}
|
|
33197
33576
|
async function assertPlainFileOrMissing(target) {
|
|
33198
33577
|
try {
|
|
33199
|
-
const entry = await
|
|
33578
|
+
const entry = await lstat21(target);
|
|
33200
33579
|
if (!entry.isFile() || entry.isSymbolicLink()) {
|
|
33201
33580
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
33202
33581
|
}
|
|
33203
33582
|
} catch (error) {
|
|
33204
|
-
if (
|
|
33583
|
+
if (isNotFound28(error)) return;
|
|
33205
33584
|
throw error;
|
|
33206
33585
|
}
|
|
33207
33586
|
}
|
|
33208
33587
|
async function directoryHasEntries(target) {
|
|
33209
33588
|
try {
|
|
33210
|
-
const entry = await
|
|
33589
|
+
const entry = await lstat21(target);
|
|
33211
33590
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
33212
33591
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
33213
33592
|
}
|
|
33214
|
-
return (await
|
|
33593
|
+
return (await readdir19(target)).length > 0;
|
|
33215
33594
|
} catch (error) {
|
|
33216
|
-
if (
|
|
33595
|
+
if (isNotFound28(error)) return false;
|
|
33217
33596
|
throw error;
|
|
33218
33597
|
}
|
|
33219
33598
|
}
|
|
33220
33599
|
async function pathExists14(target) {
|
|
33221
33600
|
try {
|
|
33222
|
-
await
|
|
33601
|
+
await lstat21(target);
|
|
33223
33602
|
return true;
|
|
33224
33603
|
} catch (error) {
|
|
33225
|
-
if (
|
|
33604
|
+
if (isNotFound28(error)) return false;
|
|
33226
33605
|
throw error;
|
|
33227
33606
|
}
|
|
33228
33607
|
}
|
|
33229
33608
|
async function releaseLocks3(locks) {
|
|
33230
33609
|
await Promise.allSettled([...locks].reverse().map((lock) => lock.release()));
|
|
33231
33610
|
}
|
|
33232
|
-
function
|
|
33611
|
+
function isNotFound28(error) {
|
|
33233
33612
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
33234
33613
|
}
|
|
33235
33614
|
|
|
33236
33615
|
// src/team/transport-migration-adapters.ts
|
|
33237
33616
|
import {
|
|
33238
|
-
lstat as
|
|
33239
|
-
mkdir as
|
|
33240
|
-
readFile as
|
|
33241
|
-
readdir as
|
|
33617
|
+
lstat as lstat22,
|
|
33618
|
+
mkdir as mkdir36,
|
|
33619
|
+
readFile as readFile40,
|
|
33620
|
+
readdir as readdir20,
|
|
33242
33621
|
rename as rename10,
|
|
33243
33622
|
unlink as unlink4,
|
|
33244
|
-
writeFile as
|
|
33623
|
+
writeFile as writeFile41
|
|
33245
33624
|
} from "fs/promises";
|
|
33246
|
-
import
|
|
33625
|
+
import path59 from "path";
|
|
33247
33626
|
|
|
33248
33627
|
// src/team/transport-migration.ts
|
|
33249
33628
|
var DIGEST_PATTERN7 = /^sha256:[a-f0-9]{64}$/;
|
|
@@ -34315,7 +34694,7 @@ function compareUtf812(left, right) {
|
|
|
34315
34694
|
var STAGE_DIRECTORY = "transport-migrations";
|
|
34316
34695
|
var COLLECTIONS = ["claims", "handoffs", "task-heads"];
|
|
34317
34696
|
async function createTransportMigrationFileAdapters(input) {
|
|
34318
|
-
const projectRoot =
|
|
34697
|
+
const projectRoot = path59.resolve(input.projectRoot);
|
|
34319
34698
|
assertUlid(input.actorId, "transport migration adapter actorId");
|
|
34320
34699
|
if (input.operationId !== void 0) {
|
|
34321
34700
|
assertUlid(input.operationId, "transport migration adapter operationId");
|
|
@@ -34367,7 +34746,7 @@ async function createTransportMigrationFileAdapters(input) {
|
|
|
34367
34746
|
var FileSystemTransportMigrationConfigAdapter = class {
|
|
34368
34747
|
constructor(projectRoot, coordinationStore) {
|
|
34369
34748
|
this.coordinationStore = coordinationStore;
|
|
34370
|
-
this.projectRoot =
|
|
34749
|
+
this.projectRoot = path59.resolve(projectRoot);
|
|
34371
34750
|
}
|
|
34372
34751
|
coordinationStore;
|
|
34373
34752
|
projectRoot;
|
|
@@ -35230,27 +35609,27 @@ async function publishMigrationActorProfiles(projectRoot, profiles) {
|
|
|
35230
35609
|
}
|
|
35231
35610
|
}
|
|
35232
35611
|
async function archiveLocalCoordinationCollections(store, operationId) {
|
|
35233
|
-
const archiveRoot =
|
|
35612
|
+
const archiveRoot = path59.join(
|
|
35234
35613
|
store.root,
|
|
35235
35614
|
STAGE_DIRECTORY,
|
|
35236
35615
|
"archive",
|
|
35237
35616
|
operationId
|
|
35238
35617
|
);
|
|
35239
|
-
await
|
|
35618
|
+
await mkdir36(archiveRoot, { recursive: true });
|
|
35240
35619
|
const directories = {
|
|
35241
35620
|
claims: claimDirectory(store),
|
|
35242
35621
|
handoffs: handoffDirectory(store),
|
|
35243
35622
|
"task-heads": taskHeadDirectory(store)
|
|
35244
35623
|
};
|
|
35245
35624
|
for (const name of COLLECTIONS) {
|
|
35246
|
-
const archived =
|
|
35247
|
-
const absent =
|
|
35625
|
+
const archived = path59.join(archiveRoot, name);
|
|
35626
|
+
const absent = path59.join(archiveRoot, `${name}.absent`);
|
|
35248
35627
|
if (await pathKind(archived) === "directory" || await pathKind(absent) === "file") {
|
|
35249
35628
|
continue;
|
|
35250
35629
|
}
|
|
35251
35630
|
const sourceKind = await pathKind(directories[name]);
|
|
35252
35631
|
if (sourceKind === null) {
|
|
35253
|
-
await
|
|
35632
|
+
await writeFile41(absent, "\n", { encoding: "utf8", flag: "wx" });
|
|
35254
35633
|
continue;
|
|
35255
35634
|
}
|
|
35256
35635
|
if (sourceKind !== "directory") {
|
|
@@ -35263,9 +35642,9 @@ async function listActorProfiles(projectRoot) {
|
|
|
35263
35642
|
const directory = sharedActorProfileDirectory(projectRoot);
|
|
35264
35643
|
let entries;
|
|
35265
35644
|
try {
|
|
35266
|
-
entries = await
|
|
35645
|
+
entries = await readdir20(directory);
|
|
35267
35646
|
} catch (error) {
|
|
35268
|
-
if (
|
|
35647
|
+
if (isNotFound29(error)) return [];
|
|
35269
35648
|
throw error;
|
|
35270
35649
|
}
|
|
35271
35650
|
const profiles = [];
|
|
@@ -35282,18 +35661,18 @@ async function listActorProfiles(projectRoot) {
|
|
|
35282
35661
|
return profiles;
|
|
35283
35662
|
}
|
|
35284
35663
|
async function listSharedTaskRefs(projectRoot) {
|
|
35285
|
-
const directory =
|
|
35664
|
+
const directory = path59.join(projectRoot, ".mancode", "shared", "workflows");
|
|
35286
35665
|
let entries;
|
|
35287
35666
|
try {
|
|
35288
|
-
entries = await
|
|
35667
|
+
entries = await readdir20(directory);
|
|
35289
35668
|
} catch (error) {
|
|
35290
|
-
if (
|
|
35669
|
+
if (isNotFound29(error)) return [];
|
|
35291
35670
|
throw error;
|
|
35292
35671
|
}
|
|
35293
35672
|
const refs = [];
|
|
35294
35673
|
for (const taskId of entries.sort(compareUtf813)) {
|
|
35295
35674
|
assertUlid(taskId, "shared workflow directory");
|
|
35296
|
-
const stat4 = await
|
|
35675
|
+
const stat4 = await lstat22(path59.join(directory, taskId));
|
|
35297
35676
|
if (!stat4.isDirectory() || stat4.isSymbolicLink()) {
|
|
35298
35677
|
throw new Error("MANCODE_CONTEXT_PATH_UNSAFE");
|
|
35299
35678
|
}
|
|
@@ -35305,7 +35684,7 @@ async function readTaskSnapshotOrNull(projectRoot, taskRef) {
|
|
|
35305
35684
|
try {
|
|
35306
35685
|
return await new V3ContextStore(projectRoot).readTaskSnapshot(taskRef);
|
|
35307
35686
|
} catch (error) {
|
|
35308
|
-
if (error instanceof Error && (error.message === "MANCODE_TASK_NOT_FOUND" ||
|
|
35687
|
+
if (error instanceof Error && (error.message === "MANCODE_TASK_NOT_FOUND" || isNotFound29(error))) {
|
|
35309
35688
|
return null;
|
|
35310
35689
|
}
|
|
35311
35690
|
throw error;
|
|
@@ -35367,7 +35746,7 @@ async function readStagedRecord(store, operationId) {
|
|
|
35367
35746
|
);
|
|
35368
35747
|
}
|
|
35369
35748
|
function stagedPath(store, operationId) {
|
|
35370
|
-
return
|
|
35749
|
+
return path59.join(
|
|
35371
35750
|
store.root,
|
|
35372
35751
|
STAGE_DIRECTORY,
|
|
35373
35752
|
"staged",
|
|
@@ -35375,7 +35754,7 @@ function stagedPath(store, operationId) {
|
|
|
35375
35754
|
);
|
|
35376
35755
|
}
|
|
35377
35756
|
function establishedPath(store, operationId) {
|
|
35378
|
-
return
|
|
35757
|
+
return path59.join(
|
|
35379
35758
|
store.root,
|
|
35380
35759
|
STAGE_DIRECTORY,
|
|
35381
35760
|
"established",
|
|
@@ -35383,12 +35762,12 @@ function establishedPath(store, operationId) {
|
|
|
35383
35762
|
);
|
|
35384
35763
|
}
|
|
35385
35764
|
function projectConfigPath2(projectRoot) {
|
|
35386
|
-
return
|
|
35765
|
+
return path59.join(projectRoot, ".mancode", "shared", "config.json");
|
|
35387
35766
|
}
|
|
35388
35767
|
async function readProjectConfigFile(projectRoot) {
|
|
35389
35768
|
try {
|
|
35390
35769
|
return parseProjectConfig(
|
|
35391
|
-
JSON.parse(await
|
|
35770
|
+
JSON.parse(await readFile40(projectConfigPath2(projectRoot), "utf8"))
|
|
35392
35771
|
);
|
|
35393
35772
|
} catch (error) {
|
|
35394
35773
|
if (error instanceof SyntaxError) {
|
|
@@ -35398,14 +35777,14 @@ async function readProjectConfigFile(projectRoot) {
|
|
|
35398
35777
|
}
|
|
35399
35778
|
}
|
|
35400
35779
|
async function writeJsonAtomic5(target, value) {
|
|
35401
|
-
await
|
|
35402
|
-
await assertPlainDirectory2(
|
|
35403
|
-
const temporary =
|
|
35404
|
-
|
|
35405
|
-
`.${
|
|
35780
|
+
await mkdir36(path59.dirname(target), { recursive: true });
|
|
35781
|
+
await assertPlainDirectory2(path59.dirname(target));
|
|
35782
|
+
const temporary = path59.join(
|
|
35783
|
+
path59.dirname(target),
|
|
35784
|
+
`.${path59.basename(target)}.${process.pid}.${createUlid()}.tmp`
|
|
35406
35785
|
);
|
|
35407
35786
|
try {
|
|
35408
|
-
await
|
|
35787
|
+
await writeFile41(temporary, serialize14(value), {
|
|
35409
35788
|
encoding: "utf8",
|
|
35410
35789
|
flag: "wx"
|
|
35411
35790
|
});
|
|
@@ -35416,12 +35795,12 @@ async function writeJsonAtomic5(target, value) {
|
|
|
35416
35795
|
}
|
|
35417
35796
|
}
|
|
35418
35797
|
async function writeJsonExclusiveOrEqual(target, value, parser, conflictCode) {
|
|
35419
|
-
await
|
|
35420
|
-
await assertPlainDirectory2(
|
|
35798
|
+
await mkdir36(path59.dirname(target), { recursive: true });
|
|
35799
|
+
await assertPlainDirectory2(path59.dirname(target));
|
|
35421
35800
|
try {
|
|
35422
|
-
await
|
|
35801
|
+
await writeFile41(target, serialize14(value), { encoding: "utf8", flag: "wx" });
|
|
35423
35802
|
} catch (error) {
|
|
35424
|
-
if (!
|
|
35803
|
+
if (!isAlreadyExists24(error)) throw error;
|
|
35425
35804
|
const existing = await readJsonOrNull5(target, parser, conflictCode);
|
|
35426
35805
|
if (existing !== null && digestCanonicalJson(existing) === digestCanonicalJson(value)) {
|
|
35427
35806
|
return;
|
|
@@ -35431,18 +35810,18 @@ async function writeJsonExclusiveOrEqual(target, value, parser, conflictCode) {
|
|
|
35431
35810
|
}
|
|
35432
35811
|
async function readJsonOrNull5(target, parser, corruptCode) {
|
|
35433
35812
|
try {
|
|
35434
|
-
const before = await
|
|
35813
|
+
const before = await lstat22(target);
|
|
35435
35814
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
35436
35815
|
throw new Error("MANCODE_TRANSPORT_MIGRATION_STAGE_UNSAFE");
|
|
35437
35816
|
}
|
|
35438
|
-
const parsed = parser(JSON.parse(await
|
|
35439
|
-
const after = await
|
|
35817
|
+
const parsed = parser(JSON.parse(await readFile40(target, "utf8")));
|
|
35818
|
+
const after = await lstat22(target);
|
|
35440
35819
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
35441
35820
|
throw new Error("MANCODE_TRANSPORT_MIGRATION_STAGE_UNSAFE");
|
|
35442
35821
|
}
|
|
35443
35822
|
return parsed;
|
|
35444
35823
|
} catch (error) {
|
|
35445
|
-
if (
|
|
35824
|
+
if (isNotFound29(error)) return null;
|
|
35446
35825
|
if (error instanceof SyntaxError) throw new Error(corruptCode);
|
|
35447
35826
|
throw error;
|
|
35448
35827
|
}
|
|
@@ -35494,18 +35873,18 @@ function requireRemote(value) {
|
|
|
35494
35873
|
}
|
|
35495
35874
|
async function pathKind(target) {
|
|
35496
35875
|
try {
|
|
35497
|
-
const stat4 = await
|
|
35876
|
+
const stat4 = await lstat22(target);
|
|
35498
35877
|
if (stat4.isSymbolicLink()) return "other";
|
|
35499
35878
|
if (stat4.isFile()) return "file";
|
|
35500
35879
|
if (stat4.isDirectory()) return "directory";
|
|
35501
35880
|
return "other";
|
|
35502
35881
|
} catch (error) {
|
|
35503
|
-
if (
|
|
35882
|
+
if (isNotFound29(error)) return null;
|
|
35504
35883
|
throw error;
|
|
35505
35884
|
}
|
|
35506
35885
|
}
|
|
35507
35886
|
async function assertPlainDirectory2(target) {
|
|
35508
|
-
const stat4 = await
|
|
35887
|
+
const stat4 = await lstat22(target);
|
|
35509
35888
|
if (!stat4.isDirectory() || stat4.isSymbolicLink()) {
|
|
35510
35889
|
throw new Error("MANCODE_TRANSPORT_MIGRATION_STAGE_UNSAFE");
|
|
35511
35890
|
}
|
|
@@ -35514,7 +35893,7 @@ async function unlinkIfExists2(target) {
|
|
|
35514
35893
|
try {
|
|
35515
35894
|
await unlink4(target);
|
|
35516
35895
|
} catch (error) {
|
|
35517
|
-
if (!
|
|
35896
|
+
if (!isNotFound29(error)) throw error;
|
|
35518
35897
|
}
|
|
35519
35898
|
}
|
|
35520
35899
|
function serialize14(value) {
|
|
@@ -35524,10 +35903,10 @@ function serialize14(value) {
|
|
|
35524
35903
|
function compareUtf813(left, right) {
|
|
35525
35904
|
return Buffer.from(left, "utf8").compare(Buffer.from(right, "utf8"));
|
|
35526
35905
|
}
|
|
35527
|
-
function
|
|
35906
|
+
function isAlreadyExists24(error) {
|
|
35528
35907
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
35529
35908
|
}
|
|
35530
|
-
function
|
|
35909
|
+
function isNotFound29(error) {
|
|
35531
35910
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
35532
35911
|
}
|
|
35533
35912
|
|
|
@@ -36967,16 +37346,16 @@ function parsePositiveInteger5(value) {
|
|
|
36967
37346
|
}
|
|
36968
37347
|
|
|
36969
37348
|
// src/commands/uninstall.ts
|
|
36970
|
-
import { access as access5, readFile as
|
|
36971
|
-
import
|
|
37349
|
+
import { access as access5, readFile as readFile41, rm as rm17, writeFile as writeFile42 } from "fs/promises";
|
|
37350
|
+
import path60 from "path";
|
|
36972
37351
|
import process11 from "process";
|
|
36973
37352
|
var EXIT_OK9 = 0;
|
|
36974
37353
|
var EXIT_NOT_INITIALIZED6 = 1;
|
|
36975
37354
|
var EXIT_UNSUPPORTED_PLATFORM2 = 2;
|
|
36976
37355
|
var EXIT_V3_AUTHORITY_PROTECTED = 3;
|
|
36977
37356
|
async function uninstall(rootDir = process11.cwd(), platform, options = {}) {
|
|
36978
|
-
const stateFile =
|
|
36979
|
-
const v3SchemaFile =
|
|
37357
|
+
const stateFile = path60.join(rootDir, ".mancode", "state.json");
|
|
37358
|
+
const v3SchemaFile = path60.join(rootDir, ".mancode", "schema.json");
|
|
36980
37359
|
if (await pathExists15(v3SchemaFile)) {
|
|
36981
37360
|
return uninstallV3(rootDir, platform, options);
|
|
36982
37361
|
}
|
|
@@ -37067,7 +37446,7 @@ async function uninstallAll(rootDir) {
|
|
|
37067
37446
|
await uninstallPlatform(rootDir, p);
|
|
37068
37447
|
}
|
|
37069
37448
|
console.log("\u2713 Removing .mancode/ directory...");
|
|
37070
|
-
await rm17(
|
|
37449
|
+
await rm17(path60.join(rootDir, ".mancode"), {
|
|
37071
37450
|
recursive: true,
|
|
37072
37451
|
force: true
|
|
37073
37452
|
});
|
|
@@ -37077,10 +37456,10 @@ async function uninstallClaudeCode(rootDir) {
|
|
|
37077
37456
|
await cleanClaudeSettings(rootDir);
|
|
37078
37457
|
}
|
|
37079
37458
|
async function cleanClaudeSettings(rootDir) {
|
|
37080
|
-
const settingsPath =
|
|
37459
|
+
const settingsPath = path60.join(rootDir, ".claude", "settings.json");
|
|
37081
37460
|
let content;
|
|
37082
37461
|
try {
|
|
37083
|
-
content = await
|
|
37462
|
+
content = await readFile41(settingsPath, "utf-8");
|
|
37084
37463
|
} catch {
|
|
37085
37464
|
return;
|
|
37086
37465
|
}
|
|
@@ -37106,7 +37485,7 @@ async function cleanClaudeSettings(rootDir) {
|
|
|
37106
37485
|
);
|
|
37107
37486
|
settings.skills = Object.keys(retainedSkills).length > 0 ? retainedSkills : void 0;
|
|
37108
37487
|
}
|
|
37109
|
-
await
|
|
37488
|
+
await writeFile42(
|
|
37110
37489
|
settingsPath,
|
|
37111
37490
|
`${JSON.stringify(settings, null, 2)}
|
|
37112
37491
|
`,
|
|
@@ -37155,12 +37534,12 @@ async function uninstallCursor(rootDir) {
|
|
|
37155
37534
|
await removeCursorCommands(rootDir);
|
|
37156
37535
|
}
|
|
37157
37536
|
async function uninstallCodex(rootDir) {
|
|
37158
|
-
const agentsPath =
|
|
37537
|
+
const agentsPath = path60.join(rootDir, "AGENTS.md");
|
|
37159
37538
|
try {
|
|
37160
|
-
const content = await
|
|
37539
|
+
const content = await readFile41(agentsPath, "utf-8");
|
|
37161
37540
|
const cleaned = removeManagedBlock(content);
|
|
37162
37541
|
if (cleaned.trim()) {
|
|
37163
|
-
await
|
|
37542
|
+
await writeFile42(agentsPath, `${cleaned}
|
|
37164
37543
|
`, "utf-8");
|
|
37165
37544
|
} else {
|
|
37166
37545
|
await rm17(agentsPath, { force: true });
|
|
@@ -37170,16 +37549,16 @@ async function uninstallCodex(rootDir) {
|
|
|
37170
37549
|
await removeCodexSkills(rootDir);
|
|
37171
37550
|
}
|
|
37172
37551
|
async function uninstallCopilot(rootDir) {
|
|
37173
|
-
const instructionsPath =
|
|
37552
|
+
const instructionsPath = path60.join(
|
|
37174
37553
|
rootDir,
|
|
37175
37554
|
".github",
|
|
37176
37555
|
"copilot-instructions.md"
|
|
37177
37556
|
);
|
|
37178
37557
|
try {
|
|
37179
|
-
const content = await
|
|
37558
|
+
const content = await readFile41(instructionsPath, "utf-8");
|
|
37180
37559
|
const cleaned = removeManagedBlock(content);
|
|
37181
37560
|
if (cleaned.trim()) {
|
|
37182
|
-
await
|
|
37561
|
+
await writeFile42(instructionsPath, `${cleaned}
|
|
37183
37562
|
`, "utf-8");
|
|
37184
37563
|
} else {
|
|
37185
37564
|
await rm17(instructionsPath, { force: true });
|
|
@@ -37189,16 +37568,16 @@ async function uninstallCopilot(rootDir) {
|
|
|
37189
37568
|
await removeCopilotPrompts(rootDir);
|
|
37190
37569
|
}
|
|
37191
37570
|
async function uninstallZcode(rootDir) {
|
|
37192
|
-
const agentsPath =
|
|
37571
|
+
const agentsPath = path60.join(rootDir, "AGENTS.md");
|
|
37193
37572
|
try {
|
|
37194
|
-
const content = await
|
|
37573
|
+
const content = await readFile41(agentsPath, "utf-8");
|
|
37195
37574
|
const cleaned = removeManagedBlock(
|
|
37196
37575
|
content,
|
|
37197
37576
|
ZCODE_MANCODE_START_MARKER,
|
|
37198
37577
|
ZCODE_MANCODE_END_MARKER
|
|
37199
37578
|
);
|
|
37200
37579
|
if (cleaned.trim()) {
|
|
37201
|
-
await
|
|
37580
|
+
await writeFile42(agentsPath, `${cleaned}
|
|
37202
37581
|
`, "utf-8");
|
|
37203
37582
|
} else {
|
|
37204
37583
|
await rm17(agentsPath, { force: true });
|
|
@@ -37208,9 +37587,9 @@ async function uninstallZcode(rootDir) {
|
|
|
37208
37587
|
await removeZcodeSkills(rootDir);
|
|
37209
37588
|
}
|
|
37210
37589
|
async function removeFromConfig(rootDir, platform) {
|
|
37211
|
-
const configPath =
|
|
37590
|
+
const configPath = path60.join(rootDir, ".mancode", "config.json");
|
|
37212
37591
|
try {
|
|
37213
|
-
const raw = await
|
|
37592
|
+
const raw = await readFile41(configPath, "utf-8");
|
|
37214
37593
|
const config = JSON.parse(raw);
|
|
37215
37594
|
if (Array.isArray(config.platforms)) {
|
|
37216
37595
|
config.platforms = config.platforms.filter((p) => p !== platform);
|
|
@@ -37222,7 +37601,7 @@ async function removeFromConfig(rootDir, platform) {
|
|
|
37222
37601
|
);
|
|
37223
37602
|
config.platformOptions = Object.keys(platformOptions).length > 0 ? platformOptions : void 0;
|
|
37224
37603
|
}
|
|
37225
|
-
await
|
|
37604
|
+
await writeFile42(
|
|
37226
37605
|
configPath,
|
|
37227
37606
|
`${JSON.stringify(config, null, 2)}
|
|
37228
37607
|
`,
|
|
@@ -37255,8 +37634,8 @@ function version() {
|
|
|
37255
37634
|
}
|
|
37256
37635
|
|
|
37257
37636
|
// src/commands/workflow.ts
|
|
37258
|
-
import { access as access6, readFile as
|
|
37259
|
-
import
|
|
37637
|
+
import { access as access6, readFile as readFile43, rm as rm19, writeFile as writeFile44 } from "fs/promises";
|
|
37638
|
+
import path62 from "path";
|
|
37260
37639
|
|
|
37261
37640
|
// src/context/child-result-merge.ts
|
|
37262
37641
|
async function mergeV3ChildResult(input) {
|
|
@@ -39711,14 +40090,14 @@ function updateMetadata4(previous, verification, operationId, updatedAt) {
|
|
|
39711
40090
|
|
|
39712
40091
|
// src/context/workflow-create.ts
|
|
39713
40092
|
import {
|
|
39714
|
-
lstat as
|
|
39715
|
-
mkdir as
|
|
39716
|
-
readFile as
|
|
40093
|
+
lstat as lstat23,
|
|
40094
|
+
mkdir as mkdir37,
|
|
40095
|
+
readFile as readFile42,
|
|
39717
40096
|
rename as rename11,
|
|
39718
40097
|
rm as rm18,
|
|
39719
|
-
writeFile as
|
|
40098
|
+
writeFile as writeFile43
|
|
39720
40099
|
} from "fs/promises";
|
|
39721
|
-
import
|
|
40100
|
+
import path61 from "path";
|
|
39722
40101
|
|
|
39723
40102
|
// src/context/creation-resolution.ts
|
|
39724
40103
|
function resolveWorkflowCreation(request) {
|
|
@@ -39828,7 +40207,7 @@ function rejectConflict(provided, expected, label) {
|
|
|
39828
40207
|
|
|
39829
40208
|
// src/context/workflow-create.ts
|
|
39830
40209
|
async function createV3Workflow(input) {
|
|
39831
|
-
const projectRoot =
|
|
40210
|
+
const projectRoot = path61.resolve(requireProjectRoot2(input.projectRoot));
|
|
39832
40211
|
const task = requireText2(input.task, "workflow task");
|
|
39833
40212
|
const client = requireText2(input.client, "workflow client");
|
|
39834
40213
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
@@ -39991,8 +40370,8 @@ async function createV3Workflow(input) {
|
|
|
39991
40370
|
assertOperationRecoveryPayloadCoversJournal(operation, recoveryPayload);
|
|
39992
40371
|
assertOperationJournalMatchesDefinition(operation);
|
|
39993
40372
|
const taskParent = await ensureSafeTaskParent3(projectRoot, taskRef);
|
|
39994
|
-
const targetDirectory =
|
|
39995
|
-
const stagingDirectory =
|
|
40373
|
+
const targetDirectory = path61.join(taskParent, taskRef.taskId);
|
|
40374
|
+
const stagingDirectory = path61.join(
|
|
39996
40375
|
taskParent,
|
|
39997
40376
|
`.${taskRef.taskId}.${operationId}.staging`
|
|
39998
40377
|
);
|
|
@@ -40433,10 +40812,10 @@ async function ensureSafeTaskParent3(projectRoot, taskRef) {
|
|
|
40433
40812
|
const segments = [".mancode", taskRef.namespace, "workflows"];
|
|
40434
40813
|
let current = projectRoot;
|
|
40435
40814
|
for (const segment of segments) {
|
|
40436
|
-
current =
|
|
40815
|
+
current = path61.join(current, segment);
|
|
40437
40816
|
const existing = await lstatOrNull5(current);
|
|
40438
40817
|
if (existing === null) {
|
|
40439
|
-
await
|
|
40818
|
+
await mkdir37(current);
|
|
40440
40819
|
continue;
|
|
40441
40820
|
}
|
|
40442
40821
|
if (!existing.isDirectory() || existing.isSymbolicLink()) {
|
|
@@ -40449,7 +40828,7 @@ async function assertDirectoryAbsent(target, code) {
|
|
|
40449
40828
|
if (await lstatOrNull5(target) !== null) throw new Error(code);
|
|
40450
40829
|
}
|
|
40451
40830
|
async function writeStagedEntities(stagingDirectory, entities) {
|
|
40452
|
-
await
|
|
40831
|
+
await mkdir37(stagingDirectory);
|
|
40453
40832
|
await assertDirectory(stagingDirectory);
|
|
40454
40833
|
await Promise.all([
|
|
40455
40834
|
writeStagedJson(stagingDirectory, "metadata.json", entities.metadata),
|
|
@@ -40469,13 +40848,13 @@ async function writeStagedEntities(stagingDirectory, entities) {
|
|
|
40469
40848
|
}
|
|
40470
40849
|
async function writeStagedJson(stagingDirectory, fileName, value) {
|
|
40471
40850
|
await assertDirectory(stagingDirectory);
|
|
40472
|
-
const target =
|
|
40473
|
-
await
|
|
40851
|
+
const target = path61.join(stagingDirectory, fileName);
|
|
40852
|
+
await writeFile43(target, `${JSON.stringify(value, null, 2)}
|
|
40474
40853
|
`, {
|
|
40475
40854
|
encoding: "utf8",
|
|
40476
40855
|
flag: "wx"
|
|
40477
40856
|
});
|
|
40478
|
-
const entry = await
|
|
40857
|
+
const entry = await lstat23(target);
|
|
40479
40858
|
if (!entry.isFile() || entry.isSymbolicLink()) {
|
|
40480
40859
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
40481
40860
|
}
|
|
@@ -40507,13 +40886,13 @@ async function validateStagedEntities(stagingDirectory) {
|
|
|
40507
40886
|
});
|
|
40508
40887
|
}
|
|
40509
40888
|
async function readStagedJson(stagingDirectory, fileName, parser) {
|
|
40510
|
-
const target =
|
|
40511
|
-
const before = await
|
|
40889
|
+
const target = path61.join(stagingDirectory, fileName);
|
|
40890
|
+
const before = await lstat23(target);
|
|
40512
40891
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
40513
40892
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
40514
40893
|
}
|
|
40515
|
-
const parsed = parser(JSON.parse(await
|
|
40516
|
-
const after = await
|
|
40894
|
+
const parsed = parser(JSON.parse(await readFile42(target, "utf8")));
|
|
40895
|
+
const after = await lstat23(target);
|
|
40517
40896
|
if (!after.isFile() || after.isSymbolicLink() || before.dev !== after.dev || before.ino !== after.ino) {
|
|
40518
40897
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
40519
40898
|
}
|
|
@@ -40608,16 +40987,16 @@ async function abortPreparedCreate(store, journal, stagingDirectory, now) {
|
|
|
40608
40987
|
}
|
|
40609
40988
|
}
|
|
40610
40989
|
async function assertDirectory(target) {
|
|
40611
|
-
const entry = await
|
|
40990
|
+
const entry = await lstat23(target);
|
|
40612
40991
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
40613
40992
|
throw new Error("MANCODE_ARTIFACT_PATH_UNSAFE");
|
|
40614
40993
|
}
|
|
40615
40994
|
}
|
|
40616
40995
|
async function lstatOrNull5(target) {
|
|
40617
40996
|
try {
|
|
40618
|
-
return await
|
|
40997
|
+
return await lstat23(target);
|
|
40619
40998
|
} catch (error) {
|
|
40620
|
-
if (
|
|
40999
|
+
if (isNotFound30(error)) return null;
|
|
40621
41000
|
throw error;
|
|
40622
41001
|
}
|
|
40623
41002
|
}
|
|
@@ -40637,7 +41016,7 @@ function requireText2(value, label) {
|
|
|
40637
41016
|
}
|
|
40638
41017
|
return value.trim();
|
|
40639
41018
|
}
|
|
40640
|
-
function
|
|
41019
|
+
function isNotFound30(error) {
|
|
40641
41020
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
40642
41021
|
}
|
|
40643
41022
|
|
|
@@ -41191,6 +41570,9 @@ async function publishTaskMutation(input) {
|
|
|
41191
41570
|
taskRef: input.context.taskRef,
|
|
41192
41571
|
expectedRemoteRevision: input.manifest.revision,
|
|
41193
41572
|
expectedOwnershipEpoch: input.fence.ownershipEpoch,
|
|
41573
|
+
expectedTaskBundleDigest: input.manifest.taskBundles.find(
|
|
41574
|
+
(bundle) => sameTaskRef(bundle.taskRef, input.context.taskRef)
|
|
41575
|
+
)?.bundleDigest ?? null,
|
|
41194
41576
|
ownershipFence: fence,
|
|
41195
41577
|
claims: input.claims,
|
|
41196
41578
|
handoffs,
|
|
@@ -41579,7 +41961,7 @@ async function workflow(rootDir, subcommand, args = [], options = {}) {
|
|
|
41579
41961
|
if (v3Activation === "v3_active") {
|
|
41580
41962
|
return workflowV3(rootDir, subcommand, args, options);
|
|
41581
41963
|
}
|
|
41582
|
-
if (!await pathExists16(
|
|
41964
|
+
if (!await pathExists16(path62.join(rootDir, ".mancode", "state.json"))) {
|
|
41583
41965
|
if (v3Activation !== null) {
|
|
41584
41966
|
return printV3Error(
|
|
41585
41967
|
options.json,
|
|
@@ -42507,8 +42889,8 @@ function parseV3ParticipantActorIds(values) {
|
|
|
42507
42889
|
return values;
|
|
42508
42890
|
}
|
|
42509
42891
|
async function readWorkflowInputFile(projectRoot, value) {
|
|
42510
|
-
const inputPath =
|
|
42511
|
-
return
|
|
42892
|
+
const inputPath = path62.isAbsolute(value) ? value : path62.resolve(projectRoot, value);
|
|
42893
|
+
return readFile43(inputPath, "utf8");
|
|
42512
42894
|
}
|
|
42513
42895
|
async function readWorkflowJsonInputFile(projectRoot, value) {
|
|
42514
42896
|
return JSON.parse(await readWorkflowInputFile(projectRoot, value));
|
|
@@ -42575,7 +42957,7 @@ async function readV3ActivationState2(rootDir) {
|
|
|
42575
42957
|
try {
|
|
42576
42958
|
const manifest = parseSchemaManifest(
|
|
42577
42959
|
JSON.parse(
|
|
42578
|
-
await
|
|
42960
|
+
await readFile43(path62.join(rootDir, ".mancode", "schema.json"), "utf8")
|
|
42579
42961
|
)
|
|
42580
42962
|
);
|
|
42581
42963
|
return manifest.activationState === "v3_active" ? "v3_active" : "other";
|
|
@@ -42620,21 +43002,21 @@ async function workflowRequirements(rootDir, args, options) {
|
|
|
42620
43002
|
"requirements can only be finalized for an in-progress man or manteam workflow at step 1 or 2"
|
|
42621
43003
|
);
|
|
42622
43004
|
}
|
|
42623
|
-
const workflowPath =
|
|
42624
|
-
const jsonPath =
|
|
42625
|
-
const markdownPath =
|
|
42626
|
-
const metadataPath3 =
|
|
43005
|
+
const workflowPath = path62.join(rootDir, ".mancode", "workflows", taskId);
|
|
43006
|
+
const jsonPath = path62.join(workflowPath, "requirements.json");
|
|
43007
|
+
const markdownPath = path62.join(workflowPath, "requirements.md");
|
|
43008
|
+
const metadataPath3 = path62.join(workflowPath, "metadata.json");
|
|
42627
43009
|
let originalJson;
|
|
42628
43010
|
let originalMarkdown;
|
|
42629
43011
|
let originalMetadata;
|
|
42630
43012
|
try {
|
|
42631
|
-
const inputPath =
|
|
42632
|
-
const input = await
|
|
43013
|
+
const inputPath = path62.isAbsolute(options.file) ? options.file : path62.resolve(rootDir, options.file);
|
|
43014
|
+
const input = await readFile43(inputPath, "utf-8");
|
|
42633
43015
|
const requirements = parseRequirementsLedger2(input);
|
|
42634
43016
|
[originalJson, originalMarkdown, originalMetadata] = await Promise.all([
|
|
42635
43017
|
readOptionalText2(jsonPath),
|
|
42636
43018
|
readOptionalText2(markdownPath),
|
|
42637
|
-
|
|
43019
|
+
readFile43(metadataPath3, "utf-8")
|
|
42638
43020
|
]);
|
|
42639
43021
|
await writeRequirementsArtifacts(rootDir, taskId, requirements);
|
|
42640
43022
|
await updateWorkflow(rootDir, taskId, {
|
|
@@ -42664,7 +43046,7 @@ async function workflowRequirements(rootDir, args, options) {
|
|
|
42664
43046
|
const rollback = await Promise.allSettled([
|
|
42665
43047
|
restoreOptionalText(jsonPath, originalJson),
|
|
42666
43048
|
restoreOptionalText(markdownPath, originalMarkdown),
|
|
42667
|
-
|
|
43049
|
+
writeFile44(metadataPath3, originalMetadata, "utf-8")
|
|
42668
43050
|
]);
|
|
42669
43051
|
rollbackIncomplete = rollback.some(
|
|
42670
43052
|
(result2) => result2.status === "rejected"
|
|
@@ -42752,7 +43134,7 @@ async function workflowVerify(rootDir, args, options) {
|
|
|
42752
43134
|
);
|
|
42753
43135
|
}
|
|
42754
43136
|
if (options.evidenceFile) {
|
|
42755
|
-
const evidencePath =
|
|
43137
|
+
const evidencePath = path62.isAbsolute(options.evidenceFile) ? options.evidenceFile : path62.resolve(rootDir, options.evidenceFile);
|
|
42756
43138
|
if (!await pathExists16(evidencePath)) {
|
|
42757
43139
|
return invalidArg(
|
|
42758
43140
|
options,
|
|
@@ -42812,17 +43194,17 @@ async function workflowVerify(rootDir, args, options) {
|
|
|
42812
43194
|
}
|
|
42813
43195
|
async function commitVerificationTransition(rootDir, meta, ledger) {
|
|
42814
43196
|
const ledgerPath = verificationLedgerPath(rootDir, meta.taskId);
|
|
42815
|
-
const metadataPath3 =
|
|
43197
|
+
const metadataPath3 = path62.join(
|
|
42816
43198
|
rootDir,
|
|
42817
43199
|
".mancode",
|
|
42818
43200
|
"workflows",
|
|
42819
43201
|
meta.taskId,
|
|
42820
43202
|
"metadata.json"
|
|
42821
43203
|
);
|
|
42822
|
-
const specPath =
|
|
43204
|
+
const specPath = path62.join(rootDir, ".mancode", "memory", "spec.md");
|
|
42823
43205
|
const [originalLedger, originalMetadata, originalSpec] = await Promise.all([
|
|
42824
43206
|
readOptionalText2(ledgerPath),
|
|
42825
|
-
|
|
43207
|
+
readFile43(metadataPath3, "utf-8"),
|
|
42826
43208
|
readOptionalText2(specPath)
|
|
42827
43209
|
]);
|
|
42828
43210
|
const wasVerificationBlocked = meta.status === "blocked" && meta.blockingReason?.startsWith("[verification]");
|
|
@@ -42851,7 +43233,7 @@ async function commitVerificationTransition(rootDir, meta, ledger) {
|
|
|
42851
43233
|
} catch (error) {
|
|
42852
43234
|
const rollback = await Promise.allSettled([
|
|
42853
43235
|
restoreOptionalText(ledgerPath, originalLedger),
|
|
42854
|
-
|
|
43236
|
+
writeFile44(metadataPath3, originalMetadata, "utf-8"),
|
|
42855
43237
|
restoreOptionalText(specPath, originalSpec)
|
|
42856
43238
|
]);
|
|
42857
43239
|
const message = error instanceof Error ? error.message : "verification transition failed";
|
|
@@ -42983,7 +43365,7 @@ async function workflowReview(rootDir, args, options) {
|
|
|
42983
43365
|
}
|
|
42984
43366
|
async function commitReviewSkip(rootDir, meta, reason) {
|
|
42985
43367
|
const ledgerPath = reviewLedgerPath(rootDir, meta.taskId);
|
|
42986
|
-
const metadataPath3 =
|
|
43368
|
+
const metadataPath3 = path62.join(
|
|
42987
43369
|
rootDir,
|
|
42988
43370
|
".mancode",
|
|
42989
43371
|
"workflows",
|
|
@@ -42992,7 +43374,7 @@ async function commitReviewSkip(rootDir, meta, reason) {
|
|
|
42992
43374
|
);
|
|
42993
43375
|
const [originalLedger, originalMetadata] = await Promise.all([
|
|
42994
43376
|
readOptionalText2(ledgerPath),
|
|
42995
|
-
|
|
43377
|
+
readFile43(metadataPath3, "utf-8")
|
|
42996
43378
|
]);
|
|
42997
43379
|
try {
|
|
42998
43380
|
await initializeSkippedReview(rootDir, meta.taskId, reason);
|
|
@@ -43003,7 +43385,7 @@ async function commitReviewSkip(rootDir, meta, reason) {
|
|
|
43003
43385
|
} catch (error) {
|
|
43004
43386
|
const rollback = await Promise.allSettled([
|
|
43005
43387
|
restoreOptionalText(ledgerPath, originalLedger),
|
|
43006
|
-
|
|
43388
|
+
writeFile44(metadataPath3, originalMetadata, "utf-8")
|
|
43007
43389
|
]);
|
|
43008
43390
|
const message = error instanceof Error ? error.message : "review skip failed";
|
|
43009
43391
|
return rollback.some((result2) => result2.status === "rejected") ? `${message}; rollback was incomplete` : message;
|
|
@@ -43223,18 +43605,18 @@ async function workflowHandoff(rootDir, taskId, options) {
|
|
|
43223
43605
|
"solo handoff requires an undecided in-progress workflow at step 4 with ready requirements"
|
|
43224
43606
|
);
|
|
43225
43607
|
}
|
|
43226
|
-
const workflowPath =
|
|
43227
|
-
if (!await pathExists16(
|
|
43608
|
+
const workflowPath = path62.join(rootDir, ".mancode", "workflows", taskId);
|
|
43609
|
+
if (!await pathExists16(path62.join(workflowPath, "requirements.md")) || !await pathExists16(path62.join(workflowPath, "plan.md"))) {
|
|
43228
43610
|
return invalidArg(
|
|
43229
43611
|
options,
|
|
43230
43612
|
"solo handoff requires requirements.md and plan.md"
|
|
43231
43613
|
);
|
|
43232
43614
|
}
|
|
43233
|
-
const statePath =
|
|
43615
|
+
const statePath = path62.join(rootDir, ".mancode", "state.json");
|
|
43234
43616
|
let originalState;
|
|
43235
43617
|
let state;
|
|
43236
43618
|
try {
|
|
43237
|
-
originalState = await
|
|
43619
|
+
originalState = await readFile43(statePath, "utf-8");
|
|
43238
43620
|
state = JSON.parse(originalState);
|
|
43239
43621
|
} catch {
|
|
43240
43622
|
return invalidArg(
|
|
@@ -43305,11 +43687,11 @@ async function workflowCompleteHandoff(rootDir, taskId, options) {
|
|
|
43305
43687
|
`workflow is not an active solo handoff: ${taskId}`
|
|
43306
43688
|
);
|
|
43307
43689
|
}
|
|
43308
|
-
const statePath =
|
|
43690
|
+
const statePath = path62.join(rootDir, ".mancode", "state.json");
|
|
43309
43691
|
let originalState;
|
|
43310
43692
|
let state;
|
|
43311
43693
|
try {
|
|
43312
|
-
originalState = await
|
|
43694
|
+
originalState = await readFile43(statePath, "utf-8");
|
|
43313
43695
|
state = JSON.parse(originalState);
|
|
43314
43696
|
} catch {
|
|
43315
43697
|
return invalidArg(
|
|
@@ -43372,18 +43754,18 @@ async function workflowDecide(rootDir, taskId, options) {
|
|
|
43372
43754
|
`workflow is not ready for a plan-only decision: ${taskId}`
|
|
43373
43755
|
);
|
|
43374
43756
|
}
|
|
43375
|
-
const workflowPath =
|
|
43376
|
-
if (!await pathExists16(
|
|
43757
|
+
const workflowPath = path62.join(rootDir, ".mancode", "workflows", taskId);
|
|
43758
|
+
if (!await pathExists16(path62.join(workflowPath, "requirements.md")) || !await pathExists16(path62.join(workflowPath, "plan.md"))) {
|
|
43377
43759
|
return invalidArg(
|
|
43378
43760
|
options,
|
|
43379
43761
|
"plan-only requires requirements.md and plan.md"
|
|
43380
43762
|
);
|
|
43381
43763
|
}
|
|
43382
|
-
const statePath =
|
|
43764
|
+
const statePath = path62.join(rootDir, ".mancode", "state.json");
|
|
43383
43765
|
let originalState;
|
|
43384
43766
|
let state;
|
|
43385
43767
|
try {
|
|
43386
|
-
originalState = await
|
|
43768
|
+
originalState = await readFile43(statePath, "utf-8");
|
|
43387
43769
|
state = JSON.parse(originalState);
|
|
43388
43770
|
} catch {
|
|
43389
43771
|
return invalidArg(
|
|
@@ -43435,25 +43817,25 @@ async function workflowDecide(rootDir, taskId, options) {
|
|
|
43435
43817
|
return EXIT_OK10;
|
|
43436
43818
|
}
|
|
43437
43819
|
async function commitPlanningTransition(args) {
|
|
43438
|
-
const metadataPath3 =
|
|
43820
|
+
const metadataPath3 = path62.join(
|
|
43439
43821
|
args.rootDir,
|
|
43440
43822
|
".mancode",
|
|
43441
43823
|
"workflows",
|
|
43442
43824
|
args.taskId,
|
|
43443
43825
|
"metadata.json"
|
|
43444
43826
|
);
|
|
43445
|
-
const specPath =
|
|
43827
|
+
const specPath = path62.join(args.rootDir, ".mancode", "memory", "spec.md");
|
|
43446
43828
|
let originalMetadata;
|
|
43447
43829
|
let originalSpec;
|
|
43448
43830
|
try {
|
|
43449
|
-
originalMetadata = await
|
|
43831
|
+
originalMetadata = await readFile43(metadataPath3, "utf-8");
|
|
43450
43832
|
originalSpec = await readOptionalText2(specPath);
|
|
43451
43833
|
} catch (error) {
|
|
43452
43834
|
return error instanceof Error ? `unable to prepare planning transition: ${error.message}` : "unable to prepare planning transition";
|
|
43453
43835
|
}
|
|
43454
43836
|
try {
|
|
43455
43837
|
await updateWorkflow(args.rootDir, args.taskId, args.workflowPatch);
|
|
43456
|
-
await
|
|
43838
|
+
await writeFile44(
|
|
43457
43839
|
args.statePath,
|
|
43458
43840
|
`${JSON.stringify(args.nextState, null, 2)}
|
|
43459
43841
|
`,
|
|
@@ -43467,9 +43849,9 @@ async function commitPlanningTransition(args) {
|
|
|
43467
43849
|
return null;
|
|
43468
43850
|
} catch (error) {
|
|
43469
43851
|
const rollback = await Promise.allSettled([
|
|
43470
|
-
|
|
43471
|
-
|
|
43472
|
-
originalSpec === null ? rm19(specPath, { force: true }) :
|
|
43852
|
+
writeFile44(metadataPath3, originalMetadata, "utf-8"),
|
|
43853
|
+
writeFile44(args.statePath, args.originalState, "utf-8"),
|
|
43854
|
+
originalSpec === null ? rm19(specPath, { force: true }) : writeFile44(specPath, originalSpec, "utf-8")
|
|
43473
43855
|
]);
|
|
43474
43856
|
const message = error instanceof Error ? error.message : "planning transition failed";
|
|
43475
43857
|
return rollback.some((result2) => result2.status === "rejected") ? `${message}; rollback was incomplete` : message;
|
|
@@ -43477,7 +43859,7 @@ async function commitPlanningTransition(args) {
|
|
|
43477
43859
|
}
|
|
43478
43860
|
async function readOptionalText2(filePath) {
|
|
43479
43861
|
try {
|
|
43480
|
-
return await
|
|
43862
|
+
return await readFile43(filePath, "utf-8");
|
|
43481
43863
|
} catch (error) {
|
|
43482
43864
|
if (isNodeError10(error) && error.code === "ENOENT") return null;
|
|
43483
43865
|
throw error;
|
|
@@ -43488,7 +43870,7 @@ async function restoreOptionalText(filePath, content) {
|
|
|
43488
43870
|
await rm19(filePath, { force: true });
|
|
43489
43871
|
return;
|
|
43490
43872
|
}
|
|
43491
|
-
await
|
|
43873
|
+
await writeFile44(filePath, content, "utf-8");
|
|
43492
43874
|
}
|
|
43493
43875
|
function readActiveSoloPlan(value) {
|
|
43494
43876
|
if (!value || typeof value !== "object") return null;
|