gitifact 0.8.6 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -36
- package/dist/browser/assets/{HgiRefresh-CnBE2KZ8.js → HgiRefresh-CmdxsKUC.js} +1 -1
- package/dist/browser/assets/{Markdown-75QVB57V.js → Markdown-BpWtY88p.js} +1 -1
- package/dist/browser/assets/{Selector-E8jyEKNB.js → Selector-Dji19JSe.js} +1 -1
- package/dist/browser/assets/{Tab-C-PhLRIZ.js → Tab-BY4IuGKn.js} +1 -1
- package/dist/browser/assets/{Table-Cr2jvka_.js → Table-Dm6wz2kf.js} +2 -2
- package/dist/browser/assets/{Token-BBk7tRek.js → Token-9hr7eTF1.js} +1 -1
- package/dist/browser/assets/about-C3s6Keuk.js +3 -0
- package/dist/browser/assets/activity-ClCBIQkT.jpg +0 -0
- package/dist/browser/assets/activity-timeline-BdRnSGAp.js +2 -0
- package/dist/browser/assets/changelog-CNUFmKj-.js +1 -0
- package/dist/browser/assets/commit-BWyvKMHI.js +4 -0
- package/dist/browser/assets/contributors-Bk_xjPNJ.js +1 -0
- package/dist/browser/assets/{contributors._email-CEcZZfAR.js → contributors._email-BPZ6AqpX.js} +1 -1
- package/dist/browser/assets/{contributors.index-DNMBFxLb.js → contributors.index-Ca6OC-eu.js} +1 -1
- package/dist/browser/assets/dashboard.index-Cgm78J6S.js +1 -0
- package/dist/browser/assets/{document-odLLdugz.js → document-BbL374wf.js} +4 -4
- package/dist/browser/assets/{document-Cmx0e6kz.css → document-DXzNxu17.css} +1 -1
- package/dist/browser/assets/document-Dtyl4_It.js +2 -0
- package/dist/browser/assets/feature-requirements-wfH5PlkX.jpg +0 -0
- package/dist/browser/assets/features-B1FsIXwk.js +2 -0
- package/dist/browser/assets/{features._featureId-Cmg8-2ku.js → features._featureId-CQYDdSK2.js} +1 -1
- package/dist/browser/assets/{features.index-CBz7BmRW.js → features.index-BcCdHpgS.js} +1 -1
- package/dist/browser/assets/getting-started-CCqN7NFk.js +1 -0
- package/dist/browser/assets/git-DCEKgdx_.js +1 -0
- package/dist/browser/assets/index-Bnx5f4X5.js +49 -0
- package/dist/browser/assets/{load-more-BVsXjzHC.js → load-more-COb87OhG.js} +1 -1
- package/dist/browser/assets/page-header-Cs2fqdqC.js +246 -0
- package/dist/browser/assets/{records._recordId-DF-NkdBL.js → records._recordId-CfPnm30x.js} +1 -1
- package/dist/browser/assets/{records.commits._commit-BBf_rxHJ.js → records.commits._commit-C-jisbh2.js} +1 -1
- package/dist/browser/assets/{records.docs._docId-Diev5opj.js → records.docs._docId-D1pQYz_I.js} +1 -1
- package/dist/browser/assets/{records.index-DPWv9blV.js → records.index-FJMKSXN0.js} +1 -1
- package/dist/browser/assets/{records.working-D5xv-dTD.js → records.working-cSfNWSM7.js} +1 -1
- package/dist/browser/assets/{settings-N1hE7l-i.js → settings-DDEler3s.js} +1 -1
- package/dist/browser/assets/useInfiniteQuery-IoAmrFi4.js +1 -0
- package/dist/browser/assets/{useKeyboardHint-CGJ2GVT3.js → useKeyboardHint-Wwnf-tpi.js} +1 -1
- package/dist/browser/index.html +18 -24
- package/dist/i18n/en/block.md +7 -7
- package/dist/i18n/en/changelog.md +20 -0
- package/dist/i18n/en/docs/commit.md +2 -2
- package/dist/i18n/en/docs/design.md +3 -3
- package/dist/i18n/en/docs/migrate.md +32 -35
- package/dist/i18n/en/docs/records.md +2 -2
- package/dist/i18n/en/docs/spec.md +1 -1
- package/dist/i18n/en/docs/workflow.md +12 -12
- package/dist/i18n/en/docs/writing.md +4 -4
- package/dist/i18n/ko/block.md +7 -7
- package/dist/i18n/ko/changelog.md +20 -0
- package/dist/i18n/ko/docs/commit.md +2 -2
- package/dist/i18n/ko/docs/design.md +3 -3
- package/dist/i18n/ko/docs/migrate.md +31 -34
- package/dist/i18n/ko/docs/records.md +2 -2
- package/dist/i18n/ko/docs/spec.md +1 -1
- package/dist/i18n/ko/docs/workflow.md +12 -12
- package/dist/i18n/ko/docs/writing.md +4 -4
- package/dist/launcher/cli.mjs +77 -0
- package/dist/main.js +281 -589
- package/package.json +1 -1
- package/dist/browser/assets/MetadataListItem-BEwPg27H.js +0 -1
- package/dist/browser/assets/about-C3ewDfU2.js +0 -3
- package/dist/browser/assets/activity-CiuGYDQ8.jpg +0 -0
- package/dist/browser/assets/activity-timeline-B3s0viEt.js +0 -2
- package/dist/browser/assets/changelog-DkRd6I8J.js +0 -1
- package/dist/browser/assets/commit-BHwKZ7hK.js +0 -4
- package/dist/browser/assets/contributor-2mkEa2Wo.css +0 -1
- package/dist/browser/assets/contributor-CqqvzxLh.js +0 -1
- package/dist/browser/assets/contributors-CuMPZx6_.js +0 -1
- package/dist/browser/assets/dashboard.index-nV7KwM5H.js +0 -1
- package/dist/browser/assets/document-BnxE7Txb.js +0 -2
- package/dist/browser/assets/feature-requirements-CA8f9Bcf.jpg +0 -0
- package/dist/browser/assets/features-C0YzZiS-.js +0 -2
- package/dist/browser/assets/getting-started-CaOhGSBe.js +0 -1
- package/dist/browser/assets/git-DwAnKiiN.js +0 -1
- package/dist/browser/assets/index-BljzO9go.js +0 -49
- package/dist/browser/assets/instructions-2OUMP-vh.css +0 -1
- package/dist/browser/assets/instructions-DWS_nwe0.js +0 -1
- package/dist/browser/assets/instructions._instructionId-l7aWWvfx.js +0 -1
- package/dist/browser/assets/instructions.agents-t7hMe4Pv.js +0 -1
- package/dist/browser/assets/instructions.index-CHVCQBSH.js +0 -1
- package/dist/browser/assets/lazyRouteComponent-BZI8yQj_.js +0 -1
- package/dist/browser/assets/page-header-CRcXie4p.js +0 -248
- package/dist/browser/assets/project-instructions-DsWrw-nY.jpg +0 -0
- package/dist/browser/assets/useInfiniteQuery-CrEm5UW2.js +0 -1
- package/dist/i18n/en/docs/instructions.md +0 -94
- package/dist/i18n/ko/docs/instructions.md +0 -94
package/dist/main.js
CHANGED
|
@@ -3381,7 +3381,7 @@ var program = new Command();
|
|
|
3381
3381
|
import { createServer } from "node:http";
|
|
3382
3382
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
3383
3383
|
import { fileURLToPath } from "node:url";
|
|
3384
|
-
import { readFile as
|
|
3384
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
3385
3385
|
|
|
3386
3386
|
// ../../packages/core/dist/domain/repository-status.js
|
|
3387
3387
|
function summarizeChanges(changes2) {
|
|
@@ -3510,9 +3510,8 @@ var messages_default = {
|
|
|
3510
3510
|
"doc.DESIGN_OVERVIEW_REQUIRED": "\uC124\uACC4\uAC00 \uC788\uB294 \uAE30\uB2A5\uC5D0\uB294 design/overview.md\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4: {feature}",
|
|
3511
3511
|
"doc.FILE_TOO_LARGE": "\uBB38\uC11C \uD30C\uC77C\uC774 1MB\uB97C \uB118\uC5B4 \uC77D\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4: {path}",
|
|
3512
3512
|
"doc.DOC_DRAFT": "new \uBA85\uB839\uC774 \uB9CC\uB4E0 \uCD08\uC548 \uD45C\uC2DC\uAC00 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4. \uBCF8\uBB38\uC744 \uB2E4 \uC4F4 \uB4A4 draft: true \uC904\uC744 \uC9C0\uC6B0\uC138\uC694: {path}",
|
|
3513
|
-
"doc.
|
|
3514
|
-
"doc.WIKI_REMOVED": "\uC704\uD0A4\uB294 0.8.0\uC5D0\uC11C \
|
|
3515
|
-
"doc.INSTRUCTION_SPEC_LINK": "\uC9C0\uCE68\uC740 \uBA85\uC138\uB97C \uAC00\uB9AC\uD0A4\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC124\uACC4\uAC00 sources\uB85C \uC9C0\uCE68\uC744 \uAC00\uB9AC\uD0B5\uB2C8\uB2E4: {path}: {link}",
|
|
3513
|
+
"doc.INSTRUCTION_MOVED": "0.9.0\uBD80\uD130 Gitifact\uB294 \uD504\uB85C\uC81D\uD2B8 \uC9C0\uCE68\uC744 \uAD00\uB9AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC774 \uC9C0\uCE68\uC744 \uC4F0\uB294 \uC5D0\uC774\uC804\uD2B8\uC758 \uC2A4\uD0AC \uD3F4\uB354\uB85C \uC62E\uAE30\uC138\uC694(gitifact guide show migrate): {path}",
|
|
3514
|
+
"doc.WIKI_REMOVED": "\uC704\uD0A4\uB294 0.8.0\uC5D0\uC11C \uC5C6\uC5B4\uC84C\uC2B5\uB2C8\uB2E4. \uC774 \uD398\uC774\uC9C0\uB97C \uC5D0\uC774\uC804\uD2B8\uC758 \uC2A4\uD0AC \uD3F4\uB354\uB098 \uB2E4\uB978 \uBB38\uC11C\uB85C \uC62E\uAE30\uC138\uC694(gitifact guide show migrate): {path}",
|
|
3516
3515
|
"warn.MISSING_LINK_TARGET": "\uB9C1\uD06C \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4: {path}: {link}",
|
|
3517
3516
|
"warn.ASSET_SIZE": "\uC5D0\uC14B\uC774 \uAD8C\uC7A5 \uD06C\uAE30(1MB)\uB97C \uB118\uC2B5\uB2C8\uB2E4: {path} ({bytes}\uBC14\uC774\uD2B8)",
|
|
3518
3517
|
"warn.ASSET_EXTENSION": "\uBE0C\uB77C\uC6B0\uC800\uAC00 \uBBF8\uB9AC \uBCF4\uC5EC \uC8FC\uC9C0 \uC54A\uB294 \uD655\uC7A5\uC790\uB77C \uB0B4\uB824\uBC1B\uAE30\uB85C\uB9CC \uC5F4\uB9BD\uB2C8\uB2E4: {path}",
|
|
@@ -3636,9 +3635,8 @@ var messages_default2 = {
|
|
|
3636
3635
|
"doc.DESIGN_OVERVIEW_REQUIRED": "A feature with a design needs design/overview.md: {feature}",
|
|
3637
3636
|
"doc.FILE_TOO_LARGE": "The document file exceeds 1 MB and was not read: {path}",
|
|
3638
3637
|
"doc.DOC_DRAFT": "The draft mark a new command added is still there. Remove the draft: true line once the body is written: {path}",
|
|
3639
|
-
"doc.
|
|
3640
|
-
"doc.WIKI_REMOVED": "The wiki
|
|
3641
|
-
"doc.INSTRUCTION_SPEC_LINK": "An instruction does not point at specs; designs name the instructions they follow in sources: {path}: {link}",
|
|
3638
|
+
"doc.INSTRUCTION_MOVED": "Gitifact no longer keeps project instructions from 0.9.0. Move this instruction to the skills folder of the agent you use (gitifact guide show migrate): {path}",
|
|
3639
|
+
"doc.WIKI_REMOVED": "The wiki went in 0.8.0. Move this page to the agent's skills folder or another document (gitifact guide show migrate): {path}",
|
|
3642
3640
|
"warn.MISSING_LINK_TARGET": "The link target does not exist: {path}: {link}",
|
|
3643
3641
|
"warn.ASSET_SIZE": "The asset is over the recommended size (1 MB): {path} ({bytes} bytes)",
|
|
3644
3642
|
"warn.ASSET_EXTENSION": "The browser does not preview this extension and offers it only as a download: {path}",
|
|
@@ -3852,9 +3850,9 @@ function extractLinks(body2) {
|
|
|
3852
3850
|
fence = void 0;
|
|
3853
3851
|
continue;
|
|
3854
3852
|
}
|
|
3855
|
-
const
|
|
3856
|
-
if (
|
|
3857
|
-
fence = { char:
|
|
3853
|
+
const open5 = /^ {0,3}(`{3,}|~{3,})/.exec(line2);
|
|
3854
|
+
if (open5) {
|
|
3855
|
+
fence = { char: open5[1][0], size: open5[1].length };
|
|
3858
3856
|
continue;
|
|
3859
3857
|
}
|
|
3860
3858
|
for (const m of line2.replace(/`[^`]*`/g, "").matchAll(/!?\[[^\]]*\]\((?:<([^>]+)>|([^)\s]+))(?:\s+"[^"]*")?\)/g))
|
|
@@ -4002,9 +4000,9 @@ function parseDesign(source2, specId) {
|
|
|
4002
4000
|
fence = void 0;
|
|
4003
4001
|
return line2;
|
|
4004
4002
|
}
|
|
4005
|
-
const
|
|
4006
|
-
if (
|
|
4007
|
-
fence = { char:
|
|
4003
|
+
const open5 = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line2);
|
|
4004
|
+
if (open5) {
|
|
4005
|
+
fence = { char: open5[1][0], size: open5[1].length };
|
|
4008
4006
|
return line2;
|
|
4009
4007
|
}
|
|
4010
4008
|
if (/^#\s/.test(line2))
|
|
@@ -4047,9 +4045,9 @@ function parseDocument(path3, source2) {
|
|
|
4047
4045
|
fence = void 0;
|
|
4048
4046
|
continue;
|
|
4049
4047
|
}
|
|
4050
|
-
const
|
|
4051
|
-
if (
|
|
4052
|
-
fence = { char:
|
|
4048
|
+
const open5 = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line2);
|
|
4049
|
+
if (open5) {
|
|
4050
|
+
fence = { char: open5[1][0], size: open5[1].length };
|
|
4053
4051
|
continue;
|
|
4054
4052
|
}
|
|
4055
4053
|
if (/^#\s/.test(line2))
|
|
@@ -4459,14 +4457,14 @@ function sections(raw, path3) {
|
|
|
4459
4457
|
found.at(-1)?.lines.push(line2);
|
|
4460
4458
|
continue;
|
|
4461
4459
|
}
|
|
4462
|
-
const
|
|
4463
|
-
if (
|
|
4464
|
-
fence = { char:
|
|
4460
|
+
const open5 = /^ {0,3}(`{3,}|~{3,})/.exec(line2);
|
|
4461
|
+
if (open5)
|
|
4462
|
+
fence = { char: open5[1][0], size: open5[1].length };
|
|
4465
4463
|
else if (/^#\s/.test(line2))
|
|
4466
4464
|
throw new DocumentError("BODY_HEADING", path3, t("doc.BODY_HEADING", { path: path3 }));
|
|
4467
4465
|
else if (/<!-- gitifact-/.test(line2))
|
|
4468
4466
|
throw new DocumentError("BODY_MARKER", path3, t("doc.BODY_MARKER", { path: path3 }));
|
|
4469
|
-
const heading = !
|
|
4467
|
+
const heading = !open5 && /^##\s+(.+?)\s*#*\s*$/.exec(line2);
|
|
4470
4468
|
if (heading) {
|
|
4471
4469
|
const key = sectionKeyOf(heading[1]);
|
|
4472
4470
|
if (!key || found.some((s) => s.key === key))
|
|
@@ -4550,6 +4548,8 @@ var HISTORY_PATH = ".gitifact/history.jsonl";
|
|
|
4550
4548
|
var name = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
4551
4549
|
var rootUpperName2 = /^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*\.md$/;
|
|
4552
4550
|
var isWikiPage = (path3) => path3.startsWith(WIKI_ROOT + "/") && path3.endsWith(".md");
|
|
4551
|
+
var isInstructionPath = (path3) => path3.startsWith(INSTRUCTIONS_ROOT + "/");
|
|
4552
|
+
var instructionFolderOf = (path3) => /^\.gitifact\/instructions\/[^/]+/.exec(path3)?.[0];
|
|
4553
4553
|
function classifyDocPath(path3) {
|
|
4554
4554
|
const unsupported = () => new DocumentError("PATH_UNSUPPORTED", path3, t("doc.PATH_UNSUPPORTED", { path: path3 }));
|
|
4555
4555
|
if (path3 === HISTORY_PATH)
|
|
@@ -4650,9 +4650,9 @@ function body(raw, path3) {
|
|
|
4650
4650
|
fence = void 0;
|
|
4651
4651
|
continue;
|
|
4652
4652
|
}
|
|
4653
|
-
const
|
|
4654
|
-
if (
|
|
4655
|
-
fence = { char:
|
|
4653
|
+
const open5 = /^ {0,3}(`{3,}|~{3,})/.exec(line2);
|
|
4654
|
+
if (open5) {
|
|
4655
|
+
fence = { char: open5[1][0], size: open5[1].length };
|
|
4656
4656
|
continue;
|
|
4657
4657
|
}
|
|
4658
4658
|
if (/^#\s/.test(line2))
|
|
@@ -4716,19 +4716,6 @@ function parseDocumentFile(path3, source2) {
|
|
|
4716
4716
|
}
|
|
4717
4717
|
return { kind: "design", feature: where.feature, order: order(), requirements: refs?.type === "list" ? refs.items : [], sources: sources(fields2, path3), ...common };
|
|
4718
4718
|
}
|
|
4719
|
-
var isInstructionReference = (path3) => path3.endsWith(".md");
|
|
4720
|
-
function parseInstructionFile(path3, source2) {
|
|
4721
|
-
if (source2.includes("\0") || /\r(?!\n)/.test(source2) || source2.charCodeAt(0) === 65279)
|
|
4722
|
-
throw new DocumentError("INVALID_CHARACTERS", path3, t("doc.INVALID_CHARACTERS", { path: path3 }));
|
|
4723
|
-
const { fields: fields2 } = parseFrontmatterBlock(source2.replace(/\r\n/g, "\n"), path3);
|
|
4724
|
-
for (const key of fields2.keys())
|
|
4725
|
-
if (key !== "title" && key !== "description")
|
|
4726
|
-
throw new DocumentError("FRONTMATTER_UNKNOWN_KEY", path3, t("doc.FRONTMATTER_UNKNOWN_KEY", { path: path3, key }));
|
|
4727
|
-
for (const key of ["title", "description"])
|
|
4728
|
-
if (!fields2.has(key))
|
|
4729
|
-
throw new DocumentError("FRONTMATTER_MISSING_KEY", path3, t("doc.FRONTMATTER_MISSING_KEY", { path: path3, key }));
|
|
4730
|
-
return { title: text(fields2, "title", path3, 200), description: text(fields2, "description", path3, 300) };
|
|
4731
|
-
}
|
|
4732
4719
|
function renderDocumentFile(doc) {
|
|
4733
4720
|
const front = renderFrontmatterBlock([
|
|
4734
4721
|
["id", doc.id],
|
|
@@ -4773,17 +4760,18 @@ function checkDocuments(files) {
|
|
|
4773
4760
|
const report = (code, path3, values = {}) => problems.push(docProblem(code, path3, values));
|
|
4774
4761
|
const features = /* @__PURE__ */ new Set();
|
|
4775
4762
|
const designFolders = /* @__PURE__ */ new Map();
|
|
4776
|
-
const instructionFolders = /* @__PURE__ */ new
|
|
4777
|
-
const specLinks = (path3, body2) => {
|
|
4778
|
-
for (const link3 of extractLinks(body2))
|
|
4779
|
-
if (resolveLink(path3, link3)?.startsWith(SPEC_ROOT + "/"))
|
|
4780
|
-
report("INSTRUCTION_SPEC_LINK", path3, { link: link3 });
|
|
4781
|
-
};
|
|
4763
|
+
const instructionFolders = /* @__PURE__ */ new Set();
|
|
4782
4764
|
for (const [path3, source2] of [...files].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
|
|
4783
4765
|
if (isWikiPage(path3)) {
|
|
4784
4766
|
report("WIKI_REMOVED", path3);
|
|
4785
4767
|
continue;
|
|
4786
4768
|
}
|
|
4769
|
+
if (isInstructionPath(path3)) {
|
|
4770
|
+
const folder = instructionFolderOf(path3);
|
|
4771
|
+
if (folder)
|
|
4772
|
+
instructionFolders.add(folder);
|
|
4773
|
+
continue;
|
|
4774
|
+
}
|
|
4787
4775
|
try {
|
|
4788
4776
|
const where = classifyDocPath(path3);
|
|
4789
4777
|
if (where.type === "ignored")
|
|
@@ -4796,16 +4784,8 @@ function checkDocuments(files) {
|
|
|
4796
4784
|
records2.push(parseRecordFile(path3, source2));
|
|
4797
4785
|
continue;
|
|
4798
4786
|
}
|
|
4799
|
-
if (where.type
|
|
4800
|
-
instructionFolders.set(where.name, instructionFolders.get(where.name) === true);
|
|
4801
|
-
if (isInstructionReference(path3)) {
|
|
4802
|
-
specLinks(path3, source2);
|
|
4803
|
-
parseInstructionFile(path3, source2);
|
|
4804
|
-
}
|
|
4787
|
+
if (where.type !== "doc")
|
|
4805
4788
|
continue;
|
|
4806
|
-
}
|
|
4807
|
-
if (where.kind === "instruction")
|
|
4808
|
-
instructionFolders.set(where.name, true);
|
|
4809
4789
|
if (where.kind === "requirement" || where.kind === "design")
|
|
4810
4790
|
features.add(where.feature);
|
|
4811
4791
|
if (where.kind === "design")
|
|
@@ -4821,9 +4801,6 @@ function checkDocuments(files) {
|
|
|
4821
4801
|
for (const doc of documents)
|
|
4822
4802
|
if (doc.draft)
|
|
4823
4803
|
report("DOC_DRAFT", doc.path);
|
|
4824
|
-
for (const doc of documents)
|
|
4825
|
-
if (doc.kind === "instruction")
|
|
4826
|
-
specLinks(doc.path, doc.body);
|
|
4827
4804
|
for (const doc of documents) {
|
|
4828
4805
|
const seen = byId.get(doc.id);
|
|
4829
4806
|
if (seen)
|
|
@@ -4871,9 +4848,8 @@ function checkDocuments(files) {
|
|
|
4871
4848
|
for (const [feature2, overview] of designFolders)
|
|
4872
4849
|
if (!overview)
|
|
4873
4850
|
report("DESIGN_OVERVIEW_REQUIRED", `.gitifact/spec/${feature2}/design/overview.md`, { feature: feature2 });
|
|
4874
|
-
for (const
|
|
4875
|
-
|
|
4876
|
-
report("INSTRUCTION_INDEX_REQUIRED", `${INSTRUCTIONS_ROOT}/${name2}/${INSTRUCTION_FILE}`);
|
|
4851
|
+
for (const folder of [...instructionFolders].sort())
|
|
4852
|
+
report("INSTRUCTION_MOVED", folder);
|
|
4877
4853
|
return { documents, records: records2, problems };
|
|
4878
4854
|
}
|
|
4879
4855
|
|
|
@@ -4889,12 +4865,11 @@ function arrangeDocuments(documents) {
|
|
|
4889
4865
|
return f;
|
|
4890
4866
|
};
|
|
4891
4867
|
const wiki = [];
|
|
4892
|
-
const instructions2 = [];
|
|
4893
4868
|
for (const doc of documents) {
|
|
4894
4869
|
if (doc.kind === "wiki")
|
|
4895
4870
|
wiki.push(doc);
|
|
4896
4871
|
else if (doc.kind === "instruction")
|
|
4897
|
-
|
|
4872
|
+
continue;
|
|
4898
4873
|
else if (doc.kind === "feature")
|
|
4899
4874
|
folder(doc.feature).index = doc;
|
|
4900
4875
|
else if (doc.kind === "requirement")
|
|
@@ -4911,7 +4886,7 @@ function arrangeDocuments(documents) {
|
|
|
4911
4886
|
}
|
|
4912
4887
|
features.push({ index: f.index, requirements: f.requirements.sort(byOrder), designs: f.designs.sort(byOrder) });
|
|
4913
4888
|
}
|
|
4914
|
-
return { features, wiki: wiki.sort(byPath),
|
|
4889
|
+
return { features, wiki: wiki.sort(byPath), orphans };
|
|
4915
4890
|
}
|
|
4916
4891
|
|
|
4917
4892
|
// ../../packages/core/dist/use-cases/compare-documents.js
|
|
@@ -4974,7 +4949,7 @@ function documentWarnings(documents, assets, existing) {
|
|
|
4974
4949
|
referenced.add(target);
|
|
4975
4950
|
continue;
|
|
4976
4951
|
}
|
|
4977
|
-
if (
|
|
4952
|
+
if (!target.startsWith(".gitifact/") && existing.has(target))
|
|
4978
4953
|
continue;
|
|
4979
4954
|
warnings.push(docWarning("MISSING_LINK_TARGET", from, { link: link3, target }));
|
|
4980
4955
|
}
|
|
@@ -25182,21 +25157,6 @@ var feature = external_exports.strictObject({
|
|
|
25182
25157
|
contributors: external_exports.array(contributor),
|
|
25183
25158
|
updatedAt: external_exports.string().nullable()
|
|
25184
25159
|
});
|
|
25185
|
-
var instructionFile = external_exports.strictObject({ path: external_exports.string(), size: external_exports.number().int().nonnegative(), title: external_exports.string().optional(), description: external_exports.string().optional() });
|
|
25186
|
-
var instruction = external_exports.strictObject({
|
|
25187
|
-
id: external_exports.string(),
|
|
25188
|
-
name: external_exports.string(),
|
|
25189
|
-
path: external_exports.string(),
|
|
25190
|
-
title: external_exports.string(),
|
|
25191
|
-
description: external_exports.string(),
|
|
25192
|
-
body: external_exports.string(),
|
|
25193
|
-
...standing,
|
|
25194
|
-
// Paths relative to the instruction folder, index.md left out; `limited` when the folder holds more than the list carries.
|
|
25195
|
-
files: external_exports.array(instructionFile),
|
|
25196
|
-
filesLimited: external_exports.boolean(),
|
|
25197
|
-
updatedAt: external_exports.string().nullable()
|
|
25198
|
-
});
|
|
25199
|
-
var agents = external_exports.strictObject({ path: external_exports.string(), body: external_exports.string(), updatedAt: external_exports.string().nullable() });
|
|
25200
25160
|
var problem = external_exports.strictObject({ code: external_exports.string(), path: external_exports.string(), message: external_exports.string() });
|
|
25201
25161
|
var oid2 = external_exports.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/);
|
|
25202
25162
|
var indexFeature = external_exports.strictObject({
|
|
@@ -25207,17 +25167,16 @@ var indexFeature = external_exports.strictObject({
|
|
|
25207
25167
|
requirements: external_exports.array(external_exports.strictObject({ id: external_exports.string(), path: external_exports.string(), title: external_exports.string(), description: external_exports.string() })),
|
|
25208
25168
|
designs: external_exports.array(external_exports.strictObject({ id: external_exports.string(), path: external_exports.string(), title: external_exports.string() }))
|
|
25209
25169
|
});
|
|
25210
|
-
var
|
|
25211
|
-
var browserCheckoutV1 = external_exports.strictObject({
|
|
25170
|
+
var browserCheckoutV2 = external_exports.strictObject({
|
|
25212
25171
|
contract: external_exports.literal("browser-checkout"),
|
|
25213
|
-
version: external_exports.literal(
|
|
25172
|
+
version: external_exports.literal(2),
|
|
25214
25173
|
sessionId: external_exports.string(),
|
|
25215
25174
|
head: oid2.nullable(),
|
|
25216
25175
|
observedAt: external_exports.string(),
|
|
25217
25176
|
working: external_exports.boolean(),
|
|
25218
25177
|
stamp: external_exports.string(),
|
|
25219
25178
|
problems: external_exports.array(problem),
|
|
25220
|
-
index: external_exports.strictObject({ features: external_exports.array(indexFeature),
|
|
25179
|
+
index: external_exports.strictObject({ features: external_exports.array(indexFeature), people: external_exports.array(external_exports.strictObject({ name: external_exports.string(), email: external_exports.string() })) })
|
|
25221
25180
|
});
|
|
25222
25181
|
var featureRow = external_exports.strictObject({
|
|
25223
25182
|
id: external_exports.string(),
|
|
@@ -25245,13 +25204,6 @@ var browserFeaturesV1 = external_exports.strictObject({
|
|
|
25245
25204
|
features: external_exports.array(featureRow)
|
|
25246
25205
|
});
|
|
25247
25206
|
var browserFeatureV2 = external_exports.strictObject({ contract: external_exports.literal("browser-feature"), version: external_exports.literal(2), sessionId: external_exports.string(), feature });
|
|
25248
|
-
var browserInstructionsV1 = external_exports.strictObject({
|
|
25249
|
-
contract: external_exports.literal("browser-instructions"),
|
|
25250
|
-
version: external_exports.literal(1),
|
|
25251
|
-
sessionId: external_exports.string(),
|
|
25252
|
-
instructions: external_exports.array(instruction),
|
|
25253
|
-
agents: agents.nullable()
|
|
25254
|
-
});
|
|
25255
25207
|
var browserContributorsV1 = external_exports.strictObject({
|
|
25256
25208
|
contract: external_exports.literal("browser-contributors"),
|
|
25257
25209
|
version: external_exports.literal(1),
|
|
@@ -25334,20 +25286,20 @@ var browserHistorySummaryV5 = external_exports.strictObject({
|
|
|
25334
25286
|
// The newest commits: a few of their changes each and how many there are in all.
|
|
25335
25287
|
recent: external_exports.array(external_exports.strictObject({ commit: oid2, count: external_exports.number().int().positive(), events: external_exports.array(event) }))
|
|
25336
25288
|
});
|
|
25337
|
-
var searchKind = external_exports.enum(["feature", "requirement", "design", "
|
|
25289
|
+
var searchKind = external_exports.enum(["feature", "requirement", "design", "record", "commit"]);
|
|
25338
25290
|
var searchHit = external_exports.strictObject({
|
|
25339
25291
|
id: external_exports.string(),
|
|
25340
25292
|
kind: searchKind,
|
|
25341
25293
|
title: external_exports.string(),
|
|
25342
25294
|
where: external_exports.string(),
|
|
25343
25295
|
line: external_exports.string(),
|
|
25344
|
-
// What the hit opens: a feature (with the requirement or design tab),
|
|
25296
|
+
// What the hit opens: a feature (with the requirement or design tab), a record, or a commit.
|
|
25345
25297
|
featureId: external_exports.string().optional(),
|
|
25346
25298
|
commit: oid2.optional()
|
|
25347
25299
|
});
|
|
25348
|
-
var
|
|
25300
|
+
var browserSearchV4 = external_exports.strictObject({
|
|
25349
25301
|
contract: external_exports.literal("browser-search"),
|
|
25350
|
-
version: external_exports.literal(
|
|
25302
|
+
version: external_exports.literal(4),
|
|
25351
25303
|
sessionId: external_exports.string(),
|
|
25352
25304
|
query: external_exports.string(),
|
|
25353
25305
|
groups: external_exports.array(external_exports.strictObject({ group: external_exports.union([searchKind, external_exports.literal("recent")]), total: external_exports.number().int().nonnegative(), next: external_exports.string().nullable(), hits: external_exports.array(searchHit) }))
|
|
@@ -25379,14 +25331,13 @@ var browserFeaturesQueryV1 = external_exports.strictObject({
|
|
|
25379
25331
|
var browserFeatureQueryV1 = external_exports.strictObject({ id: featureId });
|
|
25380
25332
|
var browserContributorsQueryV1 = external_exports.strictObject({ q: external_exports.string().max(200).optional(), after: external_exports.string().min(1).max(320).optional(), limit: count(50).pipe(external_exports.number().min(1)).optional() });
|
|
25381
25333
|
var browserContributorQueryV1 = external_exports.strictObject({ email: external_exports.string().min(1).max(320) });
|
|
25382
|
-
var
|
|
25334
|
+
var browserSearchQueryV3 = external_exports.strictObject({
|
|
25383
25335
|
q: external_exports.string().max(200),
|
|
25384
25336
|
head: headQuery.optional(),
|
|
25385
25337
|
group: searchKind.optional(),
|
|
25386
25338
|
after: external_exports.string().min(1).max(200).optional(),
|
|
25387
25339
|
limit: count(50).pipe(external_exports.number().min(1)).optional()
|
|
25388
25340
|
});
|
|
25389
|
-
var browserInstructionFileQueryV1 = external_exports.strictObject({ id: external_exports.string().regex(/^I-[a-z2-7]{10}$/), path: external_exports.string().min(1).max(1e3) });
|
|
25390
25341
|
var changelogQueryV1 = external_exports.strictObject({ lang: external_exports.string().regex(/^[a-z]{2}(?:-[A-Z]{2})?$/).optional() });
|
|
25391
25342
|
var fileStatus = external_exports.enum(["added", "modified", "deleted", "renamed"]);
|
|
25392
25343
|
var commitFile = external_exports.strictObject({
|
|
@@ -25475,17 +25426,6 @@ var browserDocumentHistoryQueryV1 = external_exports.strictObject({
|
|
|
25475
25426
|
after: oid2.optional(),
|
|
25476
25427
|
limit: count(50).pipe(external_exports.number().min(1)).optional()
|
|
25477
25428
|
});
|
|
25478
|
-
var browserInstructionFileV1 = external_exports.strictObject({
|
|
25479
|
-
contract: external_exports.literal("browser-instruction-file"),
|
|
25480
|
-
version: external_exports.literal(1),
|
|
25481
|
-
sessionId: external_exports.string(),
|
|
25482
|
-
id: external_exports.string(),
|
|
25483
|
-
path: external_exports.string(),
|
|
25484
|
-
text: external_exports.string().nullable(),
|
|
25485
|
-
size: external_exports.number().int().nonnegative(),
|
|
25486
|
-
binary: external_exports.boolean(),
|
|
25487
|
-
tooLarge: external_exports.boolean()
|
|
25488
|
-
});
|
|
25489
25429
|
var workingChange = external_exports.strictObject({ id: external_exports.string(), kind, title: external_exports.string(), path: external_exports.string(), previousPath: external_exports.string().optional(), types: external_exports.array(changeType) });
|
|
25490
25430
|
var pendingRecord = external_exports.strictObject({ id: external_exports.string(), title: external_exports.string(), docs: external_exports.array(external_exports.string()), sections: external_exports.array(recordSection), draft: external_exports.boolean() });
|
|
25491
25431
|
var browserWorkingV1 = external_exports.strictObject({
|
|
@@ -25586,7 +25526,8 @@ var updateV6 = external_exports.discriminatedUnion("ok", [
|
|
|
25586
25526
|
// refreshed: blocks whose text differed were rewritten. current: every block already matched. kept: the project is on a
|
|
25587
25527
|
// release newer than this CLI, so its blocks were left as they are.
|
|
25588
25528
|
// not-initialized: no .gitifact config here, so only the version check ran. no-block: no file carries a block.
|
|
25589
|
-
// missing: files `gitifact init` would add and update does not create
|
|
25529
|
+
// missing: files `gitifact init` would add and update does not create. Always empty since 0.9.0, when init stopped adding
|
|
25530
|
+
// a CLAUDE.md that imports AGENTS.md.
|
|
25590
25531
|
agentDocs: external_exports.strictObject({ state: external_exports.enum(["refreshed", "current", "kept", "not-initialized", "no-block"]), paths: external_exports.array(external_exports.string()), missing: external_exports.array(external_exports.string()) }),
|
|
25591
25532
|
// written: .gitifact/config.json now names this release as `cli` and the block language. current: it already did.
|
|
25592
25533
|
// cli is the project's release afterwards; one newer than cliVersion was kept, since an older CLI does not lower it.
|
|
@@ -25767,7 +25708,6 @@ var messages_default3 = {
|
|
|
25767
25708
|
"server.recordNotFound": "\uC774 \uC774\uB825\uC5D0 \uADF8 \uACB0\uC815\uAE30\uB85D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25768
25709
|
"server.documentNotFound": "\uC774 \uC774\uB825\uACFC \uC791\uC5C5 \uD3F4\uB354\uC5D0 \uADF8 \uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25769
25710
|
"server.commitFileNotFound": "\uADF8 \uCEE4\uBC0B\uC774 \uBC14\uAFBC \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
25770
|
-
"server.instructionFileNotFound": "\uC9C0\uCE68 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25771
25711
|
"server.specsUnreadable": "\uBA85\uC138\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
25772
25712
|
"server.refreshOrigin": "\uC0C8\uB85C\uACE0\uCE68\uC5D0\uB294 \uAC19\uC740 \uCD9C\uCC98\uC758 Origin\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
25773
25713
|
"server.fileNotFound": "\uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
@@ -25809,7 +25749,7 @@ var messages_default3 = {
|
|
|
25809
25749
|
"init.text.storage": "\uC800\uC7A5 \uADDC\uC57D",
|
|
25810
25750
|
"init.text.agentDocs": "\uC5D0\uC774\uC804\uD2B8 \uC9C0\uCE68",
|
|
25811
25751
|
"init.text.lineEndings": "\uC904\uBC14\uAFC8: {path}\uB85C \uBB38\uC11C\uB97C LF\uB85C \uACE0\uC815\uD588\uC2B5\uB2C8\uB2E4. \uC774\uBBF8 \uC788\uB358 \uBB38\uC11C\uAC00 \uBCC0\uACBD\uC73C\uB85C \uBCF4\uC774\uBA74 \uC904\uBC14\uAFC8\uB9CC \uBC14\uB010 \uAC83\uC774\uB2C8 \uADF8 \uBB38\uC11C\uB4E4\uC744 \uD55C \uBC88 \uCEE4\uBC0B\uD574 \uC815\uB9AC\uD558\uC138\uC694.",
|
|
25812
|
-
"init.text.updateAvailable": "\uC0C8 \uBC84\uC804 {version}\uC774 \uC788\uC2B5\uB2C8\uB2E4. {command}\uB85C \
|
|
25752
|
+
"init.text.updateAvailable": "\uC0C8 \uBC84\uC804 {version}\uC774 \uC788\uC2B5\uB2C8\uB2E4. {command}\uB85C \uD504\uB85C\uC81D\uD2B8\uB97C \uC0C8 \uBC84\uC804\uC5D0 \uB9DE\uCD94\uC138\uC694.",
|
|
25813
25753
|
"init.failed": "\uCD08\uAE30\uD654\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uD30C\uC77C \uC811\uADFC \uAD8C\uD55C\uACFC \uC0DD\uC131\uB41C \uC124\uC815\xB7\uC784\uC2DC \uD30C\uC77C\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
25814
25754
|
"config.storeNotDirectory": ".gitifact\uB294 \uB9C1\uD06C\uAC00 \uC544\uB2CC \uC77C\uBC18 \uB514\uB809\uD130\uB9AC\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
25815
25755
|
"config.fileShape": "config.json\uC740 64 KiB \uC774\uD558\uC758 \uC77C\uBC18 \uD30C\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
@@ -25844,14 +25784,13 @@ var messages_default3 = {
|
|
|
25844
25784
|
"update.text.upToDate": "\uCD5C\uC2E0 \uBC84\uC804\uC744 \uC0AC\uC6A9 \uC911\uC785\uB2C8\uB2E4.",
|
|
25845
25785
|
"update.text.disabled": "\uC0C8 \uBC84\uC804 \uD655\uC778\uC774 \uAEBC\uC838 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
25846
25786
|
"update.text.unavailable": "\uC0C8 \uBC84\uC804\uC744 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uB124\uD2B8\uC6CC\uD06C \uC5F0\uACB0\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
25847
|
-
"update.text.install": "\
|
|
25848
|
-
"update.text.afterInstall": "\
|
|
25787
|
+
"update.text.install": "\uC5C5\uB370\uC774\uD2B8 \uBA85\uB839: {command}",
|
|
25788
|
+
"update.text.afterInstall": "\uC774 \uBA85\uB839\uC774 \uC0C8 \uBC84\uC804\uC73C\uB85C \uD504\uB85C\uC81D\uD2B8 \uAE30\uC900\uACFC \uC9C0\uCE68 \uBE14\uB85D, \uC2E4\uD589\uAE30(.gitifact/bin/cli.mjs)\uB97C \uBC14\uAFC9\uB2C8\uB2E4. \uBE0C\uB77C\uC6B0\uC800\uB3C4 \uC0C8 \uBC84\uC804\uC73C\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
25849
25789
|
"update.text.blockRefreshed": "\uC9C0\uCE68 \uBE14\uB85D \uAC31\uC2E0: {paths}",
|
|
25850
25790
|
"update.text.blockCurrent": "\uC9C0\uCE68 \uBE14\uB85D\uC740 \uC774\uBBF8 \uD604\uC7AC \uBC84\uC804\uC785\uB2C8\uB2E4: {paths}",
|
|
25851
25791
|
"update.text.noBlock": "GITIFACT \uBE14\uB85D\uC774 \uC788\uB294 \uC9C0\uCE68 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. gitifact init\uC73C\uB85C \uC124\uCE58\uD558\uC138\uC694.",
|
|
25852
25792
|
"update.text.notInitialized": "\uCD08\uAE30\uD654\uB41C \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2C8\uC5B4\uC11C \uBC84\uC804\uB9CC \uD655\uC778\uD588\uC2B5\uB2C8\uB2E4.",
|
|
25853
|
-
"update.text.
|
|
25854
|
-
"update.text.migrationRequired": "\uC774 \uD504\uB85C\uC81D\uD2B8\uC758 \uBB38\uC11C\uB294 \uC544\uC9C1 0.7 \uC800\uC7A5 \uADDC\uC57D(schemaVersion 2)\uC785\uB2C8\uB2E4. \uC9C0\uCE68 \uBE14\uB85D\uC740 \uC0C8 \uBA85\uB839\uC744 \uC548\uB0B4\uD558\uC9C0\uB9CC \uC804\uD658 \uC804\uC5D0\uB294 specs\xB7instructions\xB7records\xB7check\xB7changes \uBA85\uB839\uC774 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. npx --yes gitifact@{version} guide show migrate\uC758 \uC808\uCC28\uB85C \uBB38\uC11C\uB97C \uC804\uD658\uD558\uC138\uC694.",
|
|
25793
|
+
"update.text.migrationRequired": "\uC774 \uD504\uB85C\uC81D\uD2B8\uC758 \uBB38\uC11C\uB294 \uC544\uC9C1 0.7 \uC800\uC7A5 \uADDC\uC57D(schemaVersion 2)\uC785\uB2C8\uB2E4. \uC9C0\uCE68 \uBE14\uB85D\uC740 \uC0C8 \uBA85\uB839\uC744 \uC548\uB0B4\uD558\uC9C0\uB9CC \uC804\uD658 \uC804\uC5D0\uB294 specs\xB7records\xB7check\xB7changes \uBA85\uB839\uC774 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. npx --yes gitifact@{version} guide show migrate\uC758 \uC808\uCC28\uB85C \uBB38\uC11C\uB97C \uC804\uD658\uD558\uC138\uC694.",
|
|
25855
25794
|
"update.text.committed": "\uC9C0\uCE68 \uBE14\uB85D \uCEE4\uBC0B: {commit} ({paths})",
|
|
25856
25795
|
"update.text.commitNothing": "\uCEE4\uBC0B\uD560 \uC9C0\uCE68 \uBE14\uB85D \uBCC0\uACBD\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25857
25796
|
"update.text.commitSkipped.untracked": "\uCEE4\uBC0B\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. Git\uC774 \uCD94\uC801\uD558\uC9C0 \uC54A\uB294 \uC9C0\uCE68 \uD30C\uC77C\uC785\uB2C8\uB2E4: {paths}",
|
|
@@ -25871,7 +25810,7 @@ var messages_default3 = {
|
|
|
25871
25810
|
"help.guide": "\uC5D0\uC774\uC804\uD2B8\uC6A9 \uC791\uC131 \uC9C0\uCE68",
|
|
25872
25811
|
"help.guideList": "\uC9C0\uCE68 \uBAA9\uB85D (\uC81C\uBAA9\uACFC \uC124\uBA85)",
|
|
25873
25812
|
"help.guideShow": "\uC9C0\uCE68 \uD558\uB098\uB97C \uCD9C\uB825",
|
|
25874
|
-
"help.guideTopic": "workflow, spec, design,
|
|
25813
|
+
"help.guideTopic": "workflow, spec, design, records, writing, commit, migrate \uC911 \uD558\uB098",
|
|
25875
25814
|
"command.failed": "\uBA85\uB839\uC744 \uC2E4\uD589\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
25876
25815
|
"project.notInitialized": "\uBA3C\uC800 gitifact init\uC73C\uB85C \uCD08\uAE30\uD654\uD558\uC138\uC694.",
|
|
25877
25816
|
"input.file": "\uC785\uB825\uC740 1 MiB \uC774\uD558\uC758 JSON \uD30C\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
@@ -25893,17 +25832,14 @@ var messages_default3 = {
|
|
|
25893
25832
|
"docs.unknownDocument": "\uBB38\uC11C\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: {ids}",
|
|
25894
25833
|
"docs.references": "\uCC38\uC870",
|
|
25895
25834
|
"docs.referencedBy": "\uAC00\uB9AC\uD0A4\uB294 \uBB38\uC11C",
|
|
25896
|
-
"docs.files": "\uD30C\uC77C",
|
|
25897
25835
|
"docs.invalidPath": "{kind} \uBB38\uC11C\uC758 \uACBD\uB85C\uAC00 \uC544\uB2D9\uB2C8\uB2E4: {path}. \uC608: {example}",
|
|
25898
25836
|
"docs.pathExample.feature": "payment (.gitifact/spec/payment/index.md)",
|
|
25899
25837
|
"docs.pathExample.requirement": "payment/cancel (.gitifact/spec/payment/requirements/cancel.md)",
|
|
25900
25838
|
"docs.pathExample.design": "payment/api (.gitifact/spec/payment/design/api.md)",
|
|
25901
|
-
"docs.pathExample.instruction": "cli-architecture (.gitifact/instructions/cli-architecture/index.md)",
|
|
25902
25839
|
"docs.skeleton.feature": "(\uC774 \uAE30\uB2A5\uC774 \uBB34\uC5C7\uC774\uACE0 \uC5B4\uB514\uAE4C\uC9C0\uC778\uC9C0)",
|
|
25903
25840
|
"docs.skeleton.requirement": "(\uC0AC\uC6A9\uC790)\uB85C\uC11C, (\uBAA9\uC801)\uC744 \uC704\uD574 (\uB3D9\uC791)\uC744 \uD558\uACE0 \uC2F6\uB2E4.\n\n### \uBC94\uC704\uC640 \uC81C\uC57D\n\n- (\uCC38\xB7\uAC70\uC9D3\uC744 \uAC00\uB9B4 \uC218 \uC788\uB294 \uADDC\uCE59 \uD55C \uBB38\uC7A5. \uC5C6\uC73C\uBA74 \uC774 \uC808\uC744 \uC9C0\uC6B4\uB2E4)\n\n### \uC218\uC6A9 \uC870\uAC74\n\n1. \uC870\uAC74: (\uC0C1\uD669)\n \uAE30\uB300 \uB3D9\uC791: (\uACB0\uACFC)",
|
|
25904
25841
|
"docs.skeleton.requirementUsecase": "(\uC0AC\uC6A9\uC790)\uB85C\uC11C, (\uBAA9\uC801)\uC744 \uC704\uD574 (\uB3D9\uC791)\uC744 \uD558\uACE0 \uC2F6\uB2E4.\n\n### \uBC94\uC704\uC640 \uC81C\uC57D\n\n- (\uCC38\xB7\uAC70\uC9D3\uC744 \uAC00\uB9B4 \uC218 \uC788\uB294 \uADDC\uCE59 \uD55C \uBB38\uC7A5. \uC5C6\uC73C\uBA74 \uC774 \uC808\uC744 \uC9C0\uC6B4\uB2E4)\n\n### \uC0AC\uC804 \uC870\uAC74\n\n- (\uC2DC\uC791 \uC804\uC5D0 \uCC38\uC774\uC5B4\uC57C \uD558\uB294 \uAC83. \uC5C6\uC73C\uBA74 \uC774 \uC808\uC744 \uC9C0\uC6B4\uB2E4)\n\n### \uAE30\uBCF8 \uD750\uB984\n\n1. (\uD589\uC704\uC790)\uAC00 (\uB3D9\uC791)\uD55C\uB2E4.\n2. (\uC2DC\uC2A4\uD15C)\uC774 (\uACB0\uACFC)\uB97C \uBCF4\uC778\uB2E4.\n\n### \uB300\uCCB4 \uD750\uB984\n\n- **A1. (\uAC08\uB77C\uC9C0\uB294 \uC0C1\uD669)** (1\uB2E8\uACC4\uC5D0\uC11C)\n 1. (\uADF8\uB54C\uC758 \uB3D9\uC791)\n\n### \uC0AC\uD6C4 \uC870\uAC74\n\n- (\uB05D\uB09C \uB4A4 \uCC38\uC778 \uAC83. \uC5C6\uC73C\uBA74 \uC774 \uC808\uC744 \uC9C0\uC6B4\uB2E4)\n\n### \uC218\uC6A9 \uC870\uAC74\n\n1. \uACBD\uB85C: \uAE30\uBCF8 \uD750\uB984\n \uC870\uAC74: (\uC0C1\uD669)\n \uAE30\uB300 \uB3D9\uC791: (\uACB0\uACFC)\n2. \uACBD\uB85C: \uAE30\uBCF8 \uD750\uB984, A1\n \uC870\uAC74: (\uC0C1\uD669)\n \uAE30\uB300 \uB3D9\uC791: (\uACB0\uACFC)",
|
|
25905
25842
|
"docs.skeleton.design": "(\uC774 \uC124\uACC4\uAC00 \uB2E4\uB8E8\uB294 \uAD6C\uC870\uC640 \uCC98\uB9AC \uBC29\uC2DD)",
|
|
25906
|
-
"docs.skeleton.instruction": "(\uC774 \uC791\uC5C5\uC744 \uD560 \uB54C \uC9C0\uD0AC \uADDC\uCE59\uACFC \uC808\uCC28. \uC790\uC138\uD55C \uB0B4\uC6A9\uC740 references/ \uC544\uB798 \uD30C\uC77C\uB85C \uB098\uB204\uACE0 \uC5EC\uAE30\uC11C \uB9C1\uD06C\uD55C\uB2E4)",
|
|
25907
25843
|
"docs.exists": "\uC774\uBBF8 \uC788\uB294 \uD30C\uC77C\uC785\uB2C8\uB2E4: {path}",
|
|
25908
25844
|
"docs.notFolder": "\uD3F4\uB354 \uC790\uB9AC\uC5D0 \uC77C\uBC18 \uD3F4\uB354\uAC00 \uC544\uB2CC \uAC83\uC774 \uC788\uC2B5\uB2C8\uB2E4: {path}",
|
|
25909
25845
|
"docs.created": "\uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4: {path} ({id})",
|
|
@@ -25920,6 +25856,7 @@ var messages_default3 = {
|
|
|
25920
25856
|
"changes.committed": "\uCEE4\uBC0B\uD588\uC2B5\uB2C8\uB2E4: {commit} {message}",
|
|
25921
25857
|
"changes.dryRun": "\uBBF8\uB9AC\uBCF4\uAE30: \uD30C\uC77C\uC744 \uC4F0\uAC70\uB098 \uCEE4\uBC0B\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.",
|
|
25922
25858
|
"changes.summary": "\uD30C\uC77C {paths}\uAC1C, \uBC14\uB010 \uBB38\uC11C {changes}\uAC1C, \uACB0\uC815\uAE30\uB85D {records}\uAC1C",
|
|
25859
|
+
"commit.tooManyStorePaths": "\uC774 \uCEE4\uBC0B\uC5D0 .gitifact \uC544\uB798 \uACBD\uB85C\uAC00 {count}\uAC1C\uC785\uB2C8\uB2E4. \uBB38\uC11C\xB7\uACB0\uC815\uAE30\uB85D\xB7\uC5D0\uC14B\uC740 \uD55C \uCEE4\uBC0B\uC5D0 {limit}\uAC1C\uAE4C\uC9C0 \uB2F4\uC2B5\uB2C8\uB2E4. \uACB0\uC815 \uB2E8\uC704\uB85C \uB098\uB220 \uCEE4\uBC0B\uD558\uC138\uC694(\uCF54\uB4DC \uACBD\uB85C\uB294 \uC774 \uD55C\uB3C4\uC5D0 \uB4E4\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4).",
|
|
25923
25860
|
"commit.migrationFlag": "migration\uC740 true\uC774\uAC70\uB098 \uC5C6\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
25924
25861
|
"commit.checkFailed": "\uBB38\uC11C \uAC80\uC0AC\uC5D0\uC11C \uBB38\uC81C {count}\uAC1C\uAC00 \uB098\uC640 \uCEE4\uBC0B\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.",
|
|
25925
25862
|
"commit.unknownDocument": "\uACB0\uC815\uAE30\uB85D\uC774 \uAC00\uB9AC\uD0A4\uB294 \uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4: {ids}",
|
|
@@ -25935,7 +25872,8 @@ var messages_default3 = {
|
|
|
25935
25872
|
"changes.recordAltered": "\uCEE4\uBC0B\uB41C \uACB0\uC815\uAE30\uB85D\uC774 \uBC14\uB00C\uAC70\uB098 \uC9C0\uC6CC\uC9D0(\uCEE4\uBC0B\uC774 \uAC70\uBD80\uB428): {paths}",
|
|
25936
25873
|
"commit.recordAltered": "\uC774\uBBF8 \uCEE4\uBC0B\uB41C \uACB0\uC815\uAE30\uB85D\uC740 \uACE0\uCE58\uAC70\uB098 \uC9C0\uC6B8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: {paths}. HEAD\uB300\uB85C \uB418\uB3CC\uB9AC\uACE0, \uBC14\uB010 \uACB0\uC815\uC740 \uC0C8 \uAE30\uB85D(records new)\uC73C\uB85C \uC4F0\uC138\uC694.",
|
|
25937
25874
|
"commit.selectMove": "\uC62E\uAE34 \uBB38\uC11C\uB294 \uC61B \uACBD\uB85C\uC640 \uC0C8 \uACBD\uB85C\uB97C \uD568\uAED8 \uC120\uD0DD\uD558\uC138\uC694: {ids}",
|
|
25938
|
-
"records.invalidDocs": "--docs\uC5D0 \uB300\uC0C1 \uBB38\uC11C ID(S-\xB7R-\xB7D
|
|
25875
|
+
"records.invalidDocs": "--docs\uC5D0 \uB300\uC0C1 \uBB38\uC11C ID(S-\xB7R-\xB7D-)\uB97C \uD558\uB098 \uC774\uC0C1 \uC801\uC73C\uC138\uC694.",
|
|
25876
|
+
"records.notDocIds": "--docs\uC5D0 \uBB38\uC11C ID(S-\xB7R-\xB7D-)\uAC00 \uC544\uB2CC \uAC12\uC774 \uC788\uC2B5\uB2C8\uB2E4: {ids}",
|
|
25939
25877
|
"records.skeleton": "(\uB0B4\uC6A9)",
|
|
25940
25878
|
"records.createdNext": "\uC139\uC158\uC744 \uCC44\uC6B0\uACE0 draft: true \uC904\uC744 \uC9C0\uC6B4 \uB4A4, \uCEE4\uBC0B\uD560 \uB54C \uC774 \uD30C\uC77C\uC744 paths\uC5D0 \uB123\uC73C\uC138\uC694.",
|
|
25941
25879
|
"records.unknown": "\uACB0\uC815\uAE30\uB85D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4: {ids}",
|
|
@@ -25967,17 +25905,10 @@ var messages_default3 = {
|
|
|
25967
25905
|
"help.specsNewStyle": "\uC694\uAD6C\uC0AC\uD56D \uD615\uC2DD(usecase, default). \uC5C6\uC73C\uBA74 \uC124\uC815\uC758 requirementStyle\uC744 \uB530\uB978\uB2E4",
|
|
25968
25906
|
"help.newTitle": "\uBB38\uC11C \uC81C\uBAA9",
|
|
25969
25907
|
"help.newDescription": "\uD55C \uC904 \uC124\uBA85",
|
|
25970
|
-
"help.instructions": "\uD504\uB85C\uC81D\uD2B8 \uC9C0\uCE68\uC758 \uBAA9\uB85D\xB7\uC6D0\uBB38\xB7\uC0DD\uC131",
|
|
25971
|
-
"help.instructionsList": "AGENTS.md\uC640 \uC9C0\uCE68 \uBAA9\uB85D (\uC9C0\uCE68\uB9C8\uB2E4 \uB538\uB9B0 \uD30C\uC77C\uC758 \uC81C\uBAA9\uACFC \uC124\uBA85)",
|
|
25972
|
-
"help.instructionsShow": "\uC9C0\uCE68 index.md \uC6D0\uBB38, \uB530\uB974\uB294 \uC124\uACC4, \uD3F4\uB354 \uD30C\uC77C \uBAA9\uB85D",
|
|
25973
|
-
"help.instructionsShowTargets": "\uC9C0\uCE68 \uD3F4\uB354 \uC774\uB984\uC774\uB098 I- ID (\uC5EC\uB7EC \uAC1C \uAC00\uB2A5)",
|
|
25974
|
-
"help.instructionsShowFile": "\uC9C0\uCE68 \uD3F4\uB354 \uC548\uC758 \uD30C\uC77C \uD558\uB098\uB97C \uC77D\uC74C (\uC608: references/code-style.md)",
|
|
25975
|
-
"help.instructionsNew": "ID\uB97C \uBC1C\uAE09\uD558\uACE0 \uC9C0\uCE68 \uD3F4\uB354\uC640 index.md \uBF08\uB300 \uC0DD\uC131 (draft: true \uD45C\uC2DC)",
|
|
25976
|
-
"help.instructionsNewName": "\uC9C0\uCE68 \uD3F4\uB354 \uC774\uB984 (\uC608: code-review)",
|
|
25977
25908
|
"help.recordsList": "HEAD \uC774\uB825\uC758 \uACB0\uC815\uAE30\uB85D (\uCD5C\uC2E0\uC21C, \uCEE4\uBC0B \uC804 \uAE30\uB85D\uC774 \uBA3C\uC800)",
|
|
25978
25909
|
"help.recordsListDoc": "\uD55C \uBB38\uC11C\uC758 \uACB0\uC815 \uD750\uB984: \uADF8 \uBB38\uC11C\uAC00 \uBC14\uB010 \uCEE4\uBC0B\uB9C8\uB2E4 \uACB0\uC815\uAE30\uB85D",
|
|
25979
25910
|
"help.recordsListSince": "\uADF8 \uB0A0\uC9DC(YYYY-MM-DD)\uB098 \uCEE4\uBC0B \uB4A4\uC758 \uAC83\uB9CC",
|
|
25980
|
-
"help.check": "\uBA85\uC138\xB7\
|
|
25911
|
+
"help.check": "\uBA85\uC138\xB7\uCEE4\uBC0B \uC804 \uACB0\uC815\uAE30\uB85D \uC804\uCCB4\uC758 \uD615\uC2DD\xB7ID\xB7\uCC38\uC870\xB7\uCD08\uC548 \uD45C\uC2DC \uAC80\uC0AC (\uBB38\uC81C\uAC00 \uC788\uC73C\uBA74 \uC885\uB8CC \uCF54\uB4DC 1)",
|
|
25981
25912
|
"help.listQ": "\uC81C\uBAA9\xB7\uC124\uBA85\xB7\uBCF8\uBB38\uC5D0 \uC774 \uB9D0\uC774 \uC788\uB294 \uAC83\uB9CC",
|
|
25982
25913
|
"help.listAuthor": "\uC774 Git \uC791\uC131\uC790(\uC774\uB984\uC774\uB098 \uC774\uBA54\uC77C)\uAC00 \uBC14\uAFBC \uAC83\uB9CC",
|
|
25983
25914
|
"help.listSort": "\uC815\uB82C \uAE30\uC900",
|
|
@@ -25994,18 +25925,9 @@ var messages_default3 = {
|
|
|
25994
25925
|
"list.features": "\uAE30\uB2A5",
|
|
25995
25926
|
"list.commits": "\uCEE4\uBC0B",
|
|
25996
25927
|
"list.records": "\uACB0\uC815\uAE30\uB85D",
|
|
25997
|
-
"docs.otherResource": "\uC774 \uBA85\uB839\uC774 \uB2E4\uB8E8\uB294 \uBB38\uC11C\uAC00 \uC544\uB2D9\uB2C8\uB2E4: {ids}. {command}\uB85C \uC77D\uC73C\uC138\uC694.",
|
|
25998
25928
|
"docs.noMatch": "\uC870\uAC74\uC5D0 \uB9DE\uB294 \uAC83\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25999
25929
|
"docs.requirement": "\uC694\uAD6C\uC0AC\uD56D",
|
|
26000
25930
|
"docs.design": "\uC124\uACC4",
|
|
26001
|
-
"instructions.agents": "AGENTS.md \u2014 \uBE14\uB85D \uBC16 \uC0C9\uC778\uC774 \uC5B4\uB5A4 \uC791\uC5C5\uC5D0 \uC5B4\uB290 \uC9C0\uCE68\uC744 \uC77D\uC744\uC9C0 \uC54C\uB9B0\uB2E4",
|
|
26002
|
-
"instructions.noAgents": "AGENTS.md \uC5C6\uC74C \u2014 \uC9C0\uCE68\uC744 \uC5B8\uC81C \uC77D\uC744\uC9C0 \uC54C\uB9AC\uB294 \uC0C9\uC778\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
26003
|
-
"instructions.filesLimited": "(\uD30C\uC77C\uC774 \uB354 \uC788\uC5B4 \uC55E {count}\uAC1C\uB9CC \uBCF4\uC785\uB2C8\uB2E4)",
|
|
26004
|
-
"instructions.empty": "\uC9C0\uCE68\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. instructions new\uB85C \uB9CC\uB4DC\uC138\uC694.",
|
|
26005
|
-
"instructions.fileWithOne": "--file\uC740 \uC9C0\uCE68 \uD558\uB098\uC640 \uD568\uAED8 \uC4F0\uBA70 --ref\uC640 \uD568\uAED8 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
26006
|
-
"instructions.unknownFile": "\uC9C0\uCE68 {name} \uD3F4\uB354\uC5D0 \uADF8 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4: {path}",
|
|
26007
|
-
"instructions.fileTooLarge": "(\uD30C\uC77C\uC774 \uCEE4\uC11C \uC6D0\uBB38\uC744 \uBCF4\uC774\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: {size}\uBC14\uC774\uD2B8)",
|
|
26008
|
-
"instructions.fileBinary": "(\uD14D\uC2A4\uD2B8 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: {size}\uBC14\uC774\uD2B8)",
|
|
26009
25931
|
"records.empty": "\uACB0\uC815\uAE30\uB85D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
26010
25932
|
"records.moreDocs": "\uC678 {count}\uAC1C",
|
|
26011
25933
|
"help.feedback": "Gitifact \uC790\uCCB4\uC758 \uBC84\uADF8\xB7\uAC1C\uC120\uC744 Gitifact \uC800\uC7A5\uC18C \uC774\uC288\uB85C \uBCF4\uB0C4 (gh\uAC00 \uC5C6\uC73C\uBA74 \uC774\uC288 \uC791\uC131 \uC8FC\uC18C \uCD9C\uB825)",
|
|
@@ -26021,11 +25943,11 @@ var messages_default3 = {
|
|
|
26021
25943
|
"feedback.truncated": "\uBCF8\uBB38\uC774 \uAE38\uC5B4 \uC8FC\uC18C\uC5D0\uB294 \uC55E\uBD80\uBD84\uB9CC \uB2F4\uACBC\uC2B5\uB2C8\uB2E4. \uC544\uB798 \uC804\uCCB4 \uBCF8\uBB38\uC744 \uC791\uC131 \uD398\uC774\uC9C0\uC5D0 \uBD99\uC5EC \uB123\uC73C\uC138\uC694.",
|
|
26022
25944
|
"feedback.title": "\uC81C\uBAA9: {title}",
|
|
26023
25945
|
"update.text.projectWritten": "{path}\uC758 \uD504\uB85C\uC81D\uD2B8 \uAE30\uC900\uC744 gitifact {version}\uC73C\uB85C \uC801\uC5C8\uC2B5\uB2C8\uB2E4.",
|
|
26024
|
-
"update.text.projectAhead": "\uD504\uB85C\uC81D\uD2B8 \uAE30\uC900\uC740 gitifact {project}\uC785\uB2C8\uB2E4. \uC774 CLI({version})\uAC00 \uB354 \uC624\uB798\uB418\uC5B4 \uB0AE\uCD94\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.
|
|
25946
|
+
"update.text.projectAhead": "\uD504\uB85C\uC81D\uD2B8 \uAE30\uC900\uC740 gitifact {project}\uC785\uB2C8\uB2E4. \uC774 CLI({version})\uAC00 \uB354 \uC624\uB798\uB418\uC5B4 \uB0AE\uCD94\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uD504\uB85C\uC81D\uD2B8\uC758 \uC2E4\uD589\uAE30 node .gitifact/bin/cli.mjs\uB85C \uC2E4\uD589\uD558\uC138\uC694.",
|
|
26025
25947
|
"update.later.postponed": "{latest} \uC548\uB0B4\uB97C {until}\uAE4C\uC9C0 \uC27D\uB2C8\uB2E4. \uB354 \uC0C8 \uBC84\uC804\uC774 \uB098\uC624\uBA74 \uBC14\uB85C \uB2E4\uC2DC \uC548\uB0B4\uD569\uB2C8\uB2E4.",
|
|
26026
25948
|
"update.later.nothing": "\uBBF8\uB8F0 \uC0C8 \uBC84\uC804 \uC548\uB0B4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(\uC9C0\uAE08 {version}).",
|
|
26027
|
-
"notice.release": "\uC0C8 \uBC84\uC804 {latest}\uAC00 \uC788\uC2B5\uB2C8\uB2E4(\uC9C0\uAE08 {version}). \uC5C5\uB370\uC774\uD2B8: {command} \
|
|
26028
|
-
"notice.projectNewer": "\uC774 \uD504\uB85C\uC81D\uD2B8\uB294 gitifact {project} \uAE30\uC900\uC785\uB2C8\uB2E4(\uC2E4\uD589 \uC911 {version}).
|
|
25949
|
+
"notice.release": "\uC0C8 \uBC84\uC804 {latest}\uAC00 \uC788\uC2B5\uB2C8\uB2E4(\uC9C0\uAE08 {version}). \uC5C5\uB370\uC774\uD2B8: {command} \xB7 \uB098\uC911\uC5D0: gitifact update --later",
|
|
25950
|
+
"notice.projectNewer": "\uC774 \uD504\uB85C\uC81D\uD2B8\uB294 gitifact {project} \uAE30\uC900\uC785\uB2C8\uB2E4(\uC2E4\uD589 \uC911 {version}). \uD504\uB85C\uC81D\uD2B8\uC758 \uC2E4\uD589\uAE30 node .gitifact/bin/cli.mjs\uB85C \uC2E4\uD589\uD558\uC138\uC694.",
|
|
26029
25951
|
"notice.projectOlder": "\uC774 CLI({version})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uAE30\uC900({project})\uBCF4\uB2E4 \uC0C8 \uBC84\uC804\uC785\uB2C8\uB2E4. gitifact update\uB85C \uD504\uB85C\uC81D\uD2B8 \uAE30\uC900\uC744 \uC62C\uB9B4 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
26030
25952
|
"help.updateLater": "\uC9C0\uAE08 \uC548\uB0B4\uB41C \uC0C8 \uBC84\uC804\uC744 24\uC2DC\uAC04 \uB3D9\uC548 \uC548\uB0B4\uD558\uC9C0 \uC54A\uC74C. \uB354 \uC0C8 \uBC84\uC804\uC740 \uBC14\uB85C \uC548\uB0B4",
|
|
26031
25953
|
"update.text.blockKept": "\uD504\uB85C\uC81D\uD2B8\uAC00 \uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804 \uAE30\uC900\uC774\uB77C \uC9C0\uCE68 \uBE14\uB85D\uC744 \uADF8\uB300\uB85C \uB450\uC5C8\uC2B5\uB2C8\uB2E4: {paths}"
|
|
@@ -26086,7 +26008,6 @@ var messages_default4 = {
|
|
|
26086
26008
|
"server.recordNotFound": "This history has no such decision record.",
|
|
26087
26009
|
"server.documentNotFound": "Neither this history nor the working tree has that document.",
|
|
26088
26010
|
"server.commitFileNotFound": "That commit did not change this file.",
|
|
26089
|
-
"server.instructionFileNotFound": "The instruction file was not found.",
|
|
26090
26011
|
"server.specsUnreadable": "Could not read specifications.",
|
|
26091
26012
|
"server.refreshOrigin": "Refresh requires a same-origin Origin header.",
|
|
26092
26013
|
"server.fileNotFound": "File not found.",
|
|
@@ -26128,7 +26049,7 @@ var messages_default4 = {
|
|
|
26128
26049
|
"init.text.storage": "Storage convention",
|
|
26129
26050
|
"init.text.agentDocs": "Agent instructions",
|
|
26130
26051
|
"init.text.lineEndings": "Line endings: {path} keeps documents in LF. Documents that now show as changed differ only in line endings; commit them once to settle it.",
|
|
26131
|
-
"init.text.updateAvailable": "Version {version} is available.
|
|
26052
|
+
"init.text.updateAvailable": "Version {version} is available. Move the project to it with {command}.",
|
|
26132
26053
|
"init.failed": "Initialization failed. Check file permissions and the generated configuration and temporary files.",
|
|
26133
26054
|
"config.storeNotDirectory": ".gitifact must be a regular directory, not a link.",
|
|
26134
26055
|
"config.fileShape": "config.json must be a regular file no larger than 64 KiB.",
|
|
@@ -26163,14 +26084,13 @@ var messages_default4 = {
|
|
|
26163
26084
|
"update.text.upToDate": "You are using the latest version.",
|
|
26164
26085
|
"update.text.disabled": "Update checks are disabled.",
|
|
26165
26086
|
"update.text.unavailable": "Could not check for updates. Check your network connection.",
|
|
26166
|
-
"update.text.install": "
|
|
26167
|
-
"update.text.afterInstall": "
|
|
26087
|
+
"update.text.install": "Update command: {command}",
|
|
26088
|
+
"update.text.afterInstall": "It moves the project, its instruction blocks and the launcher (.gitifact/bin/cli.mjs) to the new version. Restart the browser with the new version too.",
|
|
26168
26089
|
"update.text.blockRefreshed": "Instruction blocks refreshed: {paths}",
|
|
26169
26090
|
"update.text.blockCurrent": "Instruction blocks are already current: {paths}",
|
|
26170
26091
|
"update.text.noBlock": "No instruction files contain a GITIFACT block. Run gitifact init to install one.",
|
|
26171
26092
|
"update.text.notInitialized": "Only the version was checked because this project is not initialized.",
|
|
26172
|
-
"update.text.
|
|
26173
|
-
"update.text.migrationRequired": "This project's documents still use the 0.7 storage convention (schemaVersion 2). The blocks describe the new commands, but the specs, instructions, records, check and changes commands refuse to run until the documents are moved. Follow npx --yes gitifact@{version} guide show migrate to move them.",
|
|
26093
|
+
"update.text.migrationRequired": "This project's documents still use the 0.7 storage convention (schemaVersion 2). The blocks describe the new commands, but the specs, records, check and changes commands refuse to run until the documents are moved. Follow npx --yes gitifact@{version} guide show migrate to move them.",
|
|
26174
26094
|
"update.text.committed": "Instruction blocks committed: {commit} ({paths})",
|
|
26175
26095
|
"update.text.commitNothing": "No instruction block changes to commit.",
|
|
26176
26096
|
"update.text.commitSkipped.untracked": "Not committed. Instruction files are untracked: {paths}",
|
|
@@ -26190,7 +26110,7 @@ var messages_default4 = {
|
|
|
26190
26110
|
"help.guide": "Writing guides for agents",
|
|
26191
26111
|
"help.guideList": "List guides (title and description)",
|
|
26192
26112
|
"help.guideShow": "Print one guide",
|
|
26193
|
-
"help.guideTopic": "One of workflow, spec, design,
|
|
26113
|
+
"help.guideTopic": "One of workflow, spec, design, records, writing, commit, migrate",
|
|
26194
26114
|
"command.failed": "The command failed.",
|
|
26195
26115
|
"project.notInitialized": "Initialize the project with gitifact init first.",
|
|
26196
26116
|
"input.file": "The input must be a JSON file of 1 MiB or less.",
|
|
@@ -26212,17 +26132,14 @@ var messages_default4 = {
|
|
|
26212
26132
|
"docs.unknownDocument": "Documents not found: {ids}",
|
|
26213
26133
|
"docs.references": "References",
|
|
26214
26134
|
"docs.referencedBy": "Referenced by",
|
|
26215
|
-
"docs.files": "Files",
|
|
26216
26135
|
"docs.invalidPath": "Not a path for a {kind} document: {path}. Example: {example}",
|
|
26217
26136
|
"docs.pathExample.feature": "payment (.gitifact/spec/payment/index.md)",
|
|
26218
26137
|
"docs.pathExample.requirement": "payment/cancel (.gitifact/spec/payment/requirements/cancel.md)",
|
|
26219
26138
|
"docs.pathExample.design": "payment/api (.gitifact/spec/payment/design/api.md)",
|
|
26220
|
-
"docs.pathExample.instruction": "cli-architecture (.gitifact/instructions/cli-architecture/index.md)",
|
|
26221
26139
|
"docs.skeleton.feature": "(What this feature is and where it ends)",
|
|
26222
26140
|
"docs.skeleton.requirement": "As (a user), I want to (act) so that (purpose).\n\n### Scope and constraints\n\n- (One rule that is either true or false. Remove this section if there is none)\n\n### Acceptance criteria\n\n1. Condition: (situation)\n Expected: (result)",
|
|
26223
26141
|
"docs.skeleton.requirementUsecase": "As (a user), I want to (act) so that (purpose).\n\n### Scope and constraints\n\n- (One rule that is either true or false. Remove this section if there is none)\n\n### Preconditions\n\n- (What holds before it starts. Remove this section if there is none)\n\n### Basic flow\n\n1. (The actor) (acts).\n2. (The system) shows (the result).\n\n### Alternative flows\n\n- **A1. (Where it branches)** (at step 1)\n 1. (What happens then)\n\n### Postconditions\n\n- (What holds when it ends. Remove this section if there is none)\n\n### Acceptance criteria\n\n1. Path: Basic flow\n Condition: (situation)\n Expected: (result)\n2. Path: Basic flow, A1\n Condition: (situation)\n Expected: (result)",
|
|
26224
26142
|
"docs.skeleton.design": "(The structure and processing this design covers)",
|
|
26225
|
-
"docs.skeleton.instruction": "(Rules and steps to follow for this kind of work. Put details in files under references/ and link them from here)",
|
|
26226
26143
|
"docs.exists": "The file already exists: {path}",
|
|
26227
26144
|
"docs.notFolder": "Something other than a plain folder stands where a folder is needed: {path}",
|
|
26228
26145
|
"docs.created": "Created {path} ({id})",
|
|
@@ -26239,6 +26156,7 @@ var messages_default4 = {
|
|
|
26239
26156
|
"changes.committed": "Committed {commit} {message}",
|
|
26240
26157
|
"changes.dryRun": "Preview: no files were written and nothing was committed.",
|
|
26241
26158
|
"changes.summary": "{paths} file(s), {changes} changed document(s), {records} record(s)",
|
|
26159
|
+
"commit.tooManyStorePaths": "This commit has {count} paths under .gitifact. One commit takes up to {limit} documents, records and assets; split the commits by decision (code paths do not count toward this limit).",
|
|
26242
26160
|
"commit.migrationFlag": "migration must be true or absent.",
|
|
26243
26161
|
"commit.checkFailed": "The document check found {count} problems; nothing was committed.",
|
|
26244
26162
|
"commit.unknownDocument": "A record names documents that do not exist: {ids}",
|
|
@@ -26254,7 +26172,8 @@ var messages_default4 = {
|
|
|
26254
26172
|
"changes.recordAltered": "Committed records edited or deleted (the commit is refused): {paths}",
|
|
26255
26173
|
"commit.recordAltered": "Committed records cannot be edited or deleted: {paths}. Restore them from HEAD and write a changed decision as a new record (records new).",
|
|
26256
26174
|
"commit.selectMove": "Select both the old and the new path of a moved document: {ids}",
|
|
26257
|
-
"records.invalidDocs": "Give at least one target document ID (S-, R-, D
|
|
26175
|
+
"records.invalidDocs": "Give at least one target document ID (S-, R-, D-) with --docs.",
|
|
26176
|
+
"records.notDocIds": "--docs has values that are not document IDs (S-, R-, D-): {ids}",
|
|
26258
26177
|
"records.skeleton": "(Content)",
|
|
26259
26178
|
"records.createdNext": "Fill in the sections, remove the draft: true line, and list this file in paths when you commit.",
|
|
26260
26179
|
"records.unknown": "No such record: {ids}",
|
|
@@ -26286,17 +26205,10 @@ var messages_default4 = {
|
|
|
26286
26205
|
"help.specsNewStyle": "Requirement shape (usecase, default). Defaults to the config requirementStyle",
|
|
26287
26206
|
"help.newTitle": "Document title",
|
|
26288
26207
|
"help.newDescription": "One-line description",
|
|
26289
|
-
"help.instructions": "List, read and create project instructions",
|
|
26290
|
-
"help.instructionsList": "AGENTS.md and the instructions (with the title and description of each file in their folders)",
|
|
26291
|
-
"help.instructionsShow": "An instruction's index.md as written, the designs that follow it and its folder's files",
|
|
26292
|
-
"help.instructionsShowTargets": "Instruction folder names or I- IDs (one or more)",
|
|
26293
|
-
"help.instructionsShowFile": "Read one file of the instruction folder (e.g. references/code-style.md)",
|
|
26294
|
-
"help.instructionsNew": "Create an instruction folder and index.md skeleton with an issued ID (marked draft: true)",
|
|
26295
|
-
"help.instructionsNewName": "Instruction folder name (e.g. code-review)",
|
|
26296
26208
|
"help.recordsList": "Decision records of HEAD's history (newest first, uncommitted ones first)",
|
|
26297
26209
|
"help.recordsListDoc": "One document's decision flow: the records of each commit that changed it",
|
|
26298
26210
|
"help.recordsListSince": "Only those after that date (YYYY-MM-DD) or commit",
|
|
26299
|
-
"help.check": "Check the format, IDs, references and draft marks of all specs
|
|
26211
|
+
"help.check": "Check the format, IDs, references and draft marks of all specs and uncommitted records (exit code 1 on problems)",
|
|
26300
26212
|
"help.listQ": "Only those whose title, description or text holds these words",
|
|
26301
26213
|
"help.listAuthor": "Only those this Git author (name or email) changed",
|
|
26302
26214
|
"help.listSort": "Sort key",
|
|
@@ -26313,18 +26225,9 @@ var messages_default4 = {
|
|
|
26313
26225
|
"list.features": "Features",
|
|
26314
26226
|
"list.commits": "Commits",
|
|
26315
26227
|
"list.records": "Records",
|
|
26316
|
-
"docs.otherResource": "Not a document this command reads: {ids}. Use {command}.",
|
|
26317
26228
|
"docs.noMatch": "Nothing matches.",
|
|
26318
26229
|
"docs.requirement": "requirement",
|
|
26319
26230
|
"docs.design": "design",
|
|
26320
|
-
"instructions.agents": "AGENTS.md \u2014 the index outside the block says which instruction to read for which work",
|
|
26321
|
-
"instructions.noAgents": "No AGENTS.md \u2014 nothing tells when to read which instruction",
|
|
26322
|
-
"instructions.filesLimited": "(the folder holds more; only the first {count} are shown)",
|
|
26323
|
-
"instructions.empty": "No instructions yet. Create one with instructions new.",
|
|
26324
|
-
"instructions.fileWithOne": "--file takes one instruction and does not go with --ref.",
|
|
26325
|
-
"instructions.unknownFile": "The folder of instruction {name} has no such file: {path}",
|
|
26326
|
-
"instructions.fileTooLarge": "(Too large to show: {size} bytes)",
|
|
26327
|
-
"instructions.fileBinary": "(Not a text file: {size} bytes)",
|
|
26328
26231
|
"records.empty": "No decision records yet.",
|
|
26329
26232
|
"records.moreDocs": "and {count} more",
|
|
26330
26233
|
"help.feedback": "Send a Gitifact bug or idea as an issue to Gitifact's repository (prints a new-issue address without gh)",
|
|
@@ -26340,11 +26243,11 @@ var messages_default4 = {
|
|
|
26340
26243
|
"feedback.truncated": "The body is long, so the address holds only its beginning. Paste the full body below into the page.",
|
|
26341
26244
|
"feedback.title": "Title: {title}",
|
|
26342
26245
|
"update.text.projectWritten": "Set the project to gitifact {version} in {path}.",
|
|
26343
|
-
"update.text.projectAhead": "The project is set to gitifact {project}. This CLI ({version}) is older, so it was not lowered.
|
|
26246
|
+
"update.text.projectAhead": "The project is set to gitifact {project}. This CLI ({version}) is older, so it was not lowered. Run it through the project's launcher, node .gitifact/bin/cli.mjs.",
|
|
26344
26247
|
"update.later.postponed": "The notice for {latest} is quiet until {until}. A newer release is announced right away.",
|
|
26345
26248
|
"update.later.nothing": "No newer release to postpone (running {version}).",
|
|
26346
|
-
"notice.release": "Version {latest} is available (running {version}). Update: {command}
|
|
26347
|
-
"notice.projectNewer": "This project is set to gitifact {project} (running {version}).
|
|
26249
|
+
"notice.release": "Version {latest} is available (running {version}). Update: {command} \xB7 Later: gitifact update --later",
|
|
26250
|
+
"notice.projectNewer": "This project is set to gitifact {project} (running {version}). Run it through the project's launcher, node .gitifact/bin/cli.mjs.",
|
|
26348
26251
|
"notice.projectOlder": "This CLI ({version}) is newer than the project ({project}). Run gitifact update to move the project to it.",
|
|
26349
26252
|
"help.updateLater": "Quiet the announced newer release for 24 hours; a release newer than it is announced right away",
|
|
26350
26253
|
"update.text.blockKept": "The project is set to a newer release than this CLI, so the instruction blocks were left as they are: {paths}"
|
|
@@ -26699,7 +26602,7 @@ function storeReader(cwd) {
|
|
|
26699
26602
|
import { DatabaseSync } from "node:sqlite";
|
|
26700
26603
|
import { lstat, mkdir, rm, writeFile } from "node:fs/promises";
|
|
26701
26604
|
import { join as join2 } from "node:path";
|
|
26702
|
-
var CACHE_FORMAT =
|
|
26605
|
+
var CACHE_FORMAT = 13;
|
|
26703
26606
|
var CACHE_DIR = ".gitifact/cache";
|
|
26704
26607
|
var SCHEMA = `
|
|
26705
26608
|
-- Working-tree files already read: the modification time and size decide whether a file is read again.
|
|
@@ -26885,6 +26788,7 @@ function createDocumentCache(root, database) {
|
|
|
26885
26788
|
async function read(path3, seen) {
|
|
26886
26789
|
try {
|
|
26887
26790
|
if (isWikiPage(path3)) return { problem: docProblem("WIKI_REMOVED", path3) };
|
|
26791
|
+
if (isInstructionPath(path3)) return path3.endsWith("/index.md") && classifyDocPath(path3).type === "doc" ? { problem: docProblem("INSTRUCTION_MOVED", instructionFolderOf(path3)) } : {};
|
|
26888
26792
|
if (classifyDocPath(path3).type !== "doc") return {};
|
|
26889
26793
|
if (seen.link) return { problem: docProblem("PATH_UNSUPPORTED", path3) };
|
|
26890
26794
|
if (seen.size > FILE_LIMIT) return { problem: docProblem("FILE_TOO_LARGE", path3) };
|
|
@@ -26959,13 +26863,6 @@ function createDocumentCache(root, database) {
|
|
|
26959
26863
|
return true;
|
|
26960
26864
|
}
|
|
26961
26865
|
};
|
|
26962
|
-
const instructionFile3 = (path3) => {
|
|
26963
|
-
try {
|
|
26964
|
-
return classifyDocPath(path3).type === "instruction-file";
|
|
26965
|
-
} catch {
|
|
26966
|
-
return false;
|
|
26967
|
-
}
|
|
26968
|
-
};
|
|
26969
26866
|
return {
|
|
26970
26867
|
sync,
|
|
26971
26868
|
/**
|
|
@@ -26982,7 +26879,7 @@ function createDocumentCache(root, database) {
|
|
|
26982
26879
|
if (history) seen.set(HISTORY_PATH, { mtime: history.mtimeMs, size: history.size, link: history.isSymbolicLink() || !history.isFile() });
|
|
26983
26880
|
const read2 = await Promise.all([...seen].map(async ([path3, s]) => {
|
|
26984
26881
|
if (!readable(path3)) return { path: path3 };
|
|
26985
|
-
if (
|
|
26882
|
+
if (isInstructionPath(path3) && !path3.endsWith(".md")) return { path: path3, text: "" };
|
|
26986
26883
|
if (s.link) return { path: path3, problem: docProblem("PATH_UNSUPPORTED", path3) };
|
|
26987
26884
|
if (s.size > (path3 === HISTORY_PATH ? 64 * FILE_LIMIT : FILE_LIMIT)) return { path: path3, problem: docProblem("FILE_TOO_LARGE", path3) };
|
|
26988
26885
|
try {
|
|
@@ -28079,88 +27976,6 @@ async function publishConfig(root, text4, recheck, beforePublish, replace = fals
|
|
|
28079
27976
|
}
|
|
28080
27977
|
}
|
|
28081
27978
|
|
|
28082
|
-
// src/adapters/filesystem/instruction-folder.ts
|
|
28083
|
-
import { lstat as lstat6, open as open3, readdir as readdir4, readFile as readFile5 } from "node:fs/promises";
|
|
28084
|
-
import { join as join7 } from "node:path";
|
|
28085
|
-
var INSTRUCTION_FILE_LIMIT = 500;
|
|
28086
|
-
var INSTRUCTION_TEXT_LIMIT = 512 * 1024;
|
|
28087
|
-
var folderOf3 = (root, instructionPath) => join7(root, ...instructionPath.split("/").slice(0, -1));
|
|
28088
|
-
async function listInstructionFiles(root, instructionPath) {
|
|
28089
|
-
const files = [];
|
|
28090
|
-
let limited = false;
|
|
28091
|
-
async function visit2(folder, prefix, depth) {
|
|
28092
|
-
if (depth > 10) return;
|
|
28093
|
-
const entries = await readdir4(folder, { withFileTypes: true }).catch(() => []);
|
|
28094
|
-
for (const entry2 of entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
|
|
28095
|
-
if (files.length >= INSTRUCTION_FILE_LIMIT) {
|
|
28096
|
-
limited = true;
|
|
28097
|
-
return;
|
|
28098
|
-
}
|
|
28099
|
-
const path3 = prefix + entry2.name;
|
|
28100
|
-
if (entry2.isDirectory()) await visit2(join7(folder, entry2.name), path3 + "/", depth + 1);
|
|
28101
|
-
else if (entry2.isFile() && path3 !== INSTRUCTION_FILE) files.push({ path: path3, size: (await lstat6(join7(folder, entry2.name))).size });
|
|
28102
|
-
}
|
|
28103
|
-
}
|
|
28104
|
-
await visit2(folderOf3(root, instructionPath), "", 0);
|
|
28105
|
-
return { files, limited };
|
|
28106
|
-
}
|
|
28107
|
-
var FRONTMATTER_WINDOW = 8 * 1024;
|
|
28108
|
-
async function describeFiles(root, instructionPath, files) {
|
|
28109
|
-
const folder = folderOf3(root, instructionPath);
|
|
28110
|
-
return Promise.all(files.map(async (file2) => {
|
|
28111
|
-
if (!isInstructionReference(file2.path)) return file2;
|
|
28112
|
-
let handle;
|
|
28113
|
-
try {
|
|
28114
|
-
handle = await open3(join7(folder, ...file2.path.split("/")), "r");
|
|
28115
|
-
const buffer = Buffer.alloc(Math.min(FRONTMATTER_WINDOW, file2.size));
|
|
28116
|
-
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
28117
|
-
return { ...file2, ...parseInstructionFile(file2.path, buffer.subarray(0, bytesRead).toString("utf8")) };
|
|
28118
|
-
} catch {
|
|
28119
|
-
return file2;
|
|
28120
|
-
} finally {
|
|
28121
|
-
await handle?.close();
|
|
28122
|
-
}
|
|
28123
|
-
}));
|
|
28124
|
-
}
|
|
28125
|
-
async function readInstructionFiles(root, instructionPath) {
|
|
28126
|
-
const { files, limited } = await listInstructionFiles(root, instructionPath);
|
|
28127
|
-
return { files: await describeFiles(root, instructionPath, files), limited };
|
|
28128
|
-
}
|
|
28129
|
-
async function readInstructionFile(root, instructionPath, path3) {
|
|
28130
|
-
const parts = path3.split("/");
|
|
28131
|
-
if (parts.some((p) => !p || p === "." || p === ".." || /[\\:\0]/.test(p))) return void 0;
|
|
28132
|
-
let full = folderOf3(root, instructionPath);
|
|
28133
|
-
for (const [index, part] of parts.entries()) {
|
|
28134
|
-
full = join7(full, part);
|
|
28135
|
-
const info5 = await lstat6(full).catch(() => void 0);
|
|
28136
|
-
if (!info5 || info5.isSymbolicLink() || (index < parts.length - 1 ? !info5.isDirectory() : !info5.isFile())) return void 0;
|
|
28137
|
-
}
|
|
28138
|
-
const size = (await lstat6(full)).size;
|
|
28139
|
-
if (size > INSTRUCTION_TEXT_LIMIT) return { text: null, size, binary: false, tooLarge: true };
|
|
28140
|
-
const bytes = await readFile5(full);
|
|
28141
|
-
try {
|
|
28142
|
-
if (bytes.includes(0)) throw new TypeError("binary");
|
|
28143
|
-
return { text: new TextDecoder("utf-8", { fatal: true }).decode(bytes), size, binary: false, tooLarge: false };
|
|
28144
|
-
} catch {
|
|
28145
|
-
return { text: null, size, binary: true, tooLarge: false };
|
|
28146
|
-
}
|
|
28147
|
-
}
|
|
28148
|
-
|
|
28149
|
-
// src/adapters/filesystem/agents-file.ts
|
|
28150
|
-
import { lstat as lstat7, readFile as readFile6 } from "node:fs/promises";
|
|
28151
|
-
import { join as join8 } from "node:path";
|
|
28152
|
-
var LIMIT = 1024 * 1024;
|
|
28153
|
-
async function readAgentsFile(root) {
|
|
28154
|
-
const file2 = join8(root, "AGENTS.md");
|
|
28155
|
-
const info5 = await lstat7(file2).catch(() => void 0);
|
|
28156
|
-
if (!info5?.isFile() || info5.size > LIMIT) return null;
|
|
28157
|
-
try {
|
|
28158
|
-
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: false }).decode(await readFile6(file2));
|
|
28159
|
-
} catch {
|
|
28160
|
-
return null;
|
|
28161
|
-
}
|
|
28162
|
-
}
|
|
28163
|
-
|
|
28164
27979
|
// src/queries/document-states.ts
|
|
28165
27980
|
var isDocument = (path3) => {
|
|
28166
27981
|
try {
|
|
@@ -28229,8 +28044,8 @@ async function documentsAtHead(project, head, paths2) {
|
|
|
28229
28044
|
|
|
28230
28045
|
// src/server/checkout/stamp.ts
|
|
28231
28046
|
import { createHash as createHash2 } from "node:crypto";
|
|
28232
|
-
import { lstat as
|
|
28233
|
-
import { join as
|
|
28047
|
+
import { lstat as lstat6 } from "node:fs/promises";
|
|
28048
|
+
import { join as join7 } from "node:path";
|
|
28234
28049
|
function createStampReader(root, inherited = process.env) {
|
|
28235
28050
|
const runner = createGitRunner();
|
|
28236
28051
|
const env = { ...inherited, GIT_OPTIONAL_LOCKS: "0", GIT_NO_REPLACE_OBJECTS: "1", GIT_TERMINAL_PROMPT: "0", GIT_LITERAL_PATHSPECS: "0", LC_ALL: "C" };
|
|
@@ -28242,10 +28057,10 @@ function createStampReader(root, inherited = process.env) {
|
|
|
28242
28057
|
]);
|
|
28243
28058
|
const paths2 = status.split("\0").filter(Boolean).map((entry2) => entry2.slice(3)).filter((path3) => !path3.startsWith(".gitifact/cache/"));
|
|
28244
28059
|
const seen = await Promise.all(paths2.map(async (path3) => {
|
|
28245
|
-
const info5 = await
|
|
28060
|
+
const info5 = await lstat6(join7(root, ...path3.split("/"))).catch(() => void 0);
|
|
28246
28061
|
return path3 + " " + (info5 ? info5.mtimeMs + ":" + info5.size : "-");
|
|
28247
28062
|
}));
|
|
28248
|
-
const mailmap = await
|
|
28063
|
+
const mailmap = await lstat6(join7(root, ".mailmap")).catch(() => void 0);
|
|
28249
28064
|
seen.push(".mailmap " + (mailmap ? mailmap.mtimeMs + ":" + mailmap.size : "-"));
|
|
28250
28065
|
return createHash2("sha256").update(head.trim() + "\n" + seen.sort().join("\n")).digest("hex").slice(0, 20);
|
|
28251
28066
|
};
|
|
@@ -28258,7 +28073,7 @@ async function settled(reads) {
|
|
|
28258
28073
|
if (failure2) throw failure2.reason;
|
|
28259
28074
|
return results.map((r) => r.value);
|
|
28260
28075
|
}
|
|
28261
|
-
var
|
|
28076
|
+
var folderOf3 = (path3) => path3.split("/").slice(0, 3).join("/");
|
|
28262
28077
|
function checkoutDocuments(states, authors) {
|
|
28263
28078
|
const documents = states.documents;
|
|
28264
28079
|
const standing2 = (id) => {
|
|
@@ -28273,7 +28088,7 @@ function checkoutDocuments(states, authors) {
|
|
|
28273
28088
|
};
|
|
28274
28089
|
const arranged = arrangeDocuments(documents);
|
|
28275
28090
|
const features = arranged.features.map(({ index, requirements, designs }) => {
|
|
28276
|
-
const entry2 = authors.get(
|
|
28091
|
+
const entry2 = authors.get(folderOf3(index.path));
|
|
28277
28092
|
return {
|
|
28278
28093
|
id: index.id,
|
|
28279
28094
|
path: index.path,
|
|
@@ -28298,17 +28113,7 @@ function checkoutDocuments(states, authors) {
|
|
|
28298
28113
|
updatedAt: entry2?.latest ?? null
|
|
28299
28114
|
};
|
|
28300
28115
|
});
|
|
28301
|
-
|
|
28302
|
-
id: k.id,
|
|
28303
|
-
name: k.name,
|
|
28304
|
-
path: k.path,
|
|
28305
|
-
title: k.title,
|
|
28306
|
-
description: k.description,
|
|
28307
|
-
body: k.body,
|
|
28308
|
-
...standing2(k.id),
|
|
28309
|
-
updatedAt: authors.get(folderOf4(k.path))?.latest ?? null
|
|
28310
|
-
}));
|
|
28311
|
-
return { features, instructions: instructions2, orphans: arranged.orphans };
|
|
28116
|
+
return { features, orphans: arranged.orphans };
|
|
28312
28117
|
}
|
|
28313
28118
|
function createCheckoutReader(root, cache, inherited = process.env) {
|
|
28314
28119
|
const reader = storeReader(root);
|
|
@@ -28337,16 +28142,15 @@ function createCheckoutReader(root, cache, inherited = process.env) {
|
|
|
28337
28142
|
head ? cache.log.contributors(head) : Promise.resolve([])
|
|
28338
28143
|
]);
|
|
28339
28144
|
const states = await documentStates({ head: async () => head, reader }, current3.documents);
|
|
28340
|
-
const { features,
|
|
28145
|
+
const { features, orphans } = checkoutDocuments(states, authors);
|
|
28341
28146
|
const problems = [...current3.problems, ...orphans.map((feature2) => docProblem("FEATURE_INDEX_REQUIRED", `.gitifact/spec/${feature2}/index.md`, { feature: feature2 }))];
|
|
28342
28147
|
if (await readHead() !== head) throw new StoreError(t2("specReader.projectChanged"));
|
|
28343
28148
|
return {
|
|
28344
28149
|
head,
|
|
28345
28150
|
stamp,
|
|
28346
28151
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28347
|
-
working: head ? !!dirty.trim() : features.length > 0
|
|
28152
|
+
working: head ? !!dirty.trim() : features.length > 0,
|
|
28348
28153
|
features,
|
|
28349
|
-
instructions: instructions2,
|
|
28350
28154
|
problems,
|
|
28351
28155
|
people,
|
|
28352
28156
|
folders: authors
|
|
@@ -28369,19 +28173,7 @@ function createCheckoutReader(root, cache, inherited = process.env) {
|
|
|
28369
28173
|
}
|
|
28370
28174
|
return value;
|
|
28371
28175
|
};
|
|
28372
|
-
return {
|
|
28373
|
-
base,
|
|
28374
|
-
/** Every instruction by name with the other files of its folder, and AGENTS.md: few enough to read whole. */
|
|
28375
|
-
async instructions() {
|
|
28376
|
-
const checkout = await base();
|
|
28377
|
-
const instructions2 = await Promise.all([...checkout.instructions].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0).map(async (instruction2) => {
|
|
28378
|
-
const { files, limited } = instruction2.state === "deleted" ? { files: [], limited: false } : await readInstructionFiles(root, instruction2.path);
|
|
28379
|
-
return { ...instruction2, files, filesLimited: limited };
|
|
28380
|
-
}));
|
|
28381
|
-
const agentsText = await readAgentsFile(root);
|
|
28382
|
-
return { instructions: instructions2, agents: agentsText === null ? null : { path: "AGENTS.md", body: agentsText, updatedAt: checkout.folders.get("AGENTS.md")?.latest ?? null } };
|
|
28383
|
-
}
|
|
28384
|
-
};
|
|
28176
|
+
return { base };
|
|
28385
28177
|
}
|
|
28386
28178
|
|
|
28387
28179
|
// src/queries/paging.ts
|
|
@@ -28546,11 +28338,11 @@ async function workingChange2(source2, id) {
|
|
|
28546
28338
|
}
|
|
28547
28339
|
|
|
28548
28340
|
// src/queries/search.ts
|
|
28549
|
-
var SEARCH_GROUPS = ["feature", "requirement", "design", "
|
|
28341
|
+
var SEARCH_GROUPS = ["feature", "requirement", "design", "record", "commit"];
|
|
28550
28342
|
var FIRST = 5;
|
|
28551
28343
|
var RECENT = 6;
|
|
28552
28344
|
var place2 = (path3) => path3.replace(/^\.gitifact\//, "");
|
|
28553
|
-
var
|
|
28345
|
+
var folderOf4 = (path3) => path3.split("/").slice(0, 3).join("/");
|
|
28554
28346
|
async function searchRecords(source2, request) {
|
|
28555
28347
|
const head = request.head ?? await source2.head();
|
|
28556
28348
|
const query = request.q.trim().toLowerCase();
|
|
@@ -28567,14 +28359,7 @@ async function searchRecords(source2, request) {
|
|
|
28567
28359
|
var empty = () => ({ total: 0, next: null, hits: [] });
|
|
28568
28360
|
async function recent(source2, head) {
|
|
28569
28361
|
const [{ documents }, folders] = await Promise.all([source2.cache.documents.list(), head ? source2.cache.log.folders(head) : /* @__PURE__ */ new Map()]);
|
|
28570
|
-
const hits = documents.filter((d) => d.kind === "feature"
|
|
28571
|
-
id: doc.id,
|
|
28572
|
-
kind: doc.kind,
|
|
28573
|
-
title: doc.title,
|
|
28574
|
-
where: place2(doc.path),
|
|
28575
|
-
line: doc.description,
|
|
28576
|
-
...doc.kind === "feature" ? { featureId: doc.id } : {}
|
|
28577
|
-
}));
|
|
28362
|
+
const hits = documents.filter((d) => d.kind === "feature").map((d) => ({ doc: d, latest: folders.get(folderOf4(d.path))?.latest })).filter((d) => !!d.latest).sort((a, b) => Date.parse(b.latest) - Date.parse(a.latest) || a.doc.id.localeCompare(b.doc.id)).slice(0, RECENT).map(({ doc }) => ({ id: doc.id, kind: "feature", title: doc.title, where: place2(doc.path), line: doc.description, featureId: doc.id }));
|
|
28578
28363
|
return { group: "recent", total: hits.length, next: null, hits };
|
|
28579
28364
|
}
|
|
28580
28365
|
|
|
@@ -28609,7 +28394,6 @@ function checkoutIndex(base) {
|
|
|
28609
28394
|
requirements: f.requirements.map((r) => ({ id: r.id, path: r.path, title: r.title, description: r.description })),
|
|
28610
28395
|
designs: f.designs.map((d) => ({ id: d.id, path: d.path, title: d.title }))
|
|
28611
28396
|
})),
|
|
28612
|
-
instructions: base.instructions.map((k) => ({ id: k.id, name: k.name, path: k.path, title: k.title })),
|
|
28613
28397
|
people: base.people.map((p) => ({ name: p.name, email: p.email }))
|
|
28614
28398
|
};
|
|
28615
28399
|
}
|
|
@@ -28703,12 +28487,12 @@ function recordRoutes(root, sessionId, env) {
|
|
|
28703
28487
|
const cursorGone2 = () => new HttpError(404, "NOT_FOUND", t2("server.cursorNotFound"));
|
|
28704
28488
|
return [
|
|
28705
28489
|
// The checkout a part at a time, each shaped by the query layer (`queries/checkout.ts`): the frame every screen reads
|
|
28706
|
-
// first, the feature list and one feature,
|
|
28490
|
+
// first, the feature list and one feature, and the contributors.
|
|
28707
28491
|
route({ method: "GET", path: "/api/v1/checkout", session: true, unreadable: unreadable2, handle: async () => {
|
|
28708
28492
|
const base = await checkout.base();
|
|
28709
|
-
return ok(
|
|
28493
|
+
return ok(browserCheckoutV2.parse({
|
|
28710
28494
|
contract: "browser-checkout",
|
|
28711
|
-
version:
|
|
28495
|
+
version: 2,
|
|
28712
28496
|
sessionId,
|
|
28713
28497
|
head: base.head,
|
|
28714
28498
|
observedAt: base.observedAt,
|
|
@@ -28728,7 +28512,6 @@ function recordRoutes(root, sessionId, env) {
|
|
|
28728
28512
|
if (!feature2) throw new HttpError(404, "NOT_FOUND", t2("server.featureNotFound"));
|
|
28729
28513
|
return ok(browserFeatureV2.parse({ contract: "browser-feature", version: 2, sessionId, feature: feature2 }));
|
|
28730
28514
|
} }),
|
|
28731
|
-
route({ method: "GET", path: "/api/v1/instructions", session: true, unreadable: unreadable2, handle: async () => ok(browserInstructionsV1.parse({ contract: "browser-instructions", version: 1, sessionId, ...await checkout.instructions() })) }),
|
|
28732
28515
|
route({ method: "GET", path: "/api/v1/contributors", session: true, query: browserContributorsQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
|
|
28733
28516
|
const page = listContributors(await checkout.base(), query.q, { after: query.after, limit: query.limit ?? PAGE });
|
|
28734
28517
|
if (!page) throw cursorGone2();
|
|
@@ -28821,35 +28604,28 @@ function recordRoutes(root, sessionId, env) {
|
|
|
28821
28604
|
if (!found) throw new HttpError(404, "NOT_FOUND", t2("server.commitFileNotFound"));
|
|
28822
28605
|
return ok(browserCommitFileV1.parse({ contract: "browser-commit-file", version: 1, sessionId, commit: query.commit, ...found }));
|
|
28823
28606
|
} }),
|
|
28824
|
-
// One file of an instruction folder, read from the working tree when the reader opens it; the checkout lists the files.
|
|
28825
|
-
route({ method: "GET", path: "/api/v1/instructions/file", session: true, query: browserInstructionFileQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
|
|
28826
|
-
const instruction2 = (await cache.documents.list()).documents.find((d) => d.id === query.id && d.kind === "instruction");
|
|
28827
|
-
const found = instruction2 && await readInstructionFile(root, instruction2.path, query.path);
|
|
28828
|
-
if (!found) throw new HttpError(404, "NOT_FOUND", t2("server.instructionFileNotFound"));
|
|
28829
|
-
return ok(browserInstructionFileV1.parse({ contract: "browser-instruction-file", version: 1, sessionId, id: query.id, path: query.path, ...found }));
|
|
28830
|
-
} }),
|
|
28831
28607
|
// The search box's groups as the query layer works them out (`queries/search.ts`); the browser only draws them.
|
|
28832
|
-
route({ method: "GET", path: "/api/v1/search", session: true, query:
|
|
28608
|
+
route({ method: "GET", path: "/api/v1/search", session: true, query: browserSearchQueryV3, unreadable: unreadable2, handle: async ({ query }) => {
|
|
28833
28609
|
const groups = await searchRecords(source2, query);
|
|
28834
28610
|
if (!groups) throw cursorGone2();
|
|
28835
|
-
return ok(
|
|
28611
|
+
return ok(browserSearchV4.parse({ contract: "browser-search", version: 4, sessionId, query: query.q, groups }));
|
|
28836
28612
|
} })
|
|
28837
28613
|
];
|
|
28838
28614
|
}
|
|
28839
28615
|
|
|
28840
28616
|
// src/server/routes/asset-routes.ts
|
|
28841
|
-
import { lstat as
|
|
28842
|
-
import { join as
|
|
28617
|
+
import { lstat as lstat7, readFile as readFile5 } from "node:fs/promises";
|
|
28618
|
+
import { join as join8 } from "node:path";
|
|
28843
28619
|
function assetRoutes(root) {
|
|
28844
28620
|
return [
|
|
28845
28621
|
route({ method: "GET", path: "/api/v1/assets/*", session: false, handle: async ({ path: path3, response }) => {
|
|
28846
28622
|
const relative = path3.slice("/api/v1/assets/".length);
|
|
28847
28623
|
const assetPath = ASSETS_DIR + "/" + relative;
|
|
28848
28624
|
if (!isAssetPath(assetPath)) throw new HttpError(404, "NOT_FOUND", t2("server.assetNotFound"));
|
|
28849
|
-
const file2 =
|
|
28850
|
-
const stat3 = await
|
|
28625
|
+
const file2 = join8(root, ...assetPath.split("/"));
|
|
28626
|
+
const stat3 = await lstat7(file2).catch(() => void 0);
|
|
28851
28627
|
if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > 20 * 1024 * 1024) throw new HttpError(404, "NOT_FOUND", t2("server.assetNotFound"));
|
|
28852
|
-
const bytes = await
|
|
28628
|
+
const bytes = await readFile5(file2);
|
|
28853
28629
|
const extension = assetExtension(relative);
|
|
28854
28630
|
const inline = ["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(extension);
|
|
28855
28631
|
response.writeHead(200, {
|
|
@@ -28866,7 +28642,7 @@ function assetRoutes(root) {
|
|
|
28866
28642
|
}
|
|
28867
28643
|
|
|
28868
28644
|
// src/server/browser-server.ts
|
|
28869
|
-
var readBundledChangelog = (language) =>
|
|
28645
|
+
var readBundledChangelog = (language) => readFile6(new URL("./i18n/" + language + "/changelog.md", import.meta.url), "utf8").catch((error62) => {
|
|
28870
28646
|
if (error62.code === "ENOENT") return null;
|
|
28871
28647
|
throw error62;
|
|
28872
28648
|
});
|
|
@@ -28996,14 +28772,14 @@ async function runBrowser(options, version2) {
|
|
|
28996
28772
|
}
|
|
28997
28773
|
|
|
28998
28774
|
// src/commands/spec-init.ts
|
|
28999
|
-
import { readdir as
|
|
29000
|
-
import { join as
|
|
28775
|
+
import { readdir as readdir4 } from "node:fs/promises";
|
|
28776
|
+
import { join as join13 } from "node:path";
|
|
29001
28777
|
|
|
29002
28778
|
// src/adapters/git/init-repository.ts
|
|
29003
28779
|
import { createHash as createHash3 } from "node:crypto";
|
|
29004
|
-
import { lstat as
|
|
29005
|
-
import { join as
|
|
29006
|
-
var markerPresent = (path3) =>
|
|
28780
|
+
import { lstat as lstat8, readFile as readFile7 } from "node:fs/promises";
|
|
28781
|
+
import { join as join9 } from "node:path";
|
|
28782
|
+
var markerPresent = (path3) => lstat8(path3).then(() => true, (error62) => {
|
|
29007
28783
|
if (error62.code === "ENOENT") return false;
|
|
29008
28784
|
throw error62;
|
|
29009
28785
|
});
|
|
@@ -29026,10 +28802,10 @@ function initRepository(cwd, inherited = process.env) {
|
|
|
29026
28802
|
const gitDir = locations.length === 2 ? locations[0] : decodeGitLine(await git(["rev-parse", "--absolute-git-dir"], root));
|
|
29027
28803
|
const indexPath = locations.length === 2 ? locations[1] : decodeGitLine(await git(["rev-parse", "--path-format=absolute", "--git-path", "index"], root));
|
|
29028
28804
|
for (const marker2 of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"]) {
|
|
29029
|
-
if (await markerPresent(
|
|
28805
|
+
if (await markerPresent(join9(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
|
|
29030
28806
|
}
|
|
29031
28807
|
if (state2.changes.some((change2) => change2.kind === "unmerged")) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
29032
|
-
const index = await
|
|
28808
|
+
const index = await readFile7(indexPath).catch((error62) => {
|
|
29033
28809
|
if (error62.code === "ENOENT") return Buffer.alloc(0);
|
|
29034
28810
|
throw error62;
|
|
29035
28811
|
});
|
|
@@ -29064,14 +28840,14 @@ function initRepository(cwd, inherited = process.env) {
|
|
|
29064
28840
|
|
|
29065
28841
|
// src/adapters/filesystem/document-file.ts
|
|
29066
28842
|
import { randomBytes } from "node:crypto";
|
|
29067
|
-
import { lstat as
|
|
29068
|
-
import { join as
|
|
28843
|
+
import { lstat as lstat9, mkdir as mkdir3, writeFile as writeFile2 } from "node:fs/promises";
|
|
28844
|
+
import { join as join10 } from "node:path";
|
|
29069
28845
|
var generateId = (prefix) => prefix + "-" + [...randomBytes(10)].map((n) => "abcdefghijklmnopqrstuvwxyz234567"[n & 31]).join("");
|
|
29070
28846
|
async function createDocumentFile(root, path3, text4) {
|
|
29071
28847
|
const parts = path3.split("/");
|
|
29072
28848
|
for (let i = 1; i < parts.length; i++) {
|
|
29073
|
-
const folder =
|
|
29074
|
-
const info5 = await
|
|
28849
|
+
const folder = join10(root, ...parts.slice(0, i));
|
|
28850
|
+
const info5 = await lstat9(folder).catch((error62) => {
|
|
29075
28851
|
if (error62.code === "ENOENT") return void 0;
|
|
29076
28852
|
throw error62;
|
|
29077
28853
|
});
|
|
@@ -29081,7 +28857,7 @@ async function createDocumentFile(root, path3, text4) {
|
|
|
29081
28857
|
}
|
|
29082
28858
|
if (!info5.isDirectory() || info5.isSymbolicLink()) throw Object.assign(new Error(folder), { code: "ENOTDIR" });
|
|
29083
28859
|
}
|
|
29084
|
-
await writeFile2(
|
|
28860
|
+
await writeFile2(join10(root, ...parts), text4, { flag: "wx" });
|
|
29085
28861
|
}
|
|
29086
28862
|
var LINE_ENDINGS_PATH = ".gitifact/.gitattributes";
|
|
29087
28863
|
var LINE_ENDINGS = "# Written by gitifact init: documents keep LF on every OS, so what Git holds and the files read the same.\n* text=auto eol=lf\n";
|
|
@@ -29095,19 +28871,50 @@ async function writeLineEndings(root) {
|
|
|
29095
28871
|
}
|
|
29096
28872
|
}
|
|
29097
28873
|
|
|
28874
|
+
// src/adapters/filesystem/launcher-file.ts
|
|
28875
|
+
import { lstat as lstat10, mkdir as mkdir4, readFile as readFile8, writeFile as writeFile3 } from "node:fs/promises";
|
|
28876
|
+
import { join as join11 } from "node:path";
|
|
28877
|
+
var LAUNCHER_PATH = ".gitifact/bin/cli.mjs";
|
|
28878
|
+
var readBundledLauncher = () => readFile8(new URL("./launcher/cli.mjs", import.meta.url), "utf8").catch((error62) => {
|
|
28879
|
+
if (error62.code === "ENOENT") return void 0;
|
|
28880
|
+
throw error62;
|
|
28881
|
+
});
|
|
28882
|
+
async function refreshLauncher(root) {
|
|
28883
|
+
const text4 = await readBundledLauncher();
|
|
28884
|
+
return text4 === void 0 ? false : writeLauncher(root, text4.replace(/\r\n/g, "\n"));
|
|
28885
|
+
}
|
|
28886
|
+
async function writeLauncher(root, text4) {
|
|
28887
|
+
const folder = join11(root, ".gitifact", "bin");
|
|
28888
|
+
const file2 = join11(folder, "cli.mjs");
|
|
28889
|
+
const folderInfo = await lstat10(folder).catch((error62) => {
|
|
28890
|
+
if (error62.code === "ENOENT") return void 0;
|
|
28891
|
+
throw error62;
|
|
28892
|
+
});
|
|
28893
|
+
if (folderInfo && (!folderInfo.isDirectory() || folderInfo.isSymbolicLink())) throw Object.assign(new Error(folder), { code: "ENOTDIR" });
|
|
28894
|
+
if (!folderInfo) await mkdir4(folder);
|
|
28895
|
+
const info5 = await lstat10(file2).catch((error62) => {
|
|
28896
|
+
if (error62.code === "ENOENT") return void 0;
|
|
28897
|
+
throw error62;
|
|
28898
|
+
});
|
|
28899
|
+
if (info5 && (!info5.isFile() || info5.isSymbolicLink())) throw Object.assign(new Error(file2), { code: "ENOTDIR" });
|
|
28900
|
+
if (info5 && (await readFile8(file2, "utf8")).replace(/\r\n/g, "\n") === text4) return false;
|
|
28901
|
+
await writeFile3(file2, text4);
|
|
28902
|
+
return true;
|
|
28903
|
+
}
|
|
28904
|
+
|
|
29098
28905
|
// src/adapters/filesystem/managed-file.ts
|
|
29099
|
-
import { open as
|
|
29100
|
-
import { join as
|
|
28906
|
+
import { open as open3, readFile as readFile9, mkdir as mkdir5, realpath as realpath2, rename as rename2, link as link2, unlink as unlink2 } from "node:fs/promises";
|
|
28907
|
+
import { join as join12, dirname } from "node:path";
|
|
29101
28908
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
29102
28909
|
var DEFAULT_LIMIT = 1024 * 1024;
|
|
29103
28910
|
async function managedPath(root, path3, create = false) {
|
|
29104
28911
|
let full = root;
|
|
29105
28912
|
const parts = path3.split("/");
|
|
29106
28913
|
for (let i = 0; i < parts.length; i++) {
|
|
29107
|
-
full =
|
|
28914
|
+
full = join12(full, parts[i]);
|
|
29108
28915
|
let info5 = await fileInfo(full);
|
|
29109
28916
|
if (!info5 && create && i < parts.length - 1) {
|
|
29110
|
-
await
|
|
28917
|
+
await mkdir5(full).catch((error62) => {
|
|
29111
28918
|
if (error62.code !== "EEXIST") throw error62;
|
|
29112
28919
|
});
|
|
29113
28920
|
info5 = await fileInfo(full);
|
|
@@ -29123,7 +28930,7 @@ async function managedRead(root, path3, limit = DEFAULT_LIMIT) {
|
|
|
29123
28930
|
const before = await fileInfo(full);
|
|
29124
28931
|
if (!before) return null;
|
|
29125
28932
|
if (before.size > limit) throw new InitError("FILE_TOO_LARGE", t2("managedFile.tooLarge", { kib: limit / 1024, path: path3 }));
|
|
29126
|
-
const bytes = await
|
|
28933
|
+
const bytes = await readFile9(full);
|
|
29127
28934
|
await managedPath(root, path3);
|
|
29128
28935
|
const after = await fileInfo(full);
|
|
29129
28936
|
if (!after || before.ino !== after.ino || before.dev !== after.dev || before.mtimeMs !== after.mtimeMs || bytes.length > limit) {
|
|
@@ -29152,8 +28959,8 @@ async function managedWrite(root, path3, previous, next, recheck) {
|
|
|
29152
28959
|
if (previous !== null) await unlink2(full);
|
|
29153
28960
|
return;
|
|
29154
28961
|
}
|
|
29155
|
-
const temp =
|
|
29156
|
-
const handle = await
|
|
28962
|
+
const temp = join12(directory, ".gitifact-managed-" + randomUUID4() + ".tmp");
|
|
28963
|
+
const handle = await open3(temp, "wx", 384);
|
|
29157
28964
|
const tempOwner = await handle.stat();
|
|
29158
28965
|
try {
|
|
29159
28966
|
try {
|
|
@@ -29164,7 +28971,7 @@ async function managedWrite(root, path3, previous, next, recheck) {
|
|
|
29164
28971
|
}
|
|
29165
28972
|
await recheck();
|
|
29166
28973
|
await unchanged();
|
|
29167
|
-
if (await managedRead(root, path3) !== previous || await
|
|
28974
|
+
if (await managedRead(root, path3) !== previous || await readFile9(temp, "utf8") !== next) throw new InitError("INPUT_CHANGED", t2("managedFile.publishTargetChanged", { path: path3 }));
|
|
29168
28975
|
if (previous === null) await link2(temp, full);
|
|
29169
28976
|
else await rename2(temp, full);
|
|
29170
28977
|
} finally {
|
|
@@ -29175,10 +28982,10 @@ async function managedWrite(root, path3, previous, next, recheck) {
|
|
|
29175
28982
|
}
|
|
29176
28983
|
|
|
29177
28984
|
// src/commands/agent-block.ts
|
|
29178
|
-
import { readFile as
|
|
28985
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
29179
28986
|
|
|
29180
28987
|
// src/commands/guide.ts
|
|
29181
|
-
import { readFile as
|
|
28988
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
29182
28989
|
|
|
29183
28990
|
// src/commands/output.ts
|
|
29184
28991
|
var formats = ["text", "json"];
|
|
@@ -29213,9 +29020,9 @@ var section = (label, lines2, indent = " ") => lines2.length ? [label, ...lines
|
|
|
29213
29020
|
var text2 = (lines2) => lines2.join("\n") + "\n";
|
|
29214
29021
|
|
|
29215
29022
|
// src/commands/guide.ts
|
|
29216
|
-
var guideTopics = ["workflow", "spec", "design", "
|
|
29023
|
+
var guideTopics = ["workflow", "spec", "design", "records", "writing", "commit", "migrate"];
|
|
29217
29024
|
var isGuideTopic = (value) => guideTopics.includes(value);
|
|
29218
|
-
var readBundledGuide = (name2, lang) =>
|
|
29025
|
+
var readBundledGuide = (name2, lang) => readFile10(new URL("./i18n/" + lang + "/docs/" + name2 + ".md", import.meta.url), "utf8");
|
|
29219
29026
|
function guideSummary(source2) {
|
|
29220
29027
|
const { fields: fields2 } = parseFrontmatterBlock(source2.replace(/\r\n/g, "\n"), "guide");
|
|
29221
29028
|
const value = (key) => {
|
|
@@ -29256,7 +29063,7 @@ function boilerplateFor(path3) {
|
|
|
29256
29063
|
const name2 = path3 === "AGENTS.md" ? path3 : path3.split("/").pop().replace(/^\./, "").replace(/\.md$/, "");
|
|
29257
29064
|
return "# " + name2 + "\n\nProject-specific guidance for AI coding agents.\n";
|
|
29258
29065
|
}
|
|
29259
|
-
var readBundledBlock = (lang) =>
|
|
29066
|
+
var readBundledBlock = (lang) => readFile11(new URL("./i18n/" + lang + "/block.md", import.meta.url), "utf8");
|
|
29260
29067
|
async function renderAgentBlock(controls = {}, lang = getLanguage()) {
|
|
29261
29068
|
const body2 = await (controls.readBlock ?? readBundledBlock)(lang);
|
|
29262
29069
|
return AGENT_START + "\n" + body2.trimEnd().replace(/\{topics\}/g, guideTopics.join(", ")) + "\n" + AGENT_END;
|
|
@@ -29285,15 +29092,9 @@ function isWrapperFile(text4) {
|
|
|
29285
29092
|
return lines2.length > 0 && lines2.every((line2) => /^@(?:\.\/)?[^\s]+$/.test(line2) && candidatePaths.includes(line2.replace(/^@(?:\.\/)?/, "")));
|
|
29286
29093
|
}
|
|
29287
29094
|
var CLAUDE_WRAPPER_PATH = "CLAUDE.md";
|
|
29288
|
-
function claudeWrapperFor(agents2) {
|
|
29289
|
-
return "@AGENTS.md" + eolOf(agents2);
|
|
29290
|
-
}
|
|
29291
29095
|
function isGeneratedClaudeWrapper(text4) {
|
|
29292
29096
|
return text4.trim() === "@AGENTS.md";
|
|
29293
29097
|
}
|
|
29294
|
-
function lacksClaudeFile(existing) {
|
|
29295
|
-
return !existing.has("CLAUDE.md") && !existing.has(".claude/CLAUDE.md");
|
|
29296
|
-
}
|
|
29297
29098
|
function resolveAgentPaths(preset, existing) {
|
|
29298
29099
|
if (preset && preset !== "all") {
|
|
29299
29100
|
const order = agentPresets[preset];
|
|
@@ -29327,7 +29128,7 @@ function removeBlock(text4, boilerplate) {
|
|
|
29327
29128
|
}
|
|
29328
29129
|
|
|
29329
29130
|
// src/commands/agent-docs.ts
|
|
29330
|
-
var skippedAgentDocs = (language = explicitLanguage() ?? getLanguage()) => ({ mode: "skip", paths: [], writes: [],
|
|
29131
|
+
var skippedAgentDocs = (language = explicitLanguage() ?? getLanguage()) => ({ mode: "skip", paths: [], writes: [], language });
|
|
29331
29132
|
var blockOf = (text4) => {
|
|
29332
29133
|
try {
|
|
29333
29134
|
const found = findBlock(text4);
|
|
@@ -29362,7 +29163,7 @@ async function planAgentDocs(root, options) {
|
|
|
29362
29163
|
paths2.push(CLAUDE_WRAPPER_PATH);
|
|
29363
29164
|
writes.push({ path: CLAUDE_WRAPPER_PATH, previous: wrapper, next: null });
|
|
29364
29165
|
}
|
|
29365
|
-
return { mode: "remove", paths: paths2, writes,
|
|
29166
|
+
return { mode: "remove", paths: paths2, writes, language };
|
|
29366
29167
|
}
|
|
29367
29168
|
let block;
|
|
29368
29169
|
const blockFor = async () => block ??= await renderAgentBlock(options, language);
|
|
@@ -29377,19 +29178,11 @@ async function planAgentDocs(root, options) {
|
|
|
29377
29178
|
paths2.push(create);
|
|
29378
29179
|
writes.push({ path: create, previous: null, next: injectBlock(null, await blockFor(), boilerplateFor(create)) });
|
|
29379
29180
|
}
|
|
29380
|
-
const missing2 = [];
|
|
29381
|
-
if (paths2.includes("AGENTS.md") && lacksClaudeFile(existing)) {
|
|
29382
|
-
if (options.onlyExisting) missing2.push(CLAUDE_WRAPPER_PATH);
|
|
29383
|
-
else {
|
|
29384
|
-
paths2.push(CLAUDE_WRAPPER_PATH);
|
|
29385
|
-
writes.push({ path: CLAUDE_WRAPPER_PATH, previous: null, next: claudeWrapperFor(existing.get("AGENTS.md") ?? null) });
|
|
29386
|
-
}
|
|
29387
|
-
}
|
|
29388
29181
|
for (const [path3, text4] of existing) {
|
|
29389
29182
|
if (paths2.includes(path3) || !isWrapperFile(text4) || !findBlock(text4)) continue;
|
|
29390
29183
|
writes.push({ path: path3, previous: text4, next: removeBlock(text4, boilerplateFor(path3)) });
|
|
29391
29184
|
}
|
|
29392
|
-
return { mode: "install", paths: paths2, writes,
|
|
29185
|
+
return { mode: "install", paths: paths2, writes, language };
|
|
29393
29186
|
}
|
|
29394
29187
|
async function applyAgentDocs(root, plan, recheck) {
|
|
29395
29188
|
for (const write of plan.writes) await managedWrite(root, write.path, write.previous, write.next, recheck);
|
|
@@ -29498,6 +29291,7 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
|
|
|
29498
29291
|
current2 = next;
|
|
29499
29292
|
}
|
|
29500
29293
|
await applyAgentDocs(root, docsPlan, unchanged);
|
|
29294
|
+
if (agentDocs && !(config3.cli && isNewerRelease(config3.cli, agentDocs.version))) await refreshLauncher(root);
|
|
29501
29295
|
return result(settled2.config, "already-initialized", await writeLineEndings(root));
|
|
29502
29296
|
};
|
|
29503
29297
|
const base = { schemaVersion: SCHEMA_VERSION, baseline: first.state.head.commit ? { kind: "commit", objectFormat: first.state.repository.objectFormat, commit: first.state.head.commit } : { kind: "empty" } };
|
|
@@ -29509,13 +29303,14 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
|
|
|
29509
29303
|
};
|
|
29510
29304
|
await published();
|
|
29511
29305
|
await applyAgentDocs(root, docsPlan, published);
|
|
29306
|
+
if (agentDocs) await refreshLauncher(root);
|
|
29512
29307
|
return result(config2, outcome, await writeLineEndings(root));
|
|
29513
29308
|
};
|
|
29514
29309
|
const old = await readConfigFile(root);
|
|
29515
29310
|
if (old !== void 0) return existing(old);
|
|
29516
29311
|
if (first.trackedConfig) throw new InitError("CONFIG_DELETED", t2("init.configDeleted"));
|
|
29517
29312
|
const checkRecords = async () => {
|
|
29518
|
-
const entries = await
|
|
29313
|
+
const entries = await readdir4(join13(root, ".gitifact")).catch((e) => {
|
|
29519
29314
|
if (e.code === "ENOENT") return [];
|
|
29520
29315
|
throw e;
|
|
29521
29316
|
});
|
|
@@ -29553,22 +29348,22 @@ var fetchLatestVersion = async (signal) => {
|
|
|
29553
29348
|
};
|
|
29554
29349
|
|
|
29555
29350
|
// src/adapters/filesystem/user-cache.ts
|
|
29556
|
-
import { mkdir as
|
|
29351
|
+
import { mkdir as mkdir6, readFile as readFile12, rename as rename3, unlink as unlink3, writeFile as writeFile4 } from "node:fs/promises";
|
|
29557
29352
|
import { homedir } from "node:os";
|
|
29558
|
-
import { join as
|
|
29353
|
+
import { join as join14 } from "node:path";
|
|
29559
29354
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
29560
29355
|
function userCacheDirectory(env = process.env, platform = process.platform, home = homedir()) {
|
|
29561
29356
|
if (env.GITIFACT_CACHE_DIR) return env.GITIFACT_CACHE_DIR;
|
|
29562
|
-
if (platform === "win32") return
|
|
29563
|
-
if (platform === "darwin") return
|
|
29564
|
-
return
|
|
29357
|
+
if (platform === "win32") return join14(env.LOCALAPPDATA || join14(home, "AppData", "Local"), "gitifact");
|
|
29358
|
+
if (platform === "darwin") return join14(home, "Library", "Caches", "gitifact");
|
|
29359
|
+
return join14(env.XDG_CACHE_HOME || join14(home, ".cache"), "gitifact");
|
|
29565
29360
|
}
|
|
29566
|
-
var cacheFile = (env) =>
|
|
29361
|
+
var cacheFile = (env) => join14(userCacheDirectory(env), "update.json");
|
|
29567
29362
|
var isTime = (value) => typeof value === "string" && !Number.isNaN(Date.parse(value));
|
|
29568
29363
|
async function readUpdateCache(env = process.env) {
|
|
29569
29364
|
let value;
|
|
29570
29365
|
try {
|
|
29571
|
-
value = JSON.parse(await
|
|
29366
|
+
value = JSON.parse(await readFile12(cacheFile(env), "utf8"));
|
|
29572
29367
|
} catch {
|
|
29573
29368
|
return {};
|
|
29574
29369
|
}
|
|
@@ -29583,11 +29378,11 @@ async function readUpdateCache(env = process.env) {
|
|
|
29583
29378
|
}
|
|
29584
29379
|
async function changeUpdateCache(env, change2) {
|
|
29585
29380
|
const directory = userCacheDirectory(env);
|
|
29586
|
-
const temporary =
|
|
29381
|
+
const temporary = join14(directory, "update-" + randomUUID5() + ".tmp");
|
|
29587
29382
|
try {
|
|
29588
29383
|
const next = change2(await readUpdateCache(env));
|
|
29589
|
-
await
|
|
29590
|
-
await
|
|
29384
|
+
await mkdir6(directory, { recursive: true });
|
|
29385
|
+
await writeFile4(temporary, JSON.stringify(next) + "\n", "utf8");
|
|
29591
29386
|
await rename3(temporary, cacheFile(env));
|
|
29592
29387
|
} catch {
|
|
29593
29388
|
await unlink3(temporary).catch(() => {
|
|
@@ -29616,7 +29411,7 @@ async function runInit(options, version2) {
|
|
|
29616
29411
|
await recordUpdateCheck(process.env, dto.update);
|
|
29617
29412
|
const docs = dto.agentDocs.mode === "skip" ? t2("init.text.skipped") : dto.agentDocs.paths.join(", ") + (dto.agentDocs.mode === "remove" ? " (" + t2("init.text.blockRemoved") + ")" : dto.outcome === "planned" ? " (" + t2("init.text.blockPlanned") + ")" : " (" + t2("init.text.blockUpdated") + ")");
|
|
29618
29413
|
const lineEndings = dto.lineEndings.created ? t2("init.text.lineEndings", { path: dto.lineEndings.path }) + "\n" : "";
|
|
29619
|
-
const newer = dto.install ? t2("init.text.updateAvailable", { version: dto.update.latestVersion, command: dto.install.
|
|
29414
|
+
const newer = dto.install ? t2("init.text.updateAvailable", { version: dto.update.latestVersion, command: dto.install.npx }) + "\n" : "";
|
|
29620
29415
|
process.stdout.write(options.format === "text" ? `${dto.outcome}: ${dto.rootPath}/.gitifact/config.json
|
|
29621
29416
|
${t2("init.text.storage")}: schemaVersion ${dto.schemaVersion}
|
|
29622
29417
|
${t2("init.text.agentDocs")}: ${docs}
|
|
@@ -29631,17 +29426,17 @@ ${lineEndings}${newer}` : JSON.stringify(dto) + "\n");
|
|
|
29631
29426
|
}
|
|
29632
29427
|
|
|
29633
29428
|
// src/commands/documents.ts
|
|
29634
|
-
import { readFile as
|
|
29635
|
-
import { join as
|
|
29429
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
29430
|
+
import { join as join16 } from "node:path";
|
|
29636
29431
|
|
|
29637
29432
|
// src/commands/project.ts
|
|
29638
|
-
import { join as
|
|
29433
|
+
import { join as join15 } from "node:path";
|
|
29639
29434
|
var operations = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"];
|
|
29640
29435
|
async function openProject(cwd, options = {}) {
|
|
29641
29436
|
const reader = storeReader(cwd);
|
|
29642
29437
|
const location = await reader.location();
|
|
29643
29438
|
if (options.writing) {
|
|
29644
|
-
for (const marker2 of operations) if (await fileInfo(
|
|
29439
|
+
for (const marker2 of operations) if (await fileInfo(join15(location.gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
|
|
29645
29440
|
if (await reader.hasUnmerged()) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
29646
29441
|
}
|
|
29647
29442
|
const raw = await readConfigFile(location.root);
|
|
@@ -29800,12 +29595,11 @@ var stateLabel = {
|
|
|
29800
29595
|
};
|
|
29801
29596
|
var stateMark = (state2) => state2 === "committed" ? "" : " (" + stateLabel[state2]() + ")";
|
|
29802
29597
|
var line = (doc) => `${doc.id} ${doc.title}${draftMark(doc)} \u2014 ${doc.description}`;
|
|
29803
|
-
var fileLine = (f) => f.title ? `${f.path} ${f.title} \u2014 ${f.description}` : f.path;
|
|
29804
29598
|
async function working(project) {
|
|
29805
29599
|
const { documents } = await project.cache.documents.list();
|
|
29806
29600
|
return {
|
|
29807
29601
|
byId: new Map(documents.map((d) => [d.id, d])),
|
|
29808
|
-
read: (path3) =>
|
|
29602
|
+
read: (path3) => readFile13(join16(project.root, ...path3.split("/")), "utf8"),
|
|
29809
29603
|
referencing: async (id) => [...new Set((await project.cache.documents.referencing(id)).map((r) => r.from))]
|
|
29810
29604
|
};
|
|
29811
29605
|
}
|
|
@@ -29818,12 +29612,12 @@ async function committed(project, commit) {
|
|
|
29818
29612
|
referencing: async (id) => documents.filter((d) => d.kind === "design" && (d.requirements.includes(id) || d.sources.some((s) => "id" in s && s.id === id))).map((d) => d.id)
|
|
29819
29613
|
};
|
|
29820
29614
|
}
|
|
29821
|
-
async function showDocuments(project, ids, at, kinds
|
|
29615
|
+
async function showDocuments(project, ids, at, kinds) {
|
|
29822
29616
|
const view = at === void 0 ? await working(project) : await committed(project, at);
|
|
29823
29617
|
const unknown2 = ids.filter((id) => !view.byId.has(id));
|
|
29824
29618
|
if (unknown2.length) throw new CommandError("UNKNOWN_DOCUMENT", t2("docs.unknownDocument", { ids: unknown2.join(", ") }));
|
|
29825
29619
|
const other = ids.filter((id) => !kinds.includes(view.byId.get(id).kind));
|
|
29826
|
-
if (other.length) throw new CommandError("UNKNOWN_DOCUMENT", t2("docs.
|
|
29620
|
+
if (other.length) throw new CommandError("UNKNOWN_DOCUMENT", t2("docs.unknownDocument", { ids: other.join(", ") }));
|
|
29827
29621
|
const shown = await Promise.all([...new Set(ids)].map(async (id) => {
|
|
29828
29622
|
const doc = view.byId.get(id);
|
|
29829
29623
|
const references = doc.kind === "design" ? [
|
|
@@ -29831,34 +29625,30 @@ async function showDocuments(project, ids, at, kinds, otherResource) {
|
|
|
29831
29625
|
...doc.sources.map((s) => "id" in s ? { id: s.id, title: view.byId.get(s.id)?.title ?? null } : { title: s.title, url: s.url })
|
|
29832
29626
|
] : [];
|
|
29833
29627
|
const referencedBy = (await view.referencing(id)).map((from) => ({ id: from, title: view.byId.get(from)?.title ?? null }));
|
|
29834
|
-
|
|
29835
|
-
return { id, kind: doc.kind, path: doc.path, title: doc.title, text: await view.read(doc.path), references, referencedBy, ...files };
|
|
29628
|
+
return { id, kind: doc.kind, path: doc.path, title: doc.title, text: await view.read(doc.path), references, referencedBy };
|
|
29836
29629
|
}));
|
|
29837
29630
|
const named = (r) => r.id ? r.id + " " + (r.title ?? "(" + t2("docs.missing") + ")") : r.title + " <" + r.url + ">";
|
|
29838
29631
|
const blocks = shown.map((d) => [
|
|
29839
29632
|
`== ${d.id} ${d.path}${at ? " @ " + at.slice(0, 7) : ""}`,
|
|
29840
29633
|
d.text.replace(/\n$/, ""),
|
|
29841
29634
|
...section("-- " + t2("docs.references"), d.references.map(named)),
|
|
29842
|
-
...section("-- " + t2("docs.referencedBy"), d.referencedBy.map(named))
|
|
29843
|
-
...section("-- " + t2("docs.files"), (d.files ?? []).map(fileLine))
|
|
29635
|
+
...section("-- " + t2("docs.referencedBy"), d.referencedBy.map(named))
|
|
29844
29636
|
].join("\n"));
|
|
29845
29637
|
return { json: { ...at ? { commit: at } : {}, documents: shown }, text: blocks.join("\n\n") + "\n" };
|
|
29846
29638
|
}
|
|
29847
29639
|
var pathExample = {
|
|
29848
29640
|
feature: () => t2("docs.pathExample.feature"),
|
|
29849
29641
|
requirement: () => t2("docs.pathExample.requirement"),
|
|
29850
|
-
design: () => t2("docs.pathExample.design")
|
|
29851
|
-
instruction: () => t2("docs.pathExample.instruction")
|
|
29642
|
+
design: () => t2("docs.pathExample.design")
|
|
29852
29643
|
};
|
|
29853
29644
|
var skeleton = {
|
|
29854
29645
|
feature: () => t2("docs.skeleton.feature"),
|
|
29855
29646
|
requirement: () => t2("docs.skeleton.requirement"),
|
|
29856
|
-
design: () => t2("docs.skeleton.design")
|
|
29857
|
-
instruction: () => t2("docs.skeleton.instruction")
|
|
29647
|
+
design: () => t2("docs.skeleton.design")
|
|
29858
29648
|
};
|
|
29859
29649
|
function newPath(kind2, path3) {
|
|
29860
|
-
const target = kind2 === "feature" ? `${SPEC_ROOT}/${path3}/index.md` :
|
|
29861
|
-
const shape = kind2 === "feature"
|
|
29650
|
+
const target = kind2 === "feature" ? `${SPEC_ROOT}/${path3}/index.md` : `${SPEC_ROOT}/${path3.split("/")[0]}/${kind2 === "requirement" ? "requirements" : "design"}/${path3.split("/").slice(1).join("/")}.md`;
|
|
29651
|
+
const shape = kind2 === "feature" ? /^[^/]+$/ : /^[^/]+\/[^/]+$/;
|
|
29862
29652
|
let where;
|
|
29863
29653
|
try {
|
|
29864
29654
|
where = shape.test(path3) ? classifyDocPath(target) : void 0;
|
|
@@ -29881,7 +29671,7 @@ async function createDocument(project, kind2, path3, options) {
|
|
|
29881
29671
|
const taken = new Set(documents.map((d) => d.id));
|
|
29882
29672
|
let id;
|
|
29883
29673
|
do
|
|
29884
|
-
id = generateId({ feature: "S", requirement: "R", design: "D"
|
|
29674
|
+
id = generateId({ feature: "S", requirement: "R", design: "D" }[kind2]);
|
|
29885
29675
|
while (taken.has(id));
|
|
29886
29676
|
const folder = target.slice(0, target.lastIndexOf("/") + 1);
|
|
29887
29677
|
const siblings = documents.filter((d) => (d.kind === "requirement" || d.kind === "design") && d.path.startsWith(folder) && !d.path.slice(folder.length).includes("/"));
|
|
@@ -29889,7 +29679,7 @@ async function createDocument(project, kind2, path3, options) {
|
|
|
29889
29679
|
const body2 = style2 === "usecase" ? t2("docs.skeleton.requirementUsecase") : skeleton[kind2]();
|
|
29890
29680
|
const base = { id, path: target, title: options.title.trim(), description: options.description.trim(), body: body2, draft: true };
|
|
29891
29681
|
const feature2 = target.split("/")[2];
|
|
29892
|
-
const doc = kind2 === "feature" ? { kind: kind2, feature: feature2, ...base } : kind2 === "
|
|
29682
|
+
const doc = kind2 === "feature" ? { kind: kind2, feature: feature2, ...base } : kind2 === "requirement" ? { kind: kind2, feature: feature2, order, ...styleKey, ...base } : { kind: kind2, feature: feature2, order, requirements: [], sources: [], ...base };
|
|
29893
29683
|
const rendered = renderDocumentFile(doc);
|
|
29894
29684
|
parseDocumentFile(target, rendered);
|
|
29895
29685
|
try {
|
|
@@ -29912,11 +29702,11 @@ function parseLimit(value) {
|
|
|
29912
29702
|
if (!/^[1-9]\d{0,5}$/.test(value)) throw new InvalidArgumentError(t2("list.limit"));
|
|
29913
29703
|
return Number(value);
|
|
29914
29704
|
}
|
|
29915
|
-
var parseFields = (value) => value.split(
|
|
29916
|
-
function checkFields(fields2,
|
|
29705
|
+
var parseFields = (value) => value.split(/[\s,]+/).filter(Boolean);
|
|
29706
|
+
function checkFields(fields2, columns2) {
|
|
29917
29707
|
if (!fields2) return void 0;
|
|
29918
|
-
const unknown2 = fields2.filter((f) => !
|
|
29919
|
-
if (unknown2.length || !fields2.length) throw new CommandError("INVALID_VALUE", t2("list.unknownFields", { fields: unknown2.join(", "), columns:
|
|
29708
|
+
const unknown2 = fields2.filter((f) => !columns2.includes(f));
|
|
29709
|
+
if (unknown2.length || !fields2.length) throw new CommandError("INVALID_VALUE", t2("list.unknownFields", { fields: unknown2.join(", "), columns: columns2.join(", ") }));
|
|
29920
29710
|
return [...new Set(fields2)];
|
|
29921
29711
|
}
|
|
29922
29712
|
function cell(value) {
|
|
@@ -30004,120 +29794,14 @@ var runSpecsList = (options) => runCommand("specs", options.format, async () =>
|
|
|
30004
29794
|
var runSpecsShow = (ids, options) => runCommand("specs", options.format, async () => {
|
|
30005
29795
|
const project = await openProject(process.cwd());
|
|
30006
29796
|
const at = options.ref === void 0 ? void 0 : await project.reader.resolve(options.ref);
|
|
30007
|
-
return showDocuments(project, ids, at, specKinds, "
|
|
29797
|
+
return showDocuments(project, ids, at, at === void 0 ? specKinds : [...specKinds, "instruction"]);
|
|
30008
29798
|
});
|
|
30009
29799
|
var runSpecsNew = (kind2, path3, options) => runCommand("specs", options.format, async () => createDocument(await openProject(process.cwd()), kind2, path3, options));
|
|
30010
29800
|
|
|
30011
|
-
// src/queries/instructions.ts
|
|
30012
|
-
import { lstat as lstat12 } from "node:fs/promises";
|
|
30013
|
-
import { join as join18 } from "node:path";
|
|
30014
|
-
var AGENTS = "AGENTS.md";
|
|
30015
|
-
async function listInstructions(source2, options, request) {
|
|
30016
|
-
const listed3 = await source2.cache.documents.list();
|
|
30017
|
-
const problems = listed3.problems;
|
|
30018
|
-
const states = await documentStates(source2, listed3.documents);
|
|
30019
|
-
const documents = states.documents;
|
|
30020
|
-
const agents2 = { path: AGENTS, exists: !!(await lstat12(join18(source2.root, AGENTS)).catch(() => void 0))?.isFile() };
|
|
30021
|
-
const historyNeeded = options.sort === "updated" || options.author !== void 0 || !!options.withUpdated;
|
|
30022
|
-
const latest = /* @__PURE__ */ new Map();
|
|
30023
|
-
const newest = /* @__PURE__ */ new Map();
|
|
30024
|
-
let touched;
|
|
30025
|
-
if (historyNeeded) {
|
|
30026
|
-
const head = await source2.head();
|
|
30027
|
-
const changes2 = head ? await source2.cache.history.changesOf(head) : [];
|
|
30028
|
-
changes2.forEach((c, rank) => {
|
|
30029
|
-
if (!latest.has(c.id)) {
|
|
30030
|
-
latest.set(c.id, { commit: c.commit, date: c.date, author: c.author, email: c.email });
|
|
30031
|
-
newest.set(c.id, rank);
|
|
30032
|
-
}
|
|
30033
|
-
});
|
|
30034
|
-
if (options.author !== void 0) {
|
|
30035
|
-
const by = byAuthor(options.author);
|
|
30036
|
-
touched = new Set(changes2.filter(by).map((c) => c.id));
|
|
30037
|
-
}
|
|
30038
|
-
}
|
|
30039
|
-
const matched = options.q !== void 0 ? await source2.cache.documents.matching(options.q) : void 0;
|
|
30040
|
-
const instructions2 = documents.filter((d) => d.kind === "instruction").filter((d) => (!touched || touched.has(d.id)) && (!matched || matched.has(d.id))).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
30041
|
-
const rows = await Promise.all(instructions2.map(async (d) => {
|
|
30042
|
-
const state2 = states.state(d.id);
|
|
30043
|
-
const { files, limited } = state2 === "deleted" ? { files: [], limited: false } : await readInstructionFiles(source2.root, d.path);
|
|
30044
|
-
return {
|
|
30045
|
-
id: d.id,
|
|
30046
|
-
name: d.name,
|
|
30047
|
-
path: d.path,
|
|
30048
|
-
title: d.title,
|
|
30049
|
-
description: d.description,
|
|
30050
|
-
...d.draft ? { draft: true } : {},
|
|
30051
|
-
state: state2,
|
|
30052
|
-
...states.previousPath(d.id) ? { previousPath: states.previousPath(d.id) } : {},
|
|
30053
|
-
files,
|
|
30054
|
-
...limited ? { filesLimited: true } : {},
|
|
30055
|
-
...historyNeeded ? { updated: latest.get(d.id) ?? null } : {},
|
|
30056
|
-
...matched ? { line: matched.get(d.id) } : {}
|
|
30057
|
-
};
|
|
30058
|
-
}));
|
|
30059
|
-
if (options.sort === "updated") rows.sort((a, b) => (newest.get(a.id) ?? Infinity) - (newest.get(b.id) ?? Infinity));
|
|
30060
|
-
const page = pageOf(rows, (r) => r.id, request);
|
|
30061
|
-
if (!page) return void 0;
|
|
30062
|
-
return { agents: agents2, problems, page };
|
|
30063
|
-
}
|
|
30064
|
-
|
|
30065
|
-
// src/commands/instructions.ts
|
|
30066
|
-
var instructionSorts = ["name", "updated"];
|
|
30067
|
-
var columns2 = ["id", "name", "path", "title", "description", "draft", "state", "previousPath", "files", "updated", "line"];
|
|
30068
|
-
var runInstructionsList = (options) => runCommand("instructions", options.format, async () => {
|
|
30069
|
-
const fields2 = checkFields(options.fields, columns2);
|
|
30070
|
-
const project = await openProject(process.cwd());
|
|
30071
|
-
const listed3 = await listInstructions(project, { ...options, withUpdated: !!fields2?.includes("updated") }, options) ?? cursorGone(options);
|
|
30072
|
-
const { agents: agents2, problems, page } = listed3;
|
|
30073
|
-
const shown = page.rows;
|
|
30074
|
-
const paging = { total: page.total, next: page.next, unit: "instruction" };
|
|
30075
|
-
const unreadable2 = problems.filter((p) => p.path.startsWith(INSTRUCTIONS_ROOT + "/"));
|
|
30076
|
-
if (fields2) {
|
|
30077
|
-
const picked = selected(shown, fields2);
|
|
30078
|
-
return {
|
|
30079
|
-
json: { agents: agents2, instructions: picked.json, problems: unreadable2, page: paging },
|
|
30080
|
-
text: selected(shown.map((r) => ({ ...r, files: r.files.map((f) => f.path) })), fields2).text + aside(options.format, pageLine(page))
|
|
30081
|
-
};
|
|
30082
|
-
}
|
|
30083
|
-
const out = [agents2.exists ? t2("instructions.agents") : t2("instructions.noAgents")];
|
|
30084
|
-
for (const r of shown) {
|
|
30085
|
-
const when = r.updated ? ` \xB7 ${r.updated.date.slice(0, 10)} ${r.updated.author}` : "";
|
|
30086
|
-
out.push(`${r.id} ${r.title}${draftMark(r)}${stateMark(r.state)} (${r.name}) \u2014 ${r.description}${when}`, ...r.line ? [" " + r.line] : []);
|
|
30087
|
-
out.push(...r.files.map((f) => " " + fileLine(f)), ...r.filesLimited ? [" " + t2("instructions.filesLimited", { count: r.files.length })] : []);
|
|
30088
|
-
}
|
|
30089
|
-
if (!shown.length) out.push(options.q !== void 0 || options.author !== void 0 ? t2("docs.noMatch") : t2("instructions.empty"));
|
|
30090
|
-
out.push(...pageLine(page));
|
|
30091
|
-
if (unreadable2.length) out.push(t2("docs.unreadable", { count: unreadable2.length }));
|
|
30092
|
-
return { json: { agents: agents2, instructions: shown, problems: unreadable2, page: paging }, text: text2(out) };
|
|
30093
|
-
});
|
|
30094
|
-
async function resolveInstructions(project, targets, at) {
|
|
30095
|
-
const view = at === void 0 ? await working(project) : await committed(project, at);
|
|
30096
|
-
const byName = new Map([...view.byId.values()].filter((d) => d.kind === "instruction").map((d) => [d.name, d.id]));
|
|
30097
|
-
return targets.map((target) => byName.get(target) ?? target);
|
|
30098
|
-
}
|
|
30099
|
-
var runInstructionsShow = (targets, options) => runCommand("instructions", options.format, async () => {
|
|
30100
|
-
const project = await openProject(process.cwd());
|
|
30101
|
-
if (options.file !== void 0 && (targets.length !== 1 || options.ref !== void 0)) throw new CommandError("INVALID_VALUE", t2("instructions.fileWithOne"));
|
|
30102
|
-
const at = options.ref === void 0 ? void 0 : await project.reader.resolve(options.ref);
|
|
30103
|
-
const ids = await resolveInstructions(project, targets, at);
|
|
30104
|
-
if (options.file === void 0) return showDocuments(project, ids, at, ["instruction"], "specs show");
|
|
30105
|
-
const instruction2 = (await working(project)).byId.get(ids[0]);
|
|
30106
|
-
if (instruction2?.kind !== "instruction") throw new CommandError("UNKNOWN_DOCUMENT", t2("docs.unknownDocument", { ids: targets[0] }));
|
|
30107
|
-
const found = await readInstructionFile(project.root, instruction2.path, options.file);
|
|
30108
|
-
if (!found) throw new CommandError("UNKNOWN_FILE", t2("instructions.unknownFile", { path: options.file, name: instruction2.name }));
|
|
30109
|
-
const note = found.text !== null ? [] : [found.tooLarge ? t2("instructions.fileTooLarge", { size: found.size }) : t2("instructions.fileBinary", { size: found.size })];
|
|
30110
|
-
return {
|
|
30111
|
-
json: { id: instruction2.id, name: instruction2.name, file: { path: options.file, ...found } },
|
|
30112
|
-
text: text2([`== ${instruction2.id} ${instruction2.name}/${options.file}`, ...found.text !== null ? [found.text.replace(/\n$/, "")] : note])
|
|
30113
|
-
};
|
|
30114
|
-
});
|
|
30115
|
-
var runInstructionsNew = (name2, options) => runCommand("instructions", options.format, async () => createDocument(await openProject(process.cwd()), "instruction", name2, options));
|
|
30116
|
-
|
|
30117
29801
|
// src/adapters/filesystem/document-warnings.ts
|
|
30118
|
-
import { lstat as
|
|
30119
|
-
import { join as
|
|
30120
|
-
var info2 = async (path3) =>
|
|
29802
|
+
import { lstat as lstat11, readdir as readdir5 } from "node:fs/promises";
|
|
29803
|
+
import { join as join17 } from "node:path";
|
|
29804
|
+
var info2 = async (path3) => lstat11(path3).catch((e) => {
|
|
30121
29805
|
if (e.code === "ENOENT") return void 0;
|
|
30122
29806
|
throw e;
|
|
30123
29807
|
});
|
|
@@ -30125,20 +29809,20 @@ var posix = (path3) => path3.split("\\").join("/");
|
|
|
30125
29809
|
async function listAssets(root) {
|
|
30126
29810
|
const out = [];
|
|
30127
29811
|
async function visit2(relative, depth) {
|
|
30128
|
-
const stat3 = await info2(
|
|
29812
|
+
const stat3 = await info2(join17(root, relative));
|
|
30129
29813
|
if (!stat3 || stat3.isSymbolicLink()) return;
|
|
30130
29814
|
if (stat3.isDirectory()) {
|
|
30131
29815
|
if (depth > 8 || out.length > 4e3) return;
|
|
30132
|
-
for (const name2 of (await
|
|
29816
|
+
for (const name2 of (await readdir5(join17(root, relative))).sort()) await visit2(relative + "/" + name2, depth + 1);
|
|
30133
29817
|
} else if (stat3.isFile()) out.push({ path: posix(relative), bytes: stat3.size });
|
|
30134
29818
|
}
|
|
30135
29819
|
await visit2(ASSETS_DIR, 0);
|
|
30136
29820
|
return out;
|
|
30137
29821
|
}
|
|
30138
29822
|
async function readDocumentWarnings(root, documents) {
|
|
30139
|
-
const outside = [...new Set(documentBodyLinks(documents).map((l) => l.target).filter((t3) => !t3.startsWith(".gitifact/")
|
|
29823
|
+
const outside = [...new Set(documentBodyLinks(documents).map((l) => l.target).filter((t3) => !t3.startsWith(".gitifact/")))];
|
|
30140
29824
|
const existing = /* @__PURE__ */ new Set();
|
|
30141
|
-
for (const target of outside) if ((await info2(
|
|
29825
|
+
for (const target of outside) if ((await info2(join17(root, ...target.split("/"))))?.isFile()) existing.add(target);
|
|
30142
29826
|
return documentWarnings(documents, await listAssets(root), existing);
|
|
30143
29827
|
}
|
|
30144
29828
|
|
|
@@ -30162,31 +29846,31 @@ var runCheck = (options) => runCommand("check", options.format, async () => {
|
|
|
30162
29846
|
|
|
30163
29847
|
// src/commands/changes.ts
|
|
30164
29848
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
30165
|
-
import { mkdir as
|
|
30166
|
-
import { join as
|
|
29849
|
+
import { mkdir as mkdir8, open as open4, readFile as readFile16, rename as rename4, rmdir, unlink as unlink5, writeFile as writeFile6 } from "node:fs/promises";
|
|
29850
|
+
import { join as join20 } from "node:path";
|
|
30167
29851
|
|
|
30168
29852
|
// src/adapters/filesystem/agent-inputs.ts
|
|
30169
29853
|
import { createHash as createHash4, randomBytes as randomBytes2 } from "node:crypto";
|
|
30170
|
-
import { lstat as
|
|
29854
|
+
import { lstat as lstat12, mkdir as mkdir7, readdir as readdir6, realpath as realpath3, unlink as unlink4, writeFile as writeFile5 } from "node:fs/promises";
|
|
30171
29855
|
import { tmpdir } from "node:os";
|
|
30172
|
-
import { basename, dirname as dirname2, join as
|
|
29856
|
+
import { basename, dirname as dirname2, join as join18 } from "node:path";
|
|
30173
29857
|
var maxAge = 7 * 24 * 60 * 60 * 1e3;
|
|
30174
|
-
var info3 = (path3) =>
|
|
29858
|
+
var info3 = (path3) => lstat12(path3).catch((e) => {
|
|
30175
29859
|
if (e.code === "ENOENT") return void 0;
|
|
30176
29860
|
throw e;
|
|
30177
29861
|
});
|
|
30178
29862
|
var comparable = (path3) => process.platform === "win32" ? path3.toLowerCase() : path3;
|
|
30179
29863
|
async function candidates(root, controls) {
|
|
30180
29864
|
const key = createHash4("sha256").update(comparable(await realpath3(root))).digest("hex").slice(0, 16);
|
|
30181
|
-
return { system:
|
|
29865
|
+
return { system: join18((controls.tmpdir ?? tmpdir)(), "gitifact", key), project: join18(root, ".gitifact", "tmp") };
|
|
30182
29866
|
}
|
|
30183
29867
|
async function writable(directory) {
|
|
30184
29868
|
try {
|
|
30185
|
-
await
|
|
29869
|
+
await mkdir7(directory, { recursive: true });
|
|
30186
29870
|
const stat3 = await info3(directory);
|
|
30187
29871
|
if (!stat3?.isDirectory() || stat3.isSymbolicLink()) return false;
|
|
30188
|
-
const probe =
|
|
30189
|
-
await
|
|
29872
|
+
const probe = join18(directory, ".probe-" + randomBytes2(8).toString("hex"));
|
|
29873
|
+
await writeFile5(probe, "", { flag: "wx" });
|
|
30190
29874
|
await unlink4(probe);
|
|
30191
29875
|
return true;
|
|
30192
29876
|
} catch {
|
|
@@ -30199,18 +29883,18 @@ async function prepareAgentInputs(root, controls = {}) {
|
|
|
30199
29883
|
if (await writable(system)) directory = system;
|
|
30200
29884
|
else if (await writable(project)) {
|
|
30201
29885
|
directory = project;
|
|
30202
|
-
await
|
|
29886
|
+
await writeFile5(join18(project, ".gitignore"), "*\n", { flag: "wx" }).catch((e) => {
|
|
30203
29887
|
if (e.code !== "EEXIST") throw e;
|
|
30204
29888
|
});
|
|
30205
29889
|
}
|
|
30206
29890
|
if (!directory) return void 0;
|
|
30207
29891
|
const now = (controls.now ?? Date.now)();
|
|
30208
|
-
for (const name2 of await
|
|
29892
|
+
for (const name2 of await readdir6(directory).catch(() => [])) {
|
|
30209
29893
|
if (name2 === ".gitignore") continue;
|
|
30210
|
-
const stat3 = await info3(
|
|
30211
|
-
if (stat3?.isFile() && now - stat3.mtimeMs > maxAge) await unlink4(
|
|
29894
|
+
const stat3 = await info3(join18(directory, name2)).catch(() => void 0);
|
|
29895
|
+
if (stat3?.isFile() && now - stat3.mtimeMs > maxAge) await unlink4(join18(directory, name2)).catch(() => void 0);
|
|
30212
29896
|
}
|
|
30213
|
-
return { commit:
|
|
29897
|
+
return { commit: join18(directory, "commit.json") };
|
|
30214
29898
|
}
|
|
30215
29899
|
async function discardAgentInput(root, file2, controls = {}) {
|
|
30216
29900
|
try {
|
|
@@ -30232,17 +29916,17 @@ async function discardAgentInput(root, file2, controls = {}) {
|
|
|
30232
29916
|
|
|
30233
29917
|
// src/commands/commit-files.ts
|
|
30234
29918
|
import { createHash as createHash5 } from "node:crypto";
|
|
30235
|
-
import { lstat as
|
|
30236
|
-
import { join as
|
|
29919
|
+
import { lstat as lstat13, readFile as readFile14 } from "node:fs/promises";
|
|
29920
|
+
import { join as join19 } from "node:path";
|
|
30237
29921
|
var fail3 = (message) => {
|
|
30238
29922
|
throw new CommandError("INVALID_COMMIT", message);
|
|
30239
29923
|
};
|
|
30240
29924
|
var hash2 = (value) => createHash5("sha256").update(value).digest("hex");
|
|
30241
|
-
var optional2 = (path3) =>
|
|
29925
|
+
var optional2 = (path3) => readFile14(path3).catch((e) => {
|
|
30242
29926
|
if (e.code === "ENOENT") return null;
|
|
30243
29927
|
throw e;
|
|
30244
29928
|
});
|
|
30245
|
-
var info4 = (path3) =>
|
|
29929
|
+
var info4 = (path3) => lstat13(path3).catch((e) => {
|
|
30246
29930
|
if (e.code === "ENOENT") return void 0;
|
|
30247
29931
|
throw e;
|
|
30248
29932
|
});
|
|
@@ -30254,7 +29938,7 @@ var record3 = (path3) => {
|
|
|
30254
29938
|
return false;
|
|
30255
29939
|
}
|
|
30256
29940
|
};
|
|
30257
|
-
var
|
|
29941
|
+
var instructionFile = (path3) => {
|
|
30258
29942
|
try {
|
|
30259
29943
|
return classifyDocPath(path3).type === "instruction-file";
|
|
30260
29944
|
} catch {
|
|
@@ -30268,14 +29952,14 @@ async function fingerprint(root, path3) {
|
|
|
30268
29952
|
validPath2(path3);
|
|
30269
29953
|
const parts = path3.split("/");
|
|
30270
29954
|
for (let i = 1; i <= parts.length; i++) {
|
|
30271
|
-
const target =
|
|
29955
|
+
const target = join19(root, ...parts.slice(0, i));
|
|
30272
29956
|
const stat3 = await info4(target);
|
|
30273
29957
|
if (!stat3) return null;
|
|
30274
29958
|
if (stat3.isSymbolicLink() || (i < parts.length ? !stat3.isDirectory() : !stat3.isFile())) fail3(t2("commitFiles.linkOrDirectory"));
|
|
30275
|
-
if (i < parts.length && await info4(
|
|
29959
|
+
if (i < parts.length && await info4(join19(target, ".git"))) fail3(t2("commitFiles.nestedRepository"));
|
|
30276
29960
|
if (i === parts.length) {
|
|
30277
29961
|
if (stat3.nlink !== 1 || stat3.size > 16 * 1024 * 1024) fail3(t2("commitFiles.hardLinkOrSize"));
|
|
30278
|
-
return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await
|
|
29962
|
+
return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await readFile14(target)]));
|
|
30279
29963
|
}
|
|
30280
29964
|
}
|
|
30281
29965
|
return null;
|
|
@@ -30302,16 +29986,16 @@ function policyPaths(files) {
|
|
|
30302
29986
|
}
|
|
30303
29987
|
return [...all].sort();
|
|
30304
29988
|
}
|
|
30305
|
-
var storeFiles = /* @__PURE__ */ new Set([".gitifact/config.json", LINE_ENDINGS_PATH]);
|
|
29989
|
+
var storeFiles = /* @__PURE__ */ new Set([".gitifact/config.json", LINE_ENDINGS_PATH, LAUNCHER_PATH]);
|
|
30306
29990
|
function checkStoreSelection(selected2) {
|
|
30307
29991
|
for (const p of selected2.filter((p2) => p2.startsWith(".gitifact/") && !record3(p2) && !storeFiles.has(p2))) {
|
|
30308
|
-
if (!isAssetPath(p) && !
|
|
29992
|
+
if (!isAssetPath(p) && !instructionFile(p)) fail3(t2("commitFiles.notRecord", { path: p }));
|
|
30309
29993
|
}
|
|
30310
29994
|
}
|
|
30311
29995
|
|
|
30312
29996
|
// src/commands/input.ts
|
|
30313
|
-
import { readFile as
|
|
30314
|
-
var
|
|
29997
|
+
import { readFile as readFile15, stat as stat2 } from "node:fs/promises";
|
|
29998
|
+
var LIMIT = 1024 * 1024;
|
|
30315
29999
|
async function readJsonInput(file2, stdin = process.stdin) {
|
|
30316
30000
|
const bytes = file2 === "-" ? await readStdin(stdin) : await readInputFile(file2);
|
|
30317
30001
|
try {
|
|
@@ -30322,15 +30006,15 @@ async function readJsonInput(file2, stdin = process.stdin) {
|
|
|
30322
30006
|
}
|
|
30323
30007
|
async function readInputFile(path3) {
|
|
30324
30008
|
const source2 = await stat2(path3).catch(() => void 0);
|
|
30325
|
-
if (!source2?.isFile() || source2.size >
|
|
30326
|
-
return
|
|
30009
|
+
if (!source2?.isFile() || source2.size > LIMIT) throw new CommandError("INVALID_INPUT", t2("input.file"));
|
|
30010
|
+
return readFile15(path3);
|
|
30327
30011
|
}
|
|
30328
30012
|
async function readStdin(stream) {
|
|
30329
30013
|
const chunks = [];
|
|
30330
30014
|
let size = 0;
|
|
30331
30015
|
for await (const chunk of stream) {
|
|
30332
30016
|
size += chunk.length;
|
|
30333
|
-
if (size >
|
|
30017
|
+
if (size > LIMIT) throw new CommandError("INVALID_INPUT", t2("input.size"));
|
|
30334
30018
|
chunks.push(chunk);
|
|
30335
30019
|
}
|
|
30336
30020
|
return Buffer.concat(chunks);
|
|
@@ -30340,8 +30024,8 @@ async function readStdin(stream) {
|
|
|
30340
30024
|
var fields = ["paths", "message", "authorization", "migration"];
|
|
30341
30025
|
var integration = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"];
|
|
30342
30026
|
var MIGRATION_TARGET = "0.8.0";
|
|
30343
|
-
var PATH_LIMIT =
|
|
30344
|
-
var
|
|
30027
|
+
var PATH_LIMIT = 5e3;
|
|
30028
|
+
var STORE_PATH_LIMIT = 128;
|
|
30345
30029
|
var same2 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
30346
30030
|
var problemLines2 = (problems) => problems.map((p) => " " + p.code + " " + p.message);
|
|
30347
30031
|
var underDocuments = (path3) => path3.startsWith(SPEC_ROOT + "/") || path3.startsWith(WIKI_ROOT + "/") || path3 === HISTORY_PATH;
|
|
@@ -30399,12 +30083,14 @@ var runChangesCommit = (options, controls = {}) => runCommand("changes", options
|
|
|
30399
30083
|
async function commitChanges(cwd, input2, dryRun) {
|
|
30400
30084
|
const request = object3(input2);
|
|
30401
30085
|
if (Object.keys(request).some((k) => !fields.includes(k))) fail3(t2("commit.unknownField"));
|
|
30402
|
-
const selected2 = paths(request.paths,
|
|
30086
|
+
const selected2 = paths(request.paths, PATH_LIMIT);
|
|
30403
30087
|
const authorization = object3(request.authorization);
|
|
30088
|
+
const storePaths = selected2.filter((p) => p.startsWith(".gitifact/")).length;
|
|
30089
|
+
if (request.migration !== true && storePaths > STORE_PATH_LIMIT) fail3(t2("commit.tooManyStorePaths", { count: storePaths, limit: STORE_PATH_LIMIT }));
|
|
30404
30090
|
if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis))) fail3(t2("commit.authorizationRequired"));
|
|
30405
30091
|
text3(authorization.evidence, 2e3);
|
|
30406
30092
|
const message = text3(request.message, 4e3);
|
|
30407
|
-
if (
|
|
30093
|
+
if (/^[ \t]*Gitifact-[A-Za-z0-9-]+[ \t]*:/im.test(message)) fail3(t2("commit.trailerInMessage"));
|
|
30408
30094
|
if (request.migration !== void 0 && request.migration !== true) fail3(t2("commit.migrationFlag"));
|
|
30409
30095
|
const project = await openProject(cwd, { writing: true });
|
|
30410
30096
|
const { root, gitDir, indexPath, objectFormat } = project;
|
|
@@ -30430,7 +30116,7 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30430
30116
|
...stdin ? { input: stdin } : {}
|
|
30431
30117
|
});
|
|
30432
30118
|
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();
|
|
30433
|
-
const busy =
|
|
30119
|
+
const busy = join20(gitDir, "gitifact-changes-commit.lock");
|
|
30434
30120
|
if (await info4(busy)) fail3(t2("commit.busy", { path: busy }));
|
|
30435
30121
|
if ((await staged()).length) fail3(t2("commit.existingStaging"));
|
|
30436
30122
|
const indexHash = hash2(await optional2(indexPath) ?? Buffer.alloc(0));
|
|
@@ -30470,7 +30156,7 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30470
30156
|
if (!same2(base, await project.reader.baseline())) fail3(t2("commit.headChanged"));
|
|
30471
30157
|
return { outcome: "dry-run", committed: false, ...summary, commit: void 0 };
|
|
30472
30158
|
}
|
|
30473
|
-
const temporary =
|
|
30159
|
+
const temporary = join20(gitDir, "gitifact-commit-index-" + randomUUID6());
|
|
30474
30160
|
let owned = false;
|
|
30475
30161
|
let uncertain = false;
|
|
30476
30162
|
let commitStarted = false;
|
|
@@ -30478,20 +30164,20 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30478
30164
|
let committed2;
|
|
30479
30165
|
try {
|
|
30480
30166
|
try {
|
|
30481
|
-
await
|
|
30167
|
+
await mkdir8(busy);
|
|
30482
30168
|
owned = true;
|
|
30483
30169
|
} catch (e) {
|
|
30484
30170
|
if (e.code === "EEXIST") fail3(t2("commit.busy", { path: busy }));
|
|
30485
30171
|
throw e;
|
|
30486
30172
|
}
|
|
30487
|
-
const lock = indexLock = await
|
|
30173
|
+
const lock = indexLock = await open4(indexPath + ".lock", "wx", 384);
|
|
30488
30174
|
const original = await optional2(indexPath);
|
|
30489
30175
|
if (hash2(original ?? Buffer.alloc(0)) !== indexHash || (await staged()).length) fail3(t2("commit.indexChanged"));
|
|
30490
30176
|
const before = await hashes([...started.keys()]);
|
|
30491
30177
|
for (const [path3, value] of started) if (before.get(path3) !== value) fail3(t2("commit.fileChangedRunning", { path: path3 }));
|
|
30492
|
-
await
|
|
30178
|
+
await writeFile6(join20(busy, "recovery.json"), JSON.stringify({ before: base, originalIndex: original?.toString("base64") ?? null, temporary, paths: selected2, message }));
|
|
30493
30179
|
const locked = await hashes([.../* @__PURE__ */ new Set([...selected2, ...contextPaths])]);
|
|
30494
|
-
if (original) await
|
|
30180
|
+
if (original) await writeFile6(temporary, original, { flag: "wx" });
|
|
30495
30181
|
else await git(["read-tree", "--empty"], temporary);
|
|
30496
30182
|
await git(["add", "--pathspec-from-file=-", "--pathspec-file-nul"], temporary, Buffer.from(stageable.join("\0")));
|
|
30497
30183
|
const actual = await staged(temporary);
|
|
@@ -30506,14 +30192,14 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30506
30192
|
const size = Number(header[2]);
|
|
30507
30193
|
if (end < 0 || header[1] !== "blob" || !Number.isSafeInteger(size) || output2[end + 1 + size] !== 10) fail3(t2("commit.stagedUnreadable", { path: path3 }));
|
|
30508
30194
|
const blob = output2.subarray(end + 1, end + 1 + size);
|
|
30509
|
-
const file2 = await
|
|
30195
|
+
const file2 = await readFile16(join20(root, path3));
|
|
30510
30196
|
if (!blob.equals(file2) && !blob.equals(Buffer.from(file2.toString("latin1").replace(/\r\n/g, "\n"), "latin1"))) fail3(t2("commit.filterChanged"));
|
|
30511
30197
|
offset = end + size + 2;
|
|
30512
30198
|
}
|
|
30513
30199
|
}
|
|
30514
30200
|
const again = await hashes([...locked.keys()]);
|
|
30515
30201
|
for (const [path3, value] of locked) if (again.get(path3) !== value) fail3(t2("commit.fileChangedPreparing", { path: path3 }));
|
|
30516
|
-
for (const name2 of integration) if (await info4(
|
|
30202
|
+
for (const name2 of integration) if (await info4(join20(gitDir, name2))) fail3(t2("commit.integrationStarted"));
|
|
30517
30203
|
if (!same2(base, await project.reader.baseline())) fail3(t2("commit.headChanged"));
|
|
30518
30204
|
const tree = (await git(["write-tree"], temporary)).toString("utf8").trim();
|
|
30519
30205
|
commitStarted = true;
|
|
@@ -30528,7 +30214,7 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30528
30214
|
if (headers[0] !== "tree " + tree || after.branch !== base.branch || !same2(parents, base.head ? [base.head] : []) || trailers.some((line2) => !body2.split(/\r?\n/).includes(line2))) fail3(t2("commit.resultAltered"));
|
|
30529
30215
|
if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== indexHash) fail3(t2("commit.indexChangedAfter"));
|
|
30530
30216
|
if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail3(t2("commit.hookChangedStaging"));
|
|
30531
|
-
await lock.writeFile(await
|
|
30217
|
+
await lock.writeFile(await readFile16(temporary));
|
|
30532
30218
|
await lock.sync();
|
|
30533
30219
|
await lock.close();
|
|
30534
30220
|
await rename4(indexPath + ".lock", indexPath);
|
|
@@ -30553,7 +30239,7 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30553
30239
|
await unlink5(temporary).catch(() => {
|
|
30554
30240
|
});
|
|
30555
30241
|
if (owned) {
|
|
30556
|
-
await unlink5(
|
|
30242
|
+
await unlink5(join20(busy, "recovery.json")).catch(() => {
|
|
30557
30243
|
});
|
|
30558
30244
|
await rmdir(busy);
|
|
30559
30245
|
}
|
|
@@ -30563,12 +30249,14 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30563
30249
|
}
|
|
30564
30250
|
|
|
30565
30251
|
// src/commands/records.ts
|
|
30566
|
-
import { readFile as
|
|
30567
|
-
import { join as
|
|
30252
|
+
import { readFile as readFile17 } from "node:fs/promises";
|
|
30253
|
+
import { join as join21 } from "node:path";
|
|
30568
30254
|
var runRecordsNew = (options) => runCommand("records", options.format, async () => {
|
|
30569
30255
|
if (/[\r\n]/.test(options.title)) throw new CommandError("INVALID_VALUE", t2("docs.singleLine", { field: "title" }));
|
|
30570
|
-
const docs = [...new Set(options.docs.flatMap((d) => d.split(
|
|
30571
|
-
if (!docs.length
|
|
30256
|
+
const docs = [...new Set(options.docs.flatMap((d) => d.split(/[\s,]+/)).filter(Boolean))];
|
|
30257
|
+
if (!docs.length) throw new CommandError("INVALID_VALUE", t2("records.invalidDocs"));
|
|
30258
|
+
const invalid2 = docs.filter((d) => !docIdPattern.test(d));
|
|
30259
|
+
if (invalid2.length) throw new CommandError("INVALID_VALUE", t2("records.notDocIds", { ids: invalid2.join(", ") }));
|
|
30572
30260
|
const project = await openProject(process.cwd());
|
|
30573
30261
|
let id;
|
|
30574
30262
|
do
|
|
@@ -30600,7 +30288,7 @@ var runRecordsShow = (ids, options) => runCommand("records", options.format, asy
|
|
|
30600
30288
|
const shown = await Promise.all([...new Set(ids)].map(async (id) => {
|
|
30601
30289
|
const path3 = await findRecord(project.root, id);
|
|
30602
30290
|
if (!path3) return { id, missing: true };
|
|
30603
|
-
const source2 = await
|
|
30291
|
+
const source2 = await readFile17(join21(project.root, ...path3.split("/")), "utf8");
|
|
30604
30292
|
const log = project.reader.decode(await project.reader.run(["log", "-1", "--diff-filter=A", "--format=%H%x00%aN%x00%aI", "--", path3])).trim();
|
|
30605
30293
|
const [commit, author, date5] = log.split("\0");
|
|
30606
30294
|
return { id, path: path3, text: source2, commit: commit ? { commit, author, date: date5 } : null };
|
|
@@ -30764,11 +30452,11 @@ function newIssueUrl(title, body2, marker2) {
|
|
|
30764
30452
|
}
|
|
30765
30453
|
|
|
30766
30454
|
// src/shared/project-config.ts
|
|
30767
|
-
import { readFile as
|
|
30768
|
-
import { dirname as dirname3, join as
|
|
30455
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
30456
|
+
import { dirname as dirname3, join as join22 } from "node:path";
|
|
30769
30457
|
async function findProjectConfig(from) {
|
|
30770
30458
|
for (let folder = from; ; folder = dirname3(folder)) {
|
|
30771
|
-
const text4 = await
|
|
30459
|
+
const text4 = await readFile18(join22(folder, ".gitifact", "config.json"), "utf8").catch(() => void 0);
|
|
30772
30460
|
if (text4 !== void 0) return { root: folder, text: text4 };
|
|
30773
30461
|
if (dirname3(folder) === folder) return void 0;
|
|
30774
30462
|
}
|
|
@@ -30830,8 +30518,8 @@ var runFeedback = (options, version2, run) => runCommand("feedback", options.for
|
|
|
30830
30518
|
});
|
|
30831
30519
|
|
|
30832
30520
|
// src/commands/update.ts
|
|
30833
|
-
import { readFile as
|
|
30834
|
-
import { join as
|
|
30521
|
+
import { readFile as readFile19 } from "node:fs/promises";
|
|
30522
|
+
import { join as join23 } from "node:path";
|
|
30835
30523
|
import { isDeepStrictEqual } from "node:util";
|
|
30836
30524
|
|
|
30837
30525
|
// src/adapters/git/agent-docs-commit.ts
|
|
@@ -30855,6 +30543,10 @@ function agentDocsGit(root, inherited = process.env) {
|
|
|
30855
30543
|
async commitOnly(paths2, message) {
|
|
30856
30544
|
await git(["commit", "--only", "-m", message, "--", ...paths2]);
|
|
30857
30545
|
},
|
|
30546
|
+
// A file Git does not know yet (the launcher on its first update) is marked so `--only` can take it.
|
|
30547
|
+
async intendToAdd(paths2) {
|
|
30548
|
+
await git(["add", "--intent-to-add", "--", ...paths2]);
|
|
30549
|
+
},
|
|
30858
30550
|
async changedPaths(commit) {
|
|
30859
30551
|
return (await git(["diff-tree", "--no-commit-id", "--name-only", "--no-renames", "-r", "-z", "--root", commit])).toString("utf8").split("\0").filter(Boolean).sort();
|
|
30860
30552
|
},
|
|
@@ -30868,7 +30560,7 @@ function agentDocsGit(root, inherited = process.env) {
|
|
|
30868
30560
|
var CONFIG_PATH = ".gitifact/config.json";
|
|
30869
30561
|
var updateCommitMessage = (version2) => "chore(gitifact): update project to gitifact v" + version2;
|
|
30870
30562
|
var commitState = (state2, extra = {}) => ({ state: state2, commit: null, paths: [], message: null, reason: null, detail: null, ...extra });
|
|
30871
|
-
var notInitialized = { docs: { state: "not-initialized", paths: []
|
|
30563
|
+
var notInitialized = { docs: { state: "not-initialized", paths: [] }, project: { state: "not-initialized", cli: null } };
|
|
30872
30564
|
async function refreshProject(cwd, version2, env, controls) {
|
|
30873
30565
|
const repo = initRepository(cwd, env);
|
|
30874
30566
|
let first;
|
|
@@ -30884,13 +30576,12 @@ async function refreshProject(cwd, version2, env, controls) {
|
|
|
30884
30576
|
const root = first.state.repository.rootPath;
|
|
30885
30577
|
const parsed2 = needsMigration(config2) ? void 0 : parseManagedConfig(config2);
|
|
30886
30578
|
const plan = await planAgentDocs(root, { version: version2, onlyExisting: true, language: parsed2?.language, ...controls });
|
|
30887
|
-
|
|
30888
|
-
if (parsed2?.cli && isNewerRelease(parsed2.cli, version2)) return { docs: { state: "kept", paths: plan.paths, missing: missing2, root }, project: { state: "current", cli: parsed2.cli } };
|
|
30579
|
+
if (parsed2?.cli && isNewerRelease(parsed2.cli, version2)) return { docs: { state: "kept", paths: plan.paths, root }, project: { state: "current", cli: parsed2.cli } };
|
|
30889
30580
|
let current2 = config2;
|
|
30890
30581
|
const unchanged = async () => {
|
|
30891
30582
|
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !== current2) throw new InitError("INPUT_CHANGED", t2("init.inputChanged"));
|
|
30892
30583
|
};
|
|
30893
|
-
const docs = plan.paths.length === 0 ? { state: "no-block", paths: [],
|
|
30584
|
+
const docs = plan.paths.length === 0 ? { state: "no-block", paths: [], root } : plan.writes.length === 0 ? { state: "current", paths: plan.paths, root, candidates: plan.paths } : { state: "refreshed", paths: await applyAgentDocs(root, plan, unchanged), root, candidates: plan.paths };
|
|
30894
30585
|
if (!parsed2) return { docs, project: { state: "current", cli: null } };
|
|
30895
30586
|
const settled2 = settleConfig(parsed2, version2, plan.language);
|
|
30896
30587
|
if (settled2.changed) {
|
|
@@ -30898,6 +30589,7 @@ async function refreshProject(cwd, version2, env, controls) {
|
|
|
30898
30589
|
await publishConfig(root, next, unchanged, void 0, true);
|
|
30899
30590
|
current2 = next;
|
|
30900
30591
|
}
|
|
30592
|
+
await refreshLauncher(root);
|
|
30901
30593
|
return { docs: { ...docs, root }, project: { state: settled2.changed ? "written" : "current", cli: settled2.config.cli ?? null } };
|
|
30902
30594
|
}
|
|
30903
30595
|
function outsideBlock(text4) {
|
|
@@ -30932,7 +30624,7 @@ async function commitUpdate(docs, version2, env) {
|
|
|
30932
30624
|
if (before === null || before !== outsideBlock(working2)) return commitState("skipped", { paths: [path3], reason: "other-changes" });
|
|
30933
30625
|
changed.push(path3);
|
|
30934
30626
|
}
|
|
30935
|
-
const workingConfig = await
|
|
30627
|
+
const workingConfig = await readFile19(join23(docs.root, CONFIG_PATH), "utf8").catch(() => null);
|
|
30936
30628
|
const committedConfig = head ? await git.committed(head, CONFIG_PATH) : null;
|
|
30937
30629
|
if (workingConfig !== null && committedConfig?.replace(/\r\n/g, "\n") !== workingConfig.replace(/\r\n/g, "\n")) {
|
|
30938
30630
|
if (committedConfig === null) return commitState("skipped", { paths: [CONFIG_PATH], reason: "untracked" });
|
|
@@ -30940,10 +30632,14 @@ async function commitUpdate(docs, version2, env) {
|
|
|
30940
30632
|
if (before === null || !isDeepStrictEqual(before, withoutSettings(workingConfig))) return commitState("skipped", { paths: [CONFIG_PATH], reason: "other-changes" });
|
|
30941
30633
|
changed.push(CONFIG_PATH);
|
|
30942
30634
|
}
|
|
30635
|
+
const workingLauncher = await readFile19(join23(docs.root, ...LAUNCHER_PATH.split("/")), "utf8").catch(() => null);
|
|
30636
|
+
const committedLauncher = head ? await git.committed(head, LAUNCHER_PATH) : null;
|
|
30637
|
+
if (workingLauncher !== null && committedLauncher?.replace(/\r\n/g, "\n") !== workingLauncher.replace(/\r\n/g, "\n")) changed.push(LAUNCHER_PATH);
|
|
30943
30638
|
if (changed.length === 0) return commitState("nothing");
|
|
30944
30639
|
const message = updateCommitMessage(version2);
|
|
30945
30640
|
let failure2;
|
|
30946
30641
|
try {
|
|
30642
|
+
if (workingLauncher !== null && committedLauncher === null) await git.intendToAdd([LAUNCHER_PATH]);
|
|
30947
30643
|
await git.commitOnly(changed, message);
|
|
30948
30644
|
} catch (error62) {
|
|
30949
30645
|
failure2 = error62;
|
|
@@ -30970,7 +30666,8 @@ async function updateCommand(cwd, version2, env = process.env, controls = {}) {
|
|
|
30970
30666
|
cliVersion: version2,
|
|
30971
30667
|
update,
|
|
30972
30668
|
install: update.status === "available" ? { npmGlobal: npmGlobalInstall(update.latestVersion) } : null,
|
|
30973
|
-
|
|
30669
|
+
// missing stays in the v6 result but is always empty since 0.9.0: init no longer adds a CLAUDE.md.
|
|
30670
|
+
agentDocs: { state: docs.state, paths: docs.paths, missing: [] },
|
|
30974
30671
|
project,
|
|
30975
30672
|
commit,
|
|
30976
30673
|
migrationRequired: config2 !== void 0 && needsMigration(config2)
|
|
@@ -30986,11 +30683,10 @@ async function runUpdate(options, version2) {
|
|
|
30986
30683
|
}
|
|
30987
30684
|
const lines2 = [t2("update.text.current", { version: dto.cliVersion })];
|
|
30988
30685
|
lines2.push(dto.update.status === "available" ? t2("update.text.available", { version: dto.update.latestVersion }) : dto.update.status === "up-to-date" ? t2("update.text.upToDate") : dto.update.status === "disabled" ? t2("update.text.disabled") : t2("update.text.unavailable"));
|
|
30989
|
-
if (dto.install) lines2.push(t2("update.text.install", { command: dto.
|
|
30686
|
+
if (dto.install) lines2.push(t2("update.text.install", { command: npxUpdate(dto.update.latestVersion) }), t2("update.text.afterInstall"));
|
|
30990
30687
|
lines2.push(dto.agentDocs.state === "refreshed" ? t2("update.text.blockRefreshed", { paths: dto.agentDocs.paths.join(", ") }) : dto.agentDocs.state === "current" ? t2("update.text.blockCurrent", { paths: dto.agentDocs.paths.join(", ") }) : dto.agentDocs.state === "kept" ? t2("update.text.blockKept", { paths: dto.agentDocs.paths.join(", ") || "-" }) : dto.agentDocs.state === "no-block" ? t2("update.text.noBlock") : t2("update.text.notInitialized"));
|
|
30991
|
-
if (dto.agentDocs.missing.length) lines2.push(t2("update.text.missing", { paths: dto.agentDocs.missing.join(", ") }));
|
|
30992
30688
|
if (dto.project.state === "written") lines2.push(t2("update.text.projectWritten", { path: CONFIG_PATH, version: dto.project.cli ?? dto.cliVersion }));
|
|
30993
|
-
if (dto.project.cli && isNewerRelease(dto.project.cli, dto.cliVersion)) lines2.push(t2("update.text.projectAhead", { project: dto.project.cli, version: dto.cliVersion
|
|
30689
|
+
if (dto.project.cli && isNewerRelease(dto.project.cli, dto.cliVersion)) lines2.push(t2("update.text.projectAhead", { project: dto.project.cli, version: dto.cliVersion }));
|
|
30994
30690
|
if (dto.migrationRequired) lines2.push(t2("update.text.migrationRequired", { version: dto.cliVersion }));
|
|
30995
30691
|
const { commit } = dto;
|
|
30996
30692
|
if (commit.state === "committed") lines2.push(t2("update.text.committed", { commit: commit.commit.slice(0, 12), paths: commit.paths.join(", ") }));
|
|
@@ -31033,7 +30729,7 @@ async function runUpdateCheck(format2, version2) {
|
|
|
31033
30729
|
t2("update.text.current", { version: dto.cliVersion }),
|
|
31034
30730
|
state2.status === "available" ? t2("update.text.available", { version: state2.latestVersion }) : state2.status === "up-to-date" ? t2("update.text.upToDate") : state2.status === "disabled" ? t2("update.text.disabled") : t2("update.text.unavailable")
|
|
31035
30731
|
];
|
|
31036
|
-
if (state2.status === "available") lines2.push(t2("update.text.install", { command:
|
|
30732
|
+
if (state2.status === "available") lines2.push(t2("update.text.install", { command: npxUpdate(state2.latestVersion) }), t2("update.text.afterInstall"));
|
|
31037
30733
|
process.stdout.write(lines2.join("\n") + "\n");
|
|
31038
30734
|
}
|
|
31039
30735
|
|
|
@@ -31054,8 +30750,8 @@ function chooseNotice(running2, project, cache, now, scope = { release: true, pr
|
|
|
31054
30750
|
return null;
|
|
31055
30751
|
}
|
|
31056
30752
|
function noticeText(notice, running2) {
|
|
31057
|
-
if (notice.kind === "project-newer") return t2("notice.projectNewer", { project: notice.project, version: running2
|
|
31058
|
-
if (notice.kind === "release") return t2("notice.release", { latest: notice.latest, version: running2, command:
|
|
30753
|
+
if (notice.kind === "project-newer") return t2("notice.projectNewer", { project: notice.project, version: running2 });
|
|
30754
|
+
if (notice.kind === "release") return t2("notice.release", { latest: notice.latest, version: running2, command: npxUpdate(notice.latest) });
|
|
31059
30755
|
return t2("notice.projectOlder", { project: notice.project, version: running2 });
|
|
31060
30756
|
}
|
|
31061
30757
|
var needsRefresh = (cache, now) => !(cache.checkedAt && now - Date.parse(cache.checkedAt) < REFRESH_AFTER_MS) && !(cache.checkingSince && now - Date.parse(cache.checkingSince) < CHECKING_WINDOW_MS);
|
|
@@ -31109,17 +30805,17 @@ for (let i = 0; i < languageArgs.length; i++) {
|
|
|
31109
30805
|
if (value === "ko" || value === "en") selectedLanguage = value;
|
|
31110
30806
|
}
|
|
31111
30807
|
configureLanguage(selectedLanguage ?? environmentLanguage(), selectedLanguage);
|
|
31112
|
-
var program2 = new Command().name("gitifact").addOption(new Option("--lang <language>", t2("help.lang")).choices(["ko", "en"])).description(t2("help.program")).version("0.
|
|
30808
|
+
var program2 = new Command().name("gitifact").addOption(new Option("--lang <language>", t2("help.lang")).choices(["ko", "en"])).description(t2("help.program")).version("0.9.1").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
|
|
31113
30809
|
program2.hook("preAction", async (_program, action) => {
|
|
31114
30810
|
let top = action;
|
|
31115
30811
|
while (top.parent && top.parent !== program2) top = top.parent;
|
|
31116
|
-
if (top.name() !== REFRESH_COMMAND) await noticeVersion("0.
|
|
30812
|
+
if (top.name() !== REFRESH_COMMAND) await noticeVersion("0.9.1", top.name());
|
|
31117
30813
|
});
|
|
31118
|
-
program2.command(REFRESH_COMMAND, { hidden: true }).allowExcessArguments(false).action(() => refreshUpdateCache("0.
|
|
30814
|
+
program2.command(REFRESH_COMMAND, { hidden: true }).allowExcessArguments(false).action(() => refreshUpdateCache("0.9.1"));
|
|
31119
30815
|
var format = () => new Option("--format <format>", t2("help.format")).choices(formats).default("text");
|
|
31120
|
-
program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).action((options) => runBrowser(options, "0.
|
|
31121
|
-
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.
|
|
31122
|
-
program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).option("--commit", t2("help.updateCommit")).addOption(new Option("--check", t2("help.updateCheck")).conflicts("commit")).addOption(new Option("--later", t2("help.updateLater")).conflicts(["check", "commit"])).action((options) => options.later ? runUpdateLater(options.format, "0.
|
|
30816
|
+
program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).action((options) => runBrowser(options, "0.9.1"));
|
|
30817
|
+
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.9.1"));
|
|
30818
|
+
program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).option("--commit", t2("help.updateCommit")).addOption(new Option("--check", t2("help.updateCheck")).conflicts("commit")).addOption(new Option("--later", t2("help.updateLater")).conflicts(["check", "commit"])).action((options) => options.later ? runUpdateLater(options.format, "0.9.1") : options.check ? runUpdateCheck(options.format, "0.9.1") : runUpdate(options, "0.9.1"));
|
|
31123
30819
|
var listed2 = (command, sorts) => {
|
|
31124
30820
|
command.allowExcessArguments(false).option("--q <words>", t2("help.listQ")).option("--author <name>", t2("help.listAuthor"));
|
|
31125
30821
|
if (sorts) command.addOption(new Option("--sort <key>", t2("help.listSort")).choices([...sorts]).default(sorts[0]));
|
|
@@ -31129,10 +30825,6 @@ var specs = program2.command("specs").description(t2("help.specs"));
|
|
|
31129
30825
|
listed2(specs.command("list").description(t2("help.specsList")).addOption(new Option("--type <kind>", t2("help.specsListType")).choices([...specKinds])).option("--feature <folder>", t2("help.specsListFeature")).option("--without-design", t2("help.specsListWithoutDesign")).option("--uncovered", t2("help.specsListUncovered")).option("--draft", t2("help.specsListDraft")).option("--changed-since <date|commit>", t2("help.specsListChangedSince")), specSorts).action((o) => runSpecsList(o));
|
|
31130
30826
|
specs.command("show").description(t2("help.specsShow")).argument("<ids...>", t2("help.specsShowIds")).option("--ref <commit>", t2("help.showRef")).addOption(format()).action((ids, o) => runSpecsShow(ids, o));
|
|
31131
30827
|
specs.command("new").description(t2("help.specsNew")).allowExcessArguments(false).addArgument(new Argument("<kind>", t2("help.specsNewKind")).choices(specKinds)).argument("<path>", t2("help.specsNewPath")).requiredOption("--title <title>", t2("help.newTitle")).requiredOption("--description <text>", t2("help.newDescription")).addOption(new Option("--style <style>", t2("help.specsNewStyle")).choices(specStyles)).addOption(format()).action((kind2, path3, o) => runSpecsNew(kind2, path3, o));
|
|
31132
|
-
var instructions = program2.command("instructions").description(t2("help.instructions"));
|
|
31133
|
-
listed2(instructions.command("list").description(t2("help.instructionsList")), instructionSorts).action((o) => runInstructionsList(o));
|
|
31134
|
-
instructions.command("show").description(t2("help.instructionsShow")).argument("<targets...>", t2("help.instructionsShowTargets")).option("--ref <commit>", t2("help.showRef")).option("--file <path>", t2("help.instructionsShowFile")).addOption(format()).action((targets, o) => runInstructionsShow(targets, o));
|
|
31135
|
-
instructions.command("new").description(t2("help.instructionsNew")).allowExcessArguments(false).argument("<name>", t2("help.instructionsNewName")).requiredOption("--title <title>", t2("help.newTitle")).requiredOption("--description <text>", t2("help.newDescription")).addOption(format()).action((name2, o) => runInstructionsNew(name2, o));
|
|
31136
30828
|
var records = program2.command("records").description(t2("help.records"));
|
|
31137
30829
|
listed2(records.command("list").description(t2("help.recordsList")).option("--doc <id>", t2("help.recordsListDoc")).option("--since <date|commit>", t2("help.recordsListSince"))).action((o) => runRecordsList(o));
|
|
31138
30830
|
records.command("show").description(t2("help.recordsShow")).argument("<ids...>", t2("help.recordsShowId")).addOption(format()).action((ids, o) => runRecordsShow(ids, o));
|
|
@@ -31141,7 +30833,7 @@ program2.command("check").description(t2("help.check")).allowExcessArguments(fal
|
|
|
31141
30833
|
var changes = program2.command("changes").description(t2("help.changes"));
|
|
31142
30834
|
changes.command("list").description(t2("help.changesList")).allowExcessArguments(false).addOption(format()).action((o) => runChangesList(o));
|
|
31143
30835
|
changes.command("commit").description(t2("help.changesCommit")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.changesCommitFile")).option("--dry-run", t2("help.changesCommitDryRun")).addOption(format()).action((o) => runChangesCommit(o));
|
|
31144
|
-
program2.command("feedback").description(t2("help.feedback")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.feedbackFile")).option("--dry-run", t2("help.feedbackDryRun")).addOption(format()).action((o) => runFeedback(o, "0.
|
|
30836
|
+
program2.command("feedback").description(t2("help.feedback")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.feedbackFile")).option("--dry-run", t2("help.feedbackDryRun")).addOption(format()).action((o) => runFeedback(o, "0.9.1"));
|
|
31145
30837
|
var guide = program2.command("guide").description(t2("help.guide"));
|
|
31146
30838
|
guide.command("list").description(t2("help.guideList")).allowExcessArguments(false).addOption(format()).action((o) => runGuideList(o));
|
|
31147
30839
|
guide.command("show").description(t2("help.guideShow")).argument("<topic>", t2("help.guideTopic")).allowExcessArguments(false).addOption(format()).action((topic, o) => runGuideShow(topic, o));
|