gitifact 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/assets/BottomSheet-F2BUQwSi.js +1 -0
- package/dist/browser/assets/Card-C0juPkmX.js +1 -0
- package/dist/browser/assets/IconButton-CkA9oftf.js +1 -0
- package/dist/browser/assets/Markdown-D7VrGOLZ.js +68 -0
- package/dist/browser/assets/{MenuBottomSheet-BkRC4_VW.js → MenuBottomSheet-CQA7HL9k.js} +1 -1
- package/dist/browser/assets/{MetadataListItem-BJjmYUP-.js → MetadataListItem-DRZdPsPv.js} +1 -1
- package/dist/browser/assets/Section-zmL2D3WL.js +1 -0
- package/dist/browser/assets/Table-DxOgh9uC.js +3 -0
- package/dist/browser/assets/TimestampHoverCard-DOWpOAzA.js +1 -0
- package/dist/browser/assets/about-K6mG2f8D.js +3 -0
- package/dist/browser/assets/changelog-7YrQ3ibl.js +2 -0
- package/dist/browser/assets/composeEventHandlers-CHIontwB.js +1 -0
- package/dist/browser/assets/container.stylex-oPimSCGl.js +1 -0
- package/dist/browser/assets/{contributors._email-CwG6z4oO.js → contributors._email-PmuGt4HK.js} +1 -1
- package/dist/browser/assets/{contributors.index-B9l1YPjl.js → contributors.index-Du6gcymD.js} +1 -1
- package/dist/browser/assets/devWarning-BZMSgwyk.js +1 -0
- package/dist/browser/assets/document-B1QpmAOH.js +1 -0
- package/dist/browser/assets/document-D41OCO3e.css +1 -0
- package/dist/browser/assets/{features._featureId-uB5QcPIl.js → features._featureId-DzAIhNyX.js} +1 -1
- package/dist/browser/assets/{requirements-BMLc9Fpl.js → features.index-D9wmqimq.js} +1 -1
- package/dist/browser/assets/git-cGldo_jC.js +1 -0
- package/dist/browser/assets/guides._documentId-BEv09vs4.js +1 -0
- package/dist/browser/assets/{guides.index-BfJqdqJd.js → guides.index-tfySk9wY.js} +1 -1
- package/dist/browser/assets/index-B5Ql9tDp.js +56 -0
- package/dist/browser/assets/page-header-8LgEWnon.js +126 -0
- package/dist/browser/assets/product-BrvAWtBo.css +1 -0
- package/dist/browser/assets/product-Q9uoNMvu.js +8 -0
- package/dist/browser/assets/product.document-Bl25IX1S.js +1 -0
- package/dist/browser/assets/product.index-BwKqT4MY.js +1 -0
- package/dist/browser/assets/request-state-sfsdVRHj.js +1 -0
- package/dist/browser/assets/{features.index-DzLFYkRG.js → requirements-B9rmmF27.js} +1 -1
- package/dist/browser/assets/{routes-XUldGkLf.js → routes-COAEfNb7.js} +1 -1
- package/dist/browser/assets/settings-BvuMkHCB.css +1 -0
- package/dist/browser/assets/settings-Cv6WtTcC.js +1 -0
- package/dist/browser/assets/useDevWarning-Xg7kPMHJ.js +1 -0
- package/dist/browser/assets/useMediaQuery-DFlnKIlp.js +1 -0
- package/dist/browser/assets/useTranslator-DY2HN18N.js +4 -0
- package/dist/browser/index.html +19 -11
- package/dist/i18n/ko/block.md +6 -4
- package/dist/i18n/ko/changelog.md +23 -0
- package/dist/i18n/ko/docs/commit.md +1 -1
- package/dist/i18n/ko/docs/spec.md +1 -1
- package/dist/i18n/ko/docs/workflow.md +10 -0
- package/dist/main.js +197 -94
- package/package.json +1 -1
- package/dist/browser/assets/BottomSheet-CUR7U0gF.js +0 -1
- package/dist/browser/assets/IconButton-BqlnBu_N.js +0 -4
- package/dist/browser/assets/Markdown-BG_9T3yA.js +0 -68
- package/dist/browser/assets/Section-DQRr6JoK.js +0 -1
- package/dist/browser/assets/TimestampHoverCard-ClDQXGeS.js +0 -1
- package/dist/browser/assets/about-C5lrF_v9.js +0 -3
- package/dist/browser/assets/changelog-hNvOtw70.js +0 -2
- package/dist/browser/assets/git-DJKAcbnl.js +0 -1
- package/dist/browser/assets/guides._documentId-DHM6effA.js +0 -1
- package/dist/browser/assets/index-jaVGAf81.js +0 -56
- package/dist/browser/assets/page-header-DI5eoQC1.js +0 -127
- package/dist/browser/assets/product-CV4EzacY.css +0 -1
- package/dist/browser/assets/product-YuwMeOC0.js +0 -8
- package/dist/browser/assets/product.index-RgfLdFqG.js +0 -1
- package/dist/browser/assets/request-state-DpUKcy6G.js +0 -1
- package/dist/browser/assets/useDevWarning-CzR6rkf6.js +0 -1
- package/dist/browser/assets/useMediaQuery-C_nG4b-e.js +0 -1
package/dist/main.js
CHANGED
|
@@ -1100,18 +1100,18 @@ function editDistance(a, b) {
|
|
|
1100
1100
|
}
|
|
1101
1101
|
return d[a.length][b.length];
|
|
1102
1102
|
}
|
|
1103
|
-
function suggestSimilar(word,
|
|
1104
|
-
if (!
|
|
1105
|
-
|
|
1103
|
+
function suggestSimilar(word, candidates2) {
|
|
1104
|
+
if (!candidates2 || candidates2.length === 0) return "";
|
|
1105
|
+
candidates2 = Array.from(new Set(candidates2));
|
|
1106
1106
|
const searchingOptions = word.startsWith("--");
|
|
1107
1107
|
if (searchingOptions) {
|
|
1108
1108
|
word = word.slice(2);
|
|
1109
|
-
|
|
1109
|
+
candidates2 = candidates2.map((candidate) => candidate.slice(2));
|
|
1110
1110
|
}
|
|
1111
1111
|
let similar = [];
|
|
1112
1112
|
let bestDistance = maxDistance;
|
|
1113
1113
|
const minSimilarity = 0.4;
|
|
1114
|
-
|
|
1114
|
+
candidates2.forEach((candidate) => {
|
|
1115
1115
|
if (candidate.length <= 1) return;
|
|
1116
1116
|
const distance = editDistance(word, candidate);
|
|
1117
1117
|
const length = Math.max(word.length, candidate.length);
|
|
@@ -24601,18 +24601,21 @@ var messages_default2 = {
|
|
|
24601
24601
|
"help.spec": "Markdown \uBA85\uC138 \uC791\uC131\xB7\uC870\uD68C\xB7Git \uAE30\uB85D",
|
|
24602
24602
|
"help.deprecated": "Deprecated: 0.6.0\uC5D0\uC11C \uC81C\uAC70 \uC608\uC815. spec commit\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
24603
24603
|
"help.specCommit": "\uBCC0\uACBD \uC774\uC720 \uAE30\uB85D\uACFC \uAD00\uB828 \uD30C\uC77C \uCEE4\uBC0B\uC744 \uD55C \uBC88\uC5D0 \uC2E4\uD589",
|
|
24604
|
-
"help.specCommitFile": "reasons\xB7paths\xB7message\xB7authorization\uC744 \uB2F4\uC740 JSON \uD30C\uC77C",
|
|
24604
|
+
"help.specCommitFile": "reasons\xB7paths\xB7message\xB7authorization\uC744 \uB2F4\uC740 JSON \uD30C\uC77C (-\uB294 \uD45C\uC900 \uC785\uB825)",
|
|
24605
24605
|
"help.specCommitDryRun": "\uD30C\uC77C\uC744 \uC4F0\uAC70\uB098 \uCEE4\uBC0B\uD558\uC9C0 \uC54A\uACE0 \uACB0\uACFC\uB9CC \uD655\uC778",
|
|
24606
24606
|
"help.specCommitPlanFile": "\uCEE4\uBC0B \uC785\uB825 \uB610\uB294 \uACC4\uD68D JSON \uD30C\uC77C",
|
|
24607
24607
|
"help.specPrepareFile": "expected\uC640 \uCD5C\uC885 reasons\uB97C \uB2F4\uC740 JSON \uD30C\uC77C",
|
|
24608
24608
|
"help.specVerifyFile": "prepare\uC758 verification \uAC1D\uCCB4\uB97C \uB2F4\uC740 JSON \uD30C\uC77C",
|
|
24609
24609
|
"help.specVerifyStaged": "index \uC6D0\uBB38\uB3C4 \uBE44\uAD50",
|
|
24610
|
-
"help.specSaveFile": "expected\uC640 operations\uB97C \uB2F4\uC740 UTF-8 JSON \uD30C\uC77C",
|
|
24610
|
+
"help.specSaveFile": "expected\uC640 operations\uB97C \uB2F4\uC740 UTF-8 JSON \uD30C\uC77C (-\uB294 \uD45C\uC900 \uC785\uB825)",
|
|
24611
24611
|
"help.specReadRef": "\uC77D\uC744 \uCEE4\uBC0B",
|
|
24612
24612
|
"help.specDiffFrom": "\uC774\uC804 \uCEE4\uBC0B",
|
|
24613
24613
|
"help.specDiffTo": "\uC774\uD6C4 \uCEE4\uBC0B",
|
|
24614
24614
|
"help.specChanges": "HEAD \uB300\uBE44 \uCD5C\uC885 \uBA85\uC138 \uCC28\uC774\uC640 \uBBF8\uCEE4\uBC0B \uC774\uC720 \uC870\uD68C",
|
|
24615
|
-
"help.specWorking": "\uD604\uC7AC \uBA85\uC138\xB7\uC81C\uD488\xB7\uC9C0\uCE68 \uC804\uCCB4\uC640 stamp \uC870\uD68C",
|
|
24615
|
+
"help.specWorking": "\uD604\uC7AC \uBA85\uC138\xB7\uC81C\uD488\xB7\uC9C0\uCE68 \uC804\uCCB4\uC640 stamp, \uC785\uB825 \uD30C\uC77C \uACBD\uB85C \uC870\uD68C",
|
|
24616
|
+
"help.specWorkingStamp": "stamp\uC640 \uC785\uB825 \uD30C\uC77C \uACBD\uB85C\uB9CC \uCD9C\uB825",
|
|
24617
|
+
"help.specWorkingFeature": "\uD55C \uAE30\uB2A5 \uD3F4\uB354\uC758 \uBA85\uC138\uB9CC \uCD9C\uB825 (\uC81C\uD488\xB7\uC9C0\uCE68 \uC81C\uC678)",
|
|
24618
|
+
"help.specWorkingIds": "\uBCF8\uBB38 \uC5C6\uC774 ID\xB7\uC81C\uBAA9\xB7\uACBD\uB85C\uB9CC \uCD9C\uB825",
|
|
24616
24619
|
"help.specSave": "\uC694\uAD6C\uC0AC\uD56D\xB7\uC124\uACC4\xB7\uBB38\uC11C \uC800\uC7A5",
|
|
24617
24620
|
"help.specRead": "\uCEE4\uBC0B \uC2DC\uC810\uC758 \uBA85\uC138 \uC870\uD68C",
|
|
24618
24621
|
"help.specDiff": "\uB450 \uCEE4\uBC0B \uC0AC\uC774\uC758 \uBA85\uC138 \uBCC0\uACBD \uC870\uD68C",
|
|
@@ -24638,6 +24641,7 @@ var messages_default2 = {
|
|
|
24638
24641
|
"preview.inputFile": "\uC785\uB825\uC740 1 MiB \uC774\uD558\uC758 JSON \uD30C\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
24639
24642
|
"preview.inputSize": "\uC785\uB825 \uD06C\uAE30\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24640
24643
|
"preview.inputJson": "\uC785\uB825 \uD30C\uC77C\uC740 UTF-8 JSON\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
24644
|
+
"preview.unknownFeature": "\uAE30\uB2A5 \uD3F4\uB354 {feature}\uC758 \uBA85\uC138\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24641
24645
|
"preview.failed": "\uAC80\uD1A0 \uBA85\uC138 \uC791\uC5C5\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24642
24646
|
"initRepo.configIgnored": "\uC124\uC815\uC774 ignore \uADDC\uCE59\uC73C\uB85C \uC81C\uC678\uB429\uB2C8\uB2E4: {rule}",
|
|
24643
24647
|
"initRepo.baselineMismatch": "\uAE30\uC900\uC120\uACFC \uD604\uC7AC \uC800\uC7A5\uC18C\uAC00 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
@@ -25186,23 +25190,23 @@ var fileInfo = (path3) => lstat(path3).catch((error62) => {
|
|
|
25186
25190
|
});
|
|
25187
25191
|
async function configDirectory(root) {
|
|
25188
25192
|
const path3 = join2(root, ".gitifact");
|
|
25189
|
-
const
|
|
25190
|
-
if (
|
|
25191
|
-
return
|
|
25193
|
+
const info5 = await fileInfo(path3);
|
|
25194
|
+
if (info5 && (!info5.isDirectory() || info5.isSymbolicLink())) throw new InitError("PATH_CONFLICT", t2("config.storeNotDirectory"));
|
|
25195
|
+
return info5;
|
|
25192
25196
|
}
|
|
25193
25197
|
async function readConfigFile(root) {
|
|
25194
25198
|
await configDirectory(root);
|
|
25195
25199
|
const path3 = join2(root, ".gitifact", "config.json");
|
|
25196
|
-
const
|
|
25197
|
-
if (!
|
|
25200
|
+
const info5 = await fileInfo(path3);
|
|
25201
|
+
if (!info5) {
|
|
25198
25202
|
if (await fileInfo(join2(root, ".tryce", "config.json"))) throw new InitError("MIGRATION_REQUIRED", t2("config.migrateFirst"));
|
|
25199
25203
|
return void 0;
|
|
25200
25204
|
}
|
|
25201
|
-
if (!
|
|
25205
|
+
if (!info5.isFile() || info5.isSymbolicLink() || info5.size > 65536) throw new InitError("PATH_CONFLICT", t2("config.fileShape"));
|
|
25202
25206
|
const bytes = await readFile2(path3);
|
|
25203
25207
|
const after = await fileInfo(path3);
|
|
25204
25208
|
await configDirectory(root);
|
|
25205
|
-
if (!after || after.ino !==
|
|
25209
|
+
if (!after || after.ino !== info5.ino || after.dev !== info5.dev || after.mtimeMs !== info5.mtimeMs || bytes.length > 65536) {
|
|
25206
25210
|
throw new InitError("INPUT_CHANGED", t2("config.changedWhileReading"));
|
|
25207
25211
|
}
|
|
25208
25212
|
try {
|
|
@@ -25901,14 +25905,14 @@ async function managedPath(root, path3, create = false) {
|
|
|
25901
25905
|
const parts = path3.split("/");
|
|
25902
25906
|
for (let i = 0; i < parts.length; i++) {
|
|
25903
25907
|
full = join6(full, parts[i]);
|
|
25904
|
-
let
|
|
25905
|
-
if (!
|
|
25908
|
+
let info5 = await fileInfo(full);
|
|
25909
|
+
if (!info5 && create && i < parts.length - 1) {
|
|
25906
25910
|
await mkdir3(full).catch((error62) => {
|
|
25907
25911
|
if (error62.code !== "EEXIST") throw error62;
|
|
25908
25912
|
});
|
|
25909
|
-
|
|
25913
|
+
info5 = await fileInfo(full);
|
|
25910
25914
|
}
|
|
25911
|
-
if (
|
|
25915
|
+
if (info5 && (info5.isSymbolicLink() || (i < parts.length - 1 ? !info5.isDirectory() : !info5.isFile()))) {
|
|
25912
25916
|
throw new InitError("PATH_CONFLICT", t2("managedFile.notRegularPath", { path: path3 }));
|
|
25913
25917
|
}
|
|
25914
25918
|
}
|
|
@@ -26259,7 +26263,7 @@ async function runUpdate(options, version2) {
|
|
|
26259
26263
|
}
|
|
26260
26264
|
|
|
26261
26265
|
// src/commands/spec-preview.ts
|
|
26262
|
-
import { join as
|
|
26266
|
+
import { join as join13 } from "node:path";
|
|
26263
26267
|
import { readFile as readFile12, stat as stat2 } from "node:fs/promises";
|
|
26264
26268
|
|
|
26265
26269
|
// src/adapters/filesystem/spec-preview-prepare.ts
|
|
@@ -26344,24 +26348,89 @@ async function verifyPreparedPreview(cwd, input2, staged) {
|
|
|
26344
26348
|
return { verified: true, scope: staged ? "staged" : "working", base: c.base, stamp: current.stamp };
|
|
26345
26349
|
}
|
|
26346
26350
|
|
|
26351
|
+
// src/adapters/filesystem/agent-inputs.ts
|
|
26352
|
+
import { createHash as createHash5, randomBytes as randomBytes2 } from "node:crypto";
|
|
26353
|
+
import { lstat as lstat5, mkdir as mkdir4, readdir as readdir4, realpath as realpath3, unlink as unlink4, writeFile as writeFile2 } from "node:fs/promises";
|
|
26354
|
+
import { tmpdir } from "node:os";
|
|
26355
|
+
import { basename, dirname as dirname3, join as join9 } from "node:path";
|
|
26356
|
+
var maxAge = 7 * 24 * 60 * 60 * 1e3;
|
|
26357
|
+
var info2 = (path3) => lstat5(path3).catch((e) => {
|
|
26358
|
+
if (e.code === "ENOENT") return void 0;
|
|
26359
|
+
throw e;
|
|
26360
|
+
});
|
|
26361
|
+
var comparable = (path3) => process.platform === "win32" ? path3.toLowerCase() : path3;
|
|
26362
|
+
async function candidates(root, controls) {
|
|
26363
|
+
const key = createHash5("sha256").update(comparable(await realpath3(root))).digest("hex").slice(0, 16);
|
|
26364
|
+
return { system: join9((controls.tmpdir ?? tmpdir)(), "gitifact", key), project: join9(root, ".gitifact", "tmp") };
|
|
26365
|
+
}
|
|
26366
|
+
async function writable(directory) {
|
|
26367
|
+
try {
|
|
26368
|
+
await mkdir4(directory, { recursive: true });
|
|
26369
|
+
const stat3 = await info2(directory);
|
|
26370
|
+
if (!stat3?.isDirectory() || stat3.isSymbolicLink()) return false;
|
|
26371
|
+
const probe = join9(directory, ".probe-" + randomBytes2(8).toString("hex"));
|
|
26372
|
+
await writeFile2(probe, "", { flag: "wx" });
|
|
26373
|
+
await unlink4(probe);
|
|
26374
|
+
return true;
|
|
26375
|
+
} catch {
|
|
26376
|
+
return false;
|
|
26377
|
+
}
|
|
26378
|
+
}
|
|
26379
|
+
async function prepareAgentInputs(root, controls = {}) {
|
|
26380
|
+
const { system, project } = await candidates(root, controls);
|
|
26381
|
+
let directory;
|
|
26382
|
+
if (await writable(system)) directory = system;
|
|
26383
|
+
else if (await writable(project)) {
|
|
26384
|
+
directory = project;
|
|
26385
|
+
await writeFile2(join9(project, ".gitignore"), "*\n", { flag: "wx" }).catch((e) => {
|
|
26386
|
+
if (e.code !== "EEXIST") throw e;
|
|
26387
|
+
});
|
|
26388
|
+
}
|
|
26389
|
+
if (!directory) return void 0;
|
|
26390
|
+
const now = (controls.now ?? Date.now)();
|
|
26391
|
+
for (const name of await readdir4(directory).catch(() => [])) {
|
|
26392
|
+
if (name === ".gitignore") continue;
|
|
26393
|
+
const stat3 = await info2(join9(directory, name)).catch(() => void 0);
|
|
26394
|
+
if (stat3?.isFile() && now - stat3.mtimeMs > maxAge) await unlink4(join9(directory, name)).catch(() => void 0);
|
|
26395
|
+
}
|
|
26396
|
+
return { save: join9(directory, "save.json"), commit: join9(directory, "commit.json") };
|
|
26397
|
+
}
|
|
26398
|
+
async function discardAgentInput(root, file2, controls = {}) {
|
|
26399
|
+
try {
|
|
26400
|
+
const stat3 = await info2(file2);
|
|
26401
|
+
if (!stat3?.isFile() || stat3.isSymbolicLink()) return false;
|
|
26402
|
+
const parent = comparable(await realpath3(dirname3(file2)));
|
|
26403
|
+
const { system, project } = await candidates(root, controls);
|
|
26404
|
+
let managed = false;
|
|
26405
|
+
for (const directory of [system, project]) {
|
|
26406
|
+
if (await info2(directory) && comparable(await realpath3(directory)) === parent) managed = true;
|
|
26407
|
+
}
|
|
26408
|
+
if (!managed || basename(file2) === ".gitignore") return false;
|
|
26409
|
+
await unlink4(file2);
|
|
26410
|
+
return true;
|
|
26411
|
+
} catch {
|
|
26412
|
+
return false;
|
|
26413
|
+
}
|
|
26414
|
+
}
|
|
26415
|
+
|
|
26347
26416
|
// src/commands/spec-preview-commit.ts
|
|
26348
26417
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
26349
|
-
import { readFile as readFile10, mkdir as
|
|
26350
|
-
import { join as
|
|
26418
|
+
import { readFile as readFile10, mkdir as mkdir5, open as open4, rename as rename3, unlink as unlink5, rmdir as rmdir2, writeFile as writeFile3 } from "node:fs/promises";
|
|
26419
|
+
import { join as join11 } from "node:path";
|
|
26351
26420
|
|
|
26352
26421
|
// src/commands/spec-commit-files.ts
|
|
26353
|
-
import { createHash as
|
|
26354
|
-
import { lstat as
|
|
26355
|
-
import { join as
|
|
26422
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
26423
|
+
import { lstat as lstat6, readFile as readFile9 } from "node:fs/promises";
|
|
26424
|
+
import { join as join10 } from "node:path";
|
|
26356
26425
|
var fail6 = (message) => {
|
|
26357
26426
|
throw new SpecPreviewError(message);
|
|
26358
26427
|
};
|
|
26359
|
-
var hash2 = (value) =>
|
|
26428
|
+
var hash2 = (value) => createHash6("sha256").update(value).digest("hex");
|
|
26360
26429
|
var optional2 = (path3) => readFile9(path3).catch((e) => {
|
|
26361
26430
|
if (e.code === "ENOENT") return null;
|
|
26362
26431
|
throw e;
|
|
26363
26432
|
});
|
|
26364
|
-
var
|
|
26433
|
+
var info3 = (path3) => lstat6(path3).catch((e) => {
|
|
26365
26434
|
if (e.code === "ENOENT") return void 0;
|
|
26366
26435
|
throw e;
|
|
26367
26436
|
});
|
|
@@ -26373,11 +26442,11 @@ async function fingerprint(root, path3) {
|
|
|
26373
26442
|
validPath2(path3);
|
|
26374
26443
|
const parts = path3.split("/");
|
|
26375
26444
|
for (let i = 1; i <= parts.length; i++) {
|
|
26376
|
-
const target =
|
|
26377
|
-
const stat3 = await
|
|
26445
|
+
const target = join10(root, ...parts.slice(0, i));
|
|
26446
|
+
const stat3 = await info3(target);
|
|
26378
26447
|
if (!stat3) return null;
|
|
26379
26448
|
if (stat3.isSymbolicLink() || (i < parts.length ? !stat3.isDirectory() : !stat3.isFile())) fail6(t2("commitFiles.linkOrDirectory"));
|
|
26380
|
-
if (i < parts.length && await
|
|
26449
|
+
if (i < parts.length && await info3(join10(target, ".git"))) fail6(t2("commitFiles.nestedRepository"));
|
|
26381
26450
|
if (i === parts.length) {
|
|
26382
26451
|
if (stat3.nlink !== 1 || stat3.size > 16 * 1024 * 1024) fail6(t2("commitFiles.hardLinkOrSize"));
|
|
26383
26452
|
return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await readFile9(target)]));
|
|
@@ -26443,8 +26512,8 @@ async function previewCommit(cwd, action, input2) {
|
|
|
26443
26512
|
});
|
|
26444
26513
|
const indexPath = (await git(["rev-parse", "--path-format=absolute", "--git-path", "index"])).toString("utf8").trim();
|
|
26445
26514
|
const staged = async (index) => (await git(["diff", "--cached", "--ita-visible-in-index", "--name-only", "--no-renames", "-z"], index)).toString("utf8").split("\0").filter(Boolean).sort();
|
|
26446
|
-
const busy =
|
|
26447
|
-
if (await
|
|
26515
|
+
const busy = join11(gitDir, "gitifact-spec-commit.lock");
|
|
26516
|
+
if (await info3(busy)) fail6(t2("commit.busy", { path: busy }));
|
|
26448
26517
|
if ((await staged()).length) fail6(t2("commit.existingStagingPlan"));
|
|
26449
26518
|
const request = object3(input2);
|
|
26450
26519
|
let plan;
|
|
@@ -26501,33 +26570,33 @@ async function previewCommit(cwd, action, input2) {
|
|
|
26501
26570
|
if (!("plan" in refreshed) || refreshed.plan.digest !== plan.digest) fail6(t2("commit.planStale"));
|
|
26502
26571
|
const before = await reader.baseline();
|
|
26503
26572
|
const original = await optional2(indexPath);
|
|
26504
|
-
await
|
|
26505
|
-
const draftLock =
|
|
26573
|
+
await mkdir5(busy);
|
|
26574
|
+
const draftLock = join11(gitDir, "gitifact-spec-preview.lock");
|
|
26506
26575
|
let draftOwned = false;
|
|
26507
26576
|
let indexLock;
|
|
26508
26577
|
let uncertain = false;
|
|
26509
26578
|
let commitStarted = false;
|
|
26510
|
-
const temporary =
|
|
26579
|
+
const temporary = join11(gitDir, "gitifact-commit-index-" + randomUUID6());
|
|
26511
26580
|
const checkFiles = async () => {
|
|
26512
26581
|
for (const f of [...plan.files, ...plan.context]) if (f.hash !== await fingerprint(root, f.path)) fail6(t2("commit.fileChangedPreparing", { path: f.path }));
|
|
26513
26582
|
if ((await readLockedPreviewState(root)).stamp !== object3(plan.verification).stamp) fail6(t2("commit.specsChangedPreparing"));
|
|
26514
|
-
for (const name of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"]) if (await
|
|
26583
|
+
for (const name of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"]) if (await info3(join11(gitDir, name))) fail6(t2("commit.integrationStarted"));
|
|
26515
26584
|
};
|
|
26516
26585
|
try {
|
|
26517
26586
|
await verifyPreparedPreview(cwd, plan.verification, false);
|
|
26518
|
-
await
|
|
26587
|
+
await mkdir5(draftLock);
|
|
26519
26588
|
draftOwned = true;
|
|
26520
26589
|
indexLock = await open4(indexPath + ".lock", "wx", 384);
|
|
26521
26590
|
if (plan.index !== hash2(await optional2(indexPath) ?? Buffer.alloc(0)) || (await staged()).length) fail6(t2("commit.indexChangedLocked"));
|
|
26522
|
-
await
|
|
26523
|
-
if (original) await
|
|
26591
|
+
await writeFile3(join11(busy, "recovery.json"), JSON.stringify({ before, originalIndex: original?.toString("base64") ?? null, temporary, plan }));
|
|
26592
|
+
if (original) await writeFile3(temporary, original, { flag: "wx" });
|
|
26524
26593
|
else await git(["read-tree", "--empty"], temporary);
|
|
26525
26594
|
await git(["add", "--", ...selected], temporary);
|
|
26526
26595
|
const actual = await staged(temporary);
|
|
26527
26596
|
if (!actual.length || actual.some((p) => !selected.includes(p))) fail6(t2("commit.unexpectedFiles"));
|
|
26528
26597
|
for (const file2 of plan.files.filter((f) => record2(f.path) && f.hash !== null)) {
|
|
26529
26598
|
const stagedBytes = await git(["show", ":" + file2.path], temporary);
|
|
26530
|
-
if (!stagedBytes.equals(await readFile10(
|
|
26599
|
+
if (!stagedBytes.equals(await readFile10(join11(root, file2.path)))) fail6(t2("commit.filterChanged"));
|
|
26531
26600
|
}
|
|
26532
26601
|
await checkFiles();
|
|
26533
26602
|
if (JSON.stringify(before) !== JSON.stringify(await reader.baseline())) fail6(t2("commit.headChanged"));
|
|
@@ -26562,11 +26631,11 @@ async function previewCommit(cwd, action, input2) {
|
|
|
26562
26631
|
await indexLock?.close().catch(() => {
|
|
26563
26632
|
});
|
|
26564
26633
|
if (!uncertain) {
|
|
26565
|
-
if (indexLock) await
|
|
26634
|
+
if (indexLock) await unlink5(indexPath + ".lock").catch(() => {
|
|
26566
26635
|
});
|
|
26567
|
-
await
|
|
26636
|
+
await unlink5(temporary).catch(() => {
|
|
26568
26637
|
});
|
|
26569
|
-
await
|
|
26638
|
+
await unlink5(join11(busy, "recovery.json")).catch(() => {
|
|
26570
26639
|
});
|
|
26571
26640
|
await rmdir2(busy);
|
|
26572
26641
|
if (draftOwned) await rmdir2(draftLock);
|
|
@@ -26575,9 +26644,9 @@ async function previewCommit(cwd, action, input2) {
|
|
|
26575
26644
|
}
|
|
26576
26645
|
|
|
26577
26646
|
// src/commands/spec-commit.ts
|
|
26578
|
-
import { createHash as
|
|
26579
|
-
import { mkdir as
|
|
26580
|
-
import { join as
|
|
26647
|
+
import { createHash as createHash8, randomUUID as randomUUID7 } from "node:crypto";
|
|
26648
|
+
import { mkdir as mkdir6, open as open5, readFile as readFile11, rename as rename4, rmdir as rmdir3, unlink as unlink6, writeFile as writeFile4 } from "node:fs/promises";
|
|
26649
|
+
import { join as join12 } from "node:path";
|
|
26581
26650
|
var fields = ["reasons", "paths", "message", "authorization", "requirements", "policyFiles", "expected"];
|
|
26582
26651
|
var integration = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"];
|
|
26583
26652
|
var same2 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
@@ -26616,9 +26685,9 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26616
26685
|
...stdin ? { input: stdin } : {}
|
|
26617
26686
|
});
|
|
26618
26687
|
const staged = async (index) => (await git(["diff", "--cached", "--ita-visible-in-index", "--name-only", "--no-renames", "-z"], index)).toString("utf8").split("\0").filter(Boolean).sort();
|
|
26619
|
-
const busy =
|
|
26688
|
+
const busy = join12(gitDir, "gitifact-spec-commit.lock");
|
|
26620
26689
|
await failOnLegacyLock(gitDir);
|
|
26621
|
-
if (await
|
|
26690
|
+
if (await info3(busy)) fail6(t2("commit.busy", { path: busy }));
|
|
26622
26691
|
if ((await staged()).length) fail6(t2("commit.existingStaging"));
|
|
26623
26692
|
const indexHash = hash2(await optional2(indexPath) ?? Buffer.alloc(0));
|
|
26624
26693
|
const current = c.working;
|
|
@@ -26627,7 +26696,7 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26627
26696
|
const prepared = prepareSpecPreview(c.bundle, current.bundle, c.files, current.files, reasons, () => generatePreviewId("H"));
|
|
26628
26697
|
const blobId = (text2) => {
|
|
26629
26698
|
const bytes = Buffer.from(text2);
|
|
26630
|
-
return
|
|
26699
|
+
return createHash8(objectFormat).update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
|
|
26631
26700
|
};
|
|
26632
26701
|
const present = [...current.files.keys()];
|
|
26633
26702
|
if (present.some((p) => p.includes("\n"))) fail6(t2("commit.newlinePath"));
|
|
@@ -26670,14 +26739,14 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26670
26739
|
...prepared.changes.filter((c2) => c2.kind === "design").map((c2) => "Gitifact-Design: " + c2.id),
|
|
26671
26740
|
...prepared.changes.filter((c2) => c2.kind === "product" || c2.kind === "guide").map((c2) => "Gitifact-Doc: " + c2.id)
|
|
26672
26741
|
];
|
|
26673
|
-
const temporary =
|
|
26742
|
+
const temporary = join12(gitDir, "gitifact-commit-index-" + randomUUID7());
|
|
26674
26743
|
let owned = false;
|
|
26675
26744
|
let uncertain = false;
|
|
26676
26745
|
let indexLock;
|
|
26677
26746
|
let committed;
|
|
26678
26747
|
try {
|
|
26679
26748
|
try {
|
|
26680
|
-
await
|
|
26749
|
+
await mkdir6(busy);
|
|
26681
26750
|
owned = true;
|
|
26682
26751
|
} catch (e) {
|
|
26683
26752
|
if (e.code === "EEXIST") fail6(t2("commit.busy", { path: busy }));
|
|
@@ -26691,8 +26760,8 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26691
26760
|
if (hash2(original ?? Buffer.alloc(0)) !== indexHash || (await staged()).length) fail6(t2("commit.indexChanged"));
|
|
26692
26761
|
const locked = await hashes([.../* @__PURE__ */ new Set([...selected, ...contextPaths])]);
|
|
26693
26762
|
for (const [path3, value] of started) if (locked.get(path3) !== value) fail6(t2("commit.fileChangedRunning", { path: path3 }));
|
|
26694
|
-
await
|
|
26695
|
-
if (original) await
|
|
26763
|
+
await writeFile4(join12(busy, "recovery.json"), JSON.stringify({ before: c.base, originalIndex: original?.toString("base64") ?? null, temporary, paths: selected, message, requirements }));
|
|
26764
|
+
if (original) await writeFile4(temporary, original, { flag: "wx" });
|
|
26696
26765
|
else await git(["read-tree", "--empty"], temporary);
|
|
26697
26766
|
await git(["add", "--", ...stageable], temporary);
|
|
26698
26767
|
const actual = await staged(temporary);
|
|
@@ -26707,7 +26776,7 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26707
26776
|
const size = Number(header[2]);
|
|
26708
26777
|
if (end < 0 || header[1] !== "blob" || !Number.isSafeInteger(size) || output2[end + 1 + size] !== 10) fail6(t2("commit.stagedUnreadable", { path: path3 }));
|
|
26709
26778
|
const staged2 = output2.subarray(end + 1, end + 1 + size);
|
|
26710
|
-
const file2 = await readFile11(
|
|
26779
|
+
const file2 = await readFile11(join12(root, path3));
|
|
26711
26780
|
if (!staged2.equals(file2) && !staged2.equals(Buffer.from(file2.toString("latin1").replace(/\r\n/g, "\n"), "latin1"))) fail6(t2("commit.filterChanged"));
|
|
26712
26781
|
offset = end + size + 2;
|
|
26713
26782
|
}
|
|
@@ -26715,7 +26784,7 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26715
26784
|
const again = await hashes([...locked.keys()]);
|
|
26716
26785
|
for (const [path3, value] of locked) if (again.get(path3) !== value) fail6(t2("commit.fileChangedPreparing", { path: path3 }));
|
|
26717
26786
|
if ((await readLockedPreviewState(root)).stamp !== published.stamp) fail6(t2("commit.specsChangedPreparing"));
|
|
26718
|
-
for (const name of integration) if (await
|
|
26787
|
+
for (const name of integration) if (await info3(join12(gitDir, name))) fail6(t2("commit.integrationStarted"));
|
|
26719
26788
|
if (!same2(c.base, await c.reader.baseline())) fail6(t2("commit.headChanged"));
|
|
26720
26789
|
const tree = (await git(["write-tree"], temporary)).toString("utf8").trim();
|
|
26721
26790
|
commitStarted = true;
|
|
@@ -26752,12 +26821,12 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26752
26821
|
await indexLock?.close().catch(() => {
|
|
26753
26822
|
});
|
|
26754
26823
|
if (!uncertain) {
|
|
26755
|
-
if (indexLock) await
|
|
26824
|
+
if (indexLock) await unlink6(indexPath + ".lock").catch(() => {
|
|
26756
26825
|
});
|
|
26757
|
-
await
|
|
26826
|
+
await unlink6(temporary).catch(() => {
|
|
26758
26827
|
});
|
|
26759
26828
|
if (owned) {
|
|
26760
|
-
await
|
|
26829
|
+
await unlink6(join12(busy, "recovery.json")).catch(() => {
|
|
26761
26830
|
});
|
|
26762
26831
|
await rmdir3(busy);
|
|
26763
26832
|
}
|
|
@@ -26768,13 +26837,13 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26768
26837
|
|
|
26769
26838
|
// src/commands/spec-preview.ts
|
|
26770
26839
|
var operations = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"];
|
|
26771
|
-
var runSpecPreview = (action, options) => withCommandScope(() => execute(action, options));
|
|
26772
|
-
async function execute(action, options) {
|
|
26840
|
+
var runSpecPreview = (action, options, controls = {}) => withCommandScope(() => execute(action, options, controls));
|
|
26841
|
+
async function execute(action, options, controls) {
|
|
26773
26842
|
const envelope = { contract: "spec", version: 1 };
|
|
26774
26843
|
try {
|
|
26775
26844
|
const guard = specPreviewReader(process.cwd());
|
|
26776
26845
|
const { root, gitDir, objectFormat } = await guard.location();
|
|
26777
|
-
for (const marker2 of operations) if (await fileInfo(
|
|
26846
|
+
for (const marker2 of operations) if (await fileInfo(join13(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
|
|
26778
26847
|
if (await guard.hasUnmerged()) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
26779
26848
|
const raw = await readConfigFile(root);
|
|
26780
26849
|
if (raw === void 0) throw new SpecPreviewError(t2("preview.notInitialized"));
|
|
@@ -26783,12 +26852,11 @@ async function execute(action, options) {
|
|
|
26783
26852
|
await initRepository(root).validateBaseline(config2, root, "HEAD", objectFormat);
|
|
26784
26853
|
if (["working", "save", "changes", "prepare", "verify", "commit-plan", "commit-apply", "commit"].includes(action)) {
|
|
26785
26854
|
let result;
|
|
26786
|
-
|
|
26787
|
-
|
|
26855
|
+
const inputs = () => prepareAgentInputs(root, controls).catch(() => void 0);
|
|
26856
|
+
if (action === "working") result = narrowWorking(await readWorkingPreview(process.cwd()), options, await inputs());
|
|
26857
|
+
else if (action === "changes") result = { ...await readFinalPreviewChanges(process.cwd()), inputs: await inputs() };
|
|
26788
26858
|
else {
|
|
26789
|
-
const
|
|
26790
|
-
if (!source.isFile() || source.size > 1024 * 1024) throw new SpecPreviewError(t2("preview.inputFile"));
|
|
26791
|
-
const bytes = await readFile12(options.file);
|
|
26859
|
+
const bytes = options.file === "-" ? await readStdin(controls.stdin ?? process.stdin) : await readInputFile(options.file);
|
|
26792
26860
|
if (bytes.length > 1024 * 1024) throw new SpecPreviewError(t2("preview.inputSize"));
|
|
26793
26861
|
let input2;
|
|
26794
26862
|
try {
|
|
@@ -26797,6 +26865,8 @@ async function execute(action, options) {
|
|
|
26797
26865
|
throw new SpecPreviewError(t2("preview.inputJson"));
|
|
26798
26866
|
}
|
|
26799
26867
|
result = action === "commit" ? await specCommit(process.cwd(), input2, !!options.dryRun) : action === "commit-plan" || action === "commit-apply" ? await previewCommit(process.cwd(), action === "commit-plan" ? "plan" : "apply", input2) : action === "prepare" ? await prepareWorkingPreview(process.cwd(), input2) : action === "verify" ? await verifyPreparedPreview(process.cwd(), input2, !!options.staged) : await saveWorkingPreview(process.cwd(), input2);
|
|
26868
|
+
const consumed = action === "save" || action === "commit" && result.outcome === "committed";
|
|
26869
|
+
if (consumed && options.file !== "-") result = { ...result, inputRemoved: await discardAgentInput(root, options.file, controls) };
|
|
26800
26870
|
}
|
|
26801
26871
|
process.stdout.write(JSON.stringify({ ...envelope, ok: true, ...result }) + "\n");
|
|
26802
26872
|
return;
|
|
@@ -26817,13 +26887,46 @@ async function execute(action, options) {
|
|
|
26817
26887
|
process.exitCode = 1;
|
|
26818
26888
|
}
|
|
26819
26889
|
}
|
|
26890
|
+
async function readInputFile(path3) {
|
|
26891
|
+
const source = await stat2(path3);
|
|
26892
|
+
if (!source.isFile() || source.size > 1024 * 1024) throw new SpecPreviewError(t2("preview.inputFile"));
|
|
26893
|
+
return readFile12(path3);
|
|
26894
|
+
}
|
|
26895
|
+
async function readStdin(stream) {
|
|
26896
|
+
const chunks = [];
|
|
26897
|
+
let size = 0;
|
|
26898
|
+
for await (const chunk of stream) {
|
|
26899
|
+
size += chunk.length;
|
|
26900
|
+
if (size > 1024 * 1024) throw new SpecPreviewError(t2("preview.inputSize"));
|
|
26901
|
+
chunks.push(chunk);
|
|
26902
|
+
}
|
|
26903
|
+
return Buffer.concat(chunks);
|
|
26904
|
+
}
|
|
26905
|
+
function narrowWorking(working, options, inputs) {
|
|
26906
|
+
if (options.stamp) return { stamp: working.stamp, inputs };
|
|
26907
|
+
let { specs, documents, warnings } = working;
|
|
26908
|
+
if (options.feature !== void 0) {
|
|
26909
|
+
specs = specs.filter((s) => s.path === ".gitifact/spec/" + options.feature + "/requirements.md");
|
|
26910
|
+
if (!specs.length) throw new SpecPreviewError(t2("preview.unknownFeature", { feature: options.feature }));
|
|
26911
|
+
documents = [];
|
|
26912
|
+
warnings = warnings.filter((w) => w.specId === specs[0].id);
|
|
26913
|
+
}
|
|
26914
|
+
if (!options.ids) return { stamp: working.stamp, inputs, specs, documents, warnings };
|
|
26915
|
+
return {
|
|
26916
|
+
stamp: working.stamp,
|
|
26917
|
+
inputs,
|
|
26918
|
+
warnings,
|
|
26919
|
+
specs: specs.map((s) => ({ id: s.id, path: s.path, title: s.title, design: s.design?.title ?? null, requirements: s.requirements.map((r) => ({ id: r.id, title: r.title })) })),
|
|
26920
|
+
documents: documents.map((set2) => ({ kind: set2.kind, documents: set2.documents.map((d) => ({ id: d.id, path: d.path, title: d.title })) }))
|
|
26921
|
+
};
|
|
26922
|
+
}
|
|
26820
26923
|
|
|
26821
26924
|
// src/commands/migrate.ts
|
|
26822
|
-
import { lstat as
|
|
26823
|
-
import { join as
|
|
26824
|
-
import { randomBytes as
|
|
26925
|
+
import { lstat as lstat8, readdir as readdir5, readFile as readFile13, rename as rename5, writeFile as writeFile5, unlink as unlink7 } from "node:fs/promises";
|
|
26926
|
+
import { join as join14 } from "node:path";
|
|
26927
|
+
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
26825
26928
|
var operations2 = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"];
|
|
26826
|
-
var
|
|
26929
|
+
var info4 = (path3) => lstat8(path3).catch((e) => {
|
|
26827
26930
|
if (e.code === "ENOENT") return void 0;
|
|
26828
26931
|
throw e;
|
|
26829
26932
|
});
|
|
@@ -26834,40 +26937,40 @@ var fail7 = (code, message) => {
|
|
|
26834
26937
|
async function migrateStore(cwd, dryRun = false) {
|
|
26835
26938
|
const reader = specPreviewReader(cwd);
|
|
26836
26939
|
const { root, gitDir } = await reader.location();
|
|
26837
|
-
for (const marker3 of operations2) if (await
|
|
26940
|
+
for (const marker3 of operations2) if (await info4(join14(gitDir, marker3))) fail7("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker3 }));
|
|
26838
26941
|
if (await reader.hasUnmerged()) fail7("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
26839
|
-
for (const name of [...LEGACY_LOCKS, "gitifact-spec-preview.lock", "gitifact-spec-commit.lock"]) if (await
|
|
26840
|
-
const from =
|
|
26841
|
-
const to =
|
|
26842
|
-
const fromInfo = await
|
|
26843
|
-
if (await
|
|
26942
|
+
for (const name of [...LEGACY_LOCKS, "gitifact-spec-preview.lock", "gitifact-spec-commit.lock"]) if (await info4(join14(gitDir, name))) fail7("LOCKED", t2("migrate.locked", { path: join14(gitDir, name) }));
|
|
26943
|
+
const from = join14(root, ".tryce");
|
|
26944
|
+
const to = join14(root, ".gitifact");
|
|
26945
|
+
const fromInfo = await info4(from);
|
|
26946
|
+
if (await info4(to)) fail7("ALREADY_MIGRATED", t2("migrate.alreadyMigrated"));
|
|
26844
26947
|
if (!fromInfo) return fail7("NOTHING_TO_MIGRATE", t2("migrate.nothingToMigrate"));
|
|
26845
26948
|
if (!fromInfo.isDirectory() || fromInfo.isSymbolicLink()) fail7("PATH_CONFLICT", t2("migrate.notDirectory"));
|
|
26846
|
-
const configInfo = await
|
|
26949
|
+
const configInfo = await info4(join14(from, "config.json"));
|
|
26847
26950
|
if (!configInfo?.isFile() || configInfo.isSymbolicLink()) fail7("NOT_INITIALIZED", t2("migrate.noConfig"));
|
|
26848
|
-
const config2 = parseManagedConfig(decode4(await readFile13(
|
|
26951
|
+
const config2 = parseManagedConfig(decode4(await readFile13(join14(from, "config.json"))));
|
|
26849
26952
|
if (!("schemaVersion" in config2)) fail7("UNSUPPORTED_FORMAT", t2("migrate.legacyJson"));
|
|
26850
|
-
const top = (await
|
|
26953
|
+
const top = (await readdir5(from)).sort();
|
|
26851
26954
|
if (top.some((name) => name !== "config.json" && name !== "spec")) fail7("UNSUPPORTED_FORMAT", t2("migrate.extraEntries"));
|
|
26852
26955
|
const files = /* @__PURE__ */ new Map();
|
|
26853
26956
|
const rewrites = [];
|
|
26854
26957
|
const legacyRecords = [];
|
|
26855
26958
|
const marker2 = /^<!-- tryce-(spec|req|design|ref): /;
|
|
26856
26959
|
if (top.includes("spec")) {
|
|
26857
|
-
for (const feature2 of (await
|
|
26858
|
-
const dir =
|
|
26859
|
-
const stat3 = await
|
|
26960
|
+
for (const feature2 of (await readdir5(join14(from, "spec"))).sort()) {
|
|
26961
|
+
const dir = join14(from, "spec", feature2);
|
|
26962
|
+
const stat3 = await info4(dir);
|
|
26860
26963
|
if (!stat3?.isDirectory() || stat3.isSymbolicLink()) fail7("UNSUPPORTED_FORMAT", t2("migrate.notSpecFolder", { feature: feature2 }));
|
|
26861
|
-
for (const name of (await
|
|
26964
|
+
for (const name of (await readdir5(dir)).sort()) {
|
|
26862
26965
|
if (!["requirements.md", "design.md", "history.jsonl", "tryce.json"].includes(name)) fail7("UNSUPPORTED_FORMAT", t2("migrate.unsupportedFile", { feature: feature2, name }));
|
|
26863
|
-
const fileStat = await
|
|
26966
|
+
const fileStat = await info4(join14(dir, name));
|
|
26864
26967
|
if (!fileStat?.isFile() || fileStat.isSymbolicLink() || fileStat.nlink !== 1 || fileStat.size > 1024 * 1024) fail7("UNSUPPORTED_FORMAT", t2("migrate.fileTooLarge", { name }));
|
|
26865
26968
|
const newPath = `.gitifact/spec/${feature2}/${name}`;
|
|
26866
26969
|
if (name === "tryce.json") {
|
|
26867
26970
|
legacyRecords.push(newPath);
|
|
26868
26971
|
continue;
|
|
26869
26972
|
}
|
|
26870
|
-
const text2 = decode4(await readFile13(
|
|
26973
|
+
const text2 = decode4(await readFile13(join14(dir, name)));
|
|
26871
26974
|
if (name === "history.jsonl") {
|
|
26872
26975
|
files.set(newPath, text2);
|
|
26873
26976
|
continue;
|
|
@@ -26912,13 +27015,13 @@ async function migrateStore(cwd, dryRun = false) {
|
|
|
26912
27015
|
if (dryRun) return result("planned");
|
|
26913
27016
|
await rename5(from, to);
|
|
26914
27017
|
for (const r of rewrites) {
|
|
26915
|
-
const full =
|
|
26916
|
-
const temp =
|
|
26917
|
-
await
|
|
27018
|
+
const full = join14(root, r.path);
|
|
27019
|
+
const temp = join14(root, ".gitifact", "spec", ".gitifact-migrate-" + randomBytes3(8).toString("hex"));
|
|
27020
|
+
await writeFile5(temp, r.content, { flag: "wx" });
|
|
26918
27021
|
try {
|
|
26919
27022
|
await rename5(temp, full);
|
|
26920
27023
|
} finally {
|
|
26921
|
-
await
|
|
27024
|
+
await unlink7(temp).catch(() => {
|
|
26922
27025
|
});
|
|
26923
27026
|
}
|
|
26924
27027
|
}
|
|
@@ -26936,16 +27039,16 @@ async function runMigrate(options) {
|
|
|
26936
27039
|
}
|
|
26937
27040
|
|
|
26938
27041
|
// src/main.ts
|
|
26939
|
-
var program2 = new Command().name("gitifact").description(t2("help.program")).version("0.4.
|
|
27042
|
+
var program2 = new Command().name("gitifact").description(t2("help.program")).version("0.4.2").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
|
|
26940
27043
|
program2.command("status").description(t2("help.status")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action(async (options) => {
|
|
26941
27044
|
await runStatus(options.format);
|
|
26942
27045
|
});
|
|
26943
|
-
program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).option("--no-update-check", t2("help.browserNoUpdateCheck")).action((options) => runBrowser(options, "0.4.
|
|
26944
|
-
program2.command("init").description(t2("help.init")).allowExcessArguments(false).option("--dry-run", t2("help.initDryRun")).addOption(new Option("--agent <agent>", t2("help.initAgent")).choices([...agentPresetNames])).addOption(new Option("--remove-agents", t2("help.initRemoveAgents")).conflicts("skipAgents")).option("--skip-agents", t2("help.initSkipAgents")).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runInit(options, "0.4.
|
|
27046
|
+
program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).option("--no-update-check", t2("help.browserNoUpdateCheck")).action((options) => runBrowser(options, "0.4.2"));
|
|
27047
|
+
program2.command("init").description(t2("help.init")).allowExcessArguments(false).option("--dry-run", t2("help.initDryRun")).addOption(new Option("--agent <agent>", t2("help.initAgent")).choices([...agentPresetNames])).addOption(new Option("--remove-agents", t2("help.initRemoveAgents")).conflicts("skipAgents")).option("--skip-agents", t2("help.initSkipAgents")).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runInit(options, "0.4.2"));
|
|
26945
27048
|
program2.command("docs").description(t2("help.docs")).argument("[topic]", t2("help.docsTopic")).allowExcessArguments(false).action(async (topic) => {
|
|
26946
27049
|
await runDocs(topic);
|
|
26947
27050
|
});
|
|
26948
|
-
program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runUpdate(options, "0.4.
|
|
27051
|
+
program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runUpdate(options, "0.4.2"));
|
|
26949
27052
|
program2.command("migrate").description(t2("help.migrate")).allowExcessArguments(false).option("--dry-run", t2("help.migrateDryRun")).action(runMigrate);
|
|
26950
27053
|
var spec = program2.command("spec").description(t2("help.spec"));
|
|
26951
27054
|
var replaced = t2("help.deprecated");
|
|
@@ -26954,7 +27057,7 @@ for (const action of ["commit-plan", "commit-apply"]) spec.command(action).descr
|
|
|
26954
27057
|
spec.command("changes").description(t2("help.specChanges")).allowExcessArguments(false).action((o) => runSpecPreview("changes", o));
|
|
26955
27058
|
spec.command("prepare").description(replaced).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specPrepareFile")).action((o) => runSpecPreview("prepare", o));
|
|
26956
27059
|
spec.command("verify").description(replaced).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specVerifyFile")).option("--staged", t2("help.specVerifyStaged")).action((o) => runSpecPreview("verify", o));
|
|
26957
|
-
spec.command("working").description(t2("help.specWorking")).allowExcessArguments(false).action((o) => runSpecPreview("working", o));
|
|
27060
|
+
spec.command("working").description(t2("help.specWorking")).allowExcessArguments(false).addOption(new Option("--stamp", t2("help.specWorkingStamp")).conflicts(["feature", "ids"])).option("--feature <name>", t2("help.specWorkingFeature")).option("--ids", t2("help.specWorkingIds")).action((o) => runSpecPreview("working", o));
|
|
26958
27061
|
spec.command("save").description(t2("help.specSave")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specSaveFile")).action((o) => runSpecPreview("save", o));
|
|
26959
27062
|
spec.command("read").description(t2("help.specRead")).allowExcessArguments(false).option("--ref <commit>", t2("help.specReadRef"), "HEAD").action((o) => runSpecPreview("read", o));
|
|
26960
27063
|
spec.command("diff").description(t2("help.specDiff")).allowExcessArguments(false).requiredOption("--from <commit>", t2("help.specDiffFrom")).requiredOption("--to <commit>", t2("help.specDiffTo")).action((o) => runSpecPreview("diff", o));
|