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.
Files changed (62) hide show
  1. package/dist/browser/assets/BottomSheet-F2BUQwSi.js +1 -0
  2. package/dist/browser/assets/Card-C0juPkmX.js +1 -0
  3. package/dist/browser/assets/IconButton-CkA9oftf.js +1 -0
  4. package/dist/browser/assets/Markdown-D7VrGOLZ.js +68 -0
  5. package/dist/browser/assets/{MenuBottomSheet-BkRC4_VW.js → MenuBottomSheet-CQA7HL9k.js} +1 -1
  6. package/dist/browser/assets/{MetadataListItem-BJjmYUP-.js → MetadataListItem-DRZdPsPv.js} +1 -1
  7. package/dist/browser/assets/Section-zmL2D3WL.js +1 -0
  8. package/dist/browser/assets/Table-DxOgh9uC.js +3 -0
  9. package/dist/browser/assets/TimestampHoverCard-DOWpOAzA.js +1 -0
  10. package/dist/browser/assets/about-K6mG2f8D.js +3 -0
  11. package/dist/browser/assets/changelog-7YrQ3ibl.js +2 -0
  12. package/dist/browser/assets/composeEventHandlers-CHIontwB.js +1 -0
  13. package/dist/browser/assets/container.stylex-oPimSCGl.js +1 -0
  14. package/dist/browser/assets/{contributors._email-CwG6z4oO.js → contributors._email-PmuGt4HK.js} +1 -1
  15. package/dist/browser/assets/{contributors.index-B9l1YPjl.js → contributors.index-Du6gcymD.js} +1 -1
  16. package/dist/browser/assets/devWarning-BZMSgwyk.js +1 -0
  17. package/dist/browser/assets/document-B1QpmAOH.js +1 -0
  18. package/dist/browser/assets/document-D41OCO3e.css +1 -0
  19. package/dist/browser/assets/{features._featureId-uB5QcPIl.js → features._featureId-DzAIhNyX.js} +1 -1
  20. package/dist/browser/assets/{requirements-BMLc9Fpl.js → features.index-D9wmqimq.js} +1 -1
  21. package/dist/browser/assets/git-cGldo_jC.js +1 -0
  22. package/dist/browser/assets/guides._documentId-BEv09vs4.js +1 -0
  23. package/dist/browser/assets/{guides.index-BfJqdqJd.js → guides.index-tfySk9wY.js} +1 -1
  24. package/dist/browser/assets/index-B5Ql9tDp.js +56 -0
  25. package/dist/browser/assets/page-header-8LgEWnon.js +126 -0
  26. package/dist/browser/assets/product-BrvAWtBo.css +1 -0
  27. package/dist/browser/assets/product-Q9uoNMvu.js +8 -0
  28. package/dist/browser/assets/product.document-Bl25IX1S.js +1 -0
  29. package/dist/browser/assets/product.index-BwKqT4MY.js +1 -0
  30. package/dist/browser/assets/request-state-sfsdVRHj.js +1 -0
  31. package/dist/browser/assets/{features.index-DzLFYkRG.js → requirements-B9rmmF27.js} +1 -1
  32. package/dist/browser/assets/{routes-XUldGkLf.js → routes-COAEfNb7.js} +1 -1
  33. package/dist/browser/assets/settings-BvuMkHCB.css +1 -0
  34. package/dist/browser/assets/settings-Cv6WtTcC.js +1 -0
  35. package/dist/browser/assets/useDevWarning-Xg7kPMHJ.js +1 -0
  36. package/dist/browser/assets/useMediaQuery-DFlnKIlp.js +1 -0
  37. package/dist/browser/assets/useTranslator-DY2HN18N.js +4 -0
  38. package/dist/browser/index.html +19 -11
  39. package/dist/i18n/ko/block.md +6 -4
  40. package/dist/i18n/ko/changelog.md +23 -0
  41. package/dist/i18n/ko/docs/commit.md +1 -1
  42. package/dist/i18n/ko/docs/spec.md +1 -1
  43. package/dist/i18n/ko/docs/workflow.md +10 -0
  44. package/dist/main.js +197 -94
  45. package/package.json +1 -1
  46. package/dist/browser/assets/BottomSheet-CUR7U0gF.js +0 -1
  47. package/dist/browser/assets/IconButton-BqlnBu_N.js +0 -4
  48. package/dist/browser/assets/Markdown-BG_9T3yA.js +0 -68
  49. package/dist/browser/assets/Section-DQRr6JoK.js +0 -1
  50. package/dist/browser/assets/TimestampHoverCard-ClDQXGeS.js +0 -1
  51. package/dist/browser/assets/about-C5lrF_v9.js +0 -3
  52. package/dist/browser/assets/changelog-hNvOtw70.js +0 -2
  53. package/dist/browser/assets/git-DJKAcbnl.js +0 -1
  54. package/dist/browser/assets/guides._documentId-DHM6effA.js +0 -1
  55. package/dist/browser/assets/index-jaVGAf81.js +0 -56
  56. package/dist/browser/assets/page-header-DI5eoQC1.js +0 -127
  57. package/dist/browser/assets/product-CV4EzacY.css +0 -1
  58. package/dist/browser/assets/product-YuwMeOC0.js +0 -8
  59. package/dist/browser/assets/product.index-RgfLdFqG.js +0 -1
  60. package/dist/browser/assets/request-state-DpUKcy6G.js +0 -1
  61. package/dist/browser/assets/useDevWarning-CzR6rkf6.js +0 -1
  62. 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, candidates) {
1104
- if (!candidates || candidates.length === 0) return "";
1105
- candidates = Array.from(new Set(candidates));
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
- candidates = candidates.map((candidate) => candidate.slice(2));
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
- candidates.forEach((candidate) => {
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 info4 = await fileInfo(path3);
25190
- if (info4 && (!info4.isDirectory() || info4.isSymbolicLink())) throw new InitError("PATH_CONFLICT", t2("config.storeNotDirectory"));
25191
- return info4;
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 info4 = await fileInfo(path3);
25197
- if (!info4) {
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 (!info4.isFile() || info4.isSymbolicLink() || info4.size > 65536) throw new InitError("PATH_CONFLICT", t2("config.fileShape"));
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 !== info4.ino || after.dev !== info4.dev || after.mtimeMs !== info4.mtimeMs || bytes.length > 65536) {
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 info4 = await fileInfo(full);
25905
- if (!info4 && create && i < parts.length - 1) {
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
- info4 = await fileInfo(full);
25913
+ info5 = await fileInfo(full);
25910
25914
  }
25911
- if (info4 && (info4.isSymbolicLink() || (i < parts.length - 1 ? !info4.isDirectory() : !info4.isFile()))) {
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 join12 } from "node:path";
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 mkdir4, open as open4, rename as rename3, unlink as unlink4, rmdir as rmdir2, writeFile as writeFile2 } from "node:fs/promises";
26350
- import { join as join10 } from "node:path";
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 createHash5 } from "node:crypto";
26354
- import { lstat as lstat5, readFile as readFile9 } from "node:fs/promises";
26355
- import { join as join9 } from "node:path";
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) => createHash5("sha256").update(value).digest("hex");
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 info2 = (path3) => lstat5(path3).catch((e) => {
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 = join9(root, ...parts.slice(0, i));
26377
- const stat3 = await info2(target);
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 info2(join9(target, ".git"))) fail6(t2("commitFiles.nestedRepository"));
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 = join10(gitDir, "gitifact-spec-commit.lock");
26447
- if (await info2(busy)) fail6(t2("commit.busy", { path: busy }));
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 mkdir4(busy);
26505
- const draftLock = join10(gitDir, "gitifact-spec-preview.lock");
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 = join10(gitDir, "gitifact-commit-index-" + randomUUID6());
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 info2(join10(gitDir, name))) fail6(t2("commit.integrationStarted"));
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 mkdir4(draftLock);
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 writeFile2(join10(busy, "recovery.json"), JSON.stringify({ before, originalIndex: original?.toString("base64") ?? null, temporary, plan }));
26523
- if (original) await writeFile2(temporary, original, { flag: "wx" });
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(join10(root, file2.path)))) fail6(t2("commit.filterChanged"));
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 unlink4(indexPath + ".lock").catch(() => {
26634
+ if (indexLock) await unlink5(indexPath + ".lock").catch(() => {
26566
26635
  });
26567
- await unlink4(temporary).catch(() => {
26636
+ await unlink5(temporary).catch(() => {
26568
26637
  });
26569
- await unlink4(join10(busy, "recovery.json")).catch(() => {
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 createHash7, randomUUID as randomUUID7 } from "node:crypto";
26579
- import { mkdir as mkdir5, open as open5, readFile as readFile11, rename as rename4, rmdir as rmdir3, unlink as unlink5, writeFile as writeFile3 } from "node:fs/promises";
26580
- import { join as join11 } from "node:path";
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 = join11(gitDir, "gitifact-spec-commit.lock");
26688
+ const busy = join12(gitDir, "gitifact-spec-commit.lock");
26620
26689
  await failOnLegacyLock(gitDir);
26621
- if (await info2(busy)) fail6(t2("commit.busy", { path: busy }));
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 createHash7(objectFormat).update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
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 = join11(gitDir, "gitifact-commit-index-" + randomUUID7());
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 mkdir5(busy);
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 writeFile3(join11(busy, "recovery.json"), JSON.stringify({ before: c.base, originalIndex: original?.toString("base64") ?? null, temporary, paths: selected, message, requirements }));
26695
- if (original) await writeFile3(temporary, original, { flag: "wx" });
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(join11(root, path3));
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 info2(join11(gitDir, name))) fail6(t2("commit.integrationStarted"));
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 unlink5(indexPath + ".lock").catch(() => {
26824
+ if (indexLock) await unlink6(indexPath + ".lock").catch(() => {
26756
26825
  });
26757
- await unlink5(temporary).catch(() => {
26826
+ await unlink6(temporary).catch(() => {
26758
26827
  });
26759
26828
  if (owned) {
26760
- await unlink5(join11(busy, "recovery.json")).catch(() => {
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(join12(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
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
- if (action === "working") result = await readWorkingPreview(process.cwd());
26787
- else if (action === "changes") result = await readFinalPreviewChanges(process.cwd());
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 source = await stat2(options.file);
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 lstat7, readdir as readdir4, readFile as readFile13, rename as rename5, writeFile as writeFile4, unlink as unlink6 } from "node:fs/promises";
26823
- import { join as join13 } from "node:path";
26824
- import { randomBytes as randomBytes2 } from "node:crypto";
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 info3 = (path3) => lstat7(path3).catch((e) => {
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 info3(join13(gitDir, marker3))) fail7("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker3 }));
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 info3(join13(gitDir, name))) fail7("LOCKED", t2("migrate.locked", { path: join13(gitDir, name) }));
26840
- const from = join13(root, ".tryce");
26841
- const to = join13(root, ".gitifact");
26842
- const fromInfo = await info3(from);
26843
- if (await info3(to)) fail7("ALREADY_MIGRATED", t2("migrate.alreadyMigrated"));
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 info3(join13(from, "config.json"));
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(join13(from, "config.json"))));
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 readdir4(from)).sort();
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 readdir4(join13(from, "spec"))).sort()) {
26858
- const dir = join13(from, "spec", feature2);
26859
- const stat3 = await info3(dir);
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 readdir4(dir)).sort()) {
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 info3(join13(dir, name));
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(join13(dir, name)));
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 = join13(root, r.path);
26916
- const temp = join13(root, ".gitifact", "spec", ".gitifact-migrate-" + randomBytes2(8).toString("hex"));
26917
- await writeFile4(temp, r.content, { flag: "wx" });
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 unlink6(temp).catch(() => {
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.0").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
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.0"));
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.0"));
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.0"));
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));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitifact",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Git-backed requirements and change history for coding agents.",
5
5
  "license": "MIT",
6
6
  "repository": {