gitifact 0.8.2 → 0.8.4
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 +47 -37
- package/dist/THIRD_PARTY_NOTICES.txt +26 -0
- package/dist/browser/assets/HgiRefresh-CAJ0Xdvi.js +1 -0
- package/dist/browser/assets/{Markdown-B9QJ2Ao-.js → Markdown-ev4hMr67.js} +1 -1
- package/dist/browser/assets/Selector-CGOdL2eo.js +2 -0
- package/dist/browser/assets/Tab-BwJj0rUr.js +1 -0
- package/dist/browser/assets/{Table-LdzcI4YS.js → Table-XuC9zK9w.js} +2 -2
- package/dist/browser/assets/Token-BV_4bSkY.js +2 -0
- package/dist/browser/assets/Token-Bqkc8eyB.css +1 -0
- package/dist/browser/assets/about-vlKWfG7J.js +3 -0
- package/dist/browser/assets/activity-timeline-Dmc-97N6.js +2 -0
- package/dist/browser/assets/{appearance-DgDbwXAm.js → appearance-DyJA06C4.js} +1 -1
- package/dist/browser/assets/changelog-6QcNKW8u.js +1 -0
- package/dist/browser/assets/commit-BcdbBdP4.js +4 -0
- package/dist/browser/assets/contributor-Bs3RWHQv.js +1 -0
- package/dist/browser/assets/contributors-B_bVSY4J.js +1 -0
- package/dist/browser/assets/contributors._email-BR9sLgCs.js +1 -0
- package/dist/browser/assets/contributors.index-FoYwG7VE.js +1 -0
- package/dist/browser/assets/dashboard.index-BFp6Hqsf.js +1 -0
- package/dist/browser/assets/document-Cmx0e6kz.css +1 -0
- package/dist/browser/assets/document-DPtVyR5y.js +19 -0
- package/dist/browser/assets/document-Q3lvgyX8.js +2 -0
- package/dist/browser/assets/features-CmvypKgf.js +2 -0
- package/dist/browser/assets/features-DUHxz0_L.css +1 -0
- package/dist/browser/assets/features._featureId-xxpihTEs.js +1 -0
- package/dist/browser/assets/features.index-CO7APsrh.js +1 -0
- package/dist/browser/assets/getting-started-11zYPwlJ.js +1 -0
- package/dist/browser/assets/git-CVY8qpaV.js +1 -0
- package/dist/browser/assets/index-BeeP8ZFW.js +49 -0
- package/dist/browser/assets/index-D1JeDnJc.css +1 -0
- package/dist/browser/assets/instructions-D3-EfbZG.js +1 -0
- package/dist/browser/assets/instructions._instructionId-Bp9u9xx9.js +1 -0
- package/dist/browser/assets/instructions.agents-DvFHo8x8.js +1 -0
- package/dist/browser/assets/instructions.index-zHzGHq7D.js +1 -0
- package/dist/browser/assets/lazyRouteComponent-D4lq6X5s.js +1 -0
- package/dist/browser/assets/load-more-CymfxLt7.js +1 -0
- package/dist/browser/assets/lottie_light-DSIvQuvH.js +2 -0
- package/dist/browser/assets/page-header-CVCjLFQo.js +246 -0
- package/dist/browser/assets/{search-palette-CDmYAo36.css → page-header-DTEyUWBS.css} +1 -1
- package/dist/browser/assets/records._recordId-Be8aM0F-.js +1 -0
- package/dist/browser/assets/records.commits._commit-Dm3gX-bQ.js +1 -0
- package/dist/browser/assets/records.index-BgfJnGAl.js +1 -0
- package/dist/browser/assets/records.working-Eeag2L5N.js +1 -0
- package/dist/browser/assets/rocket-loader-CMSP4Jri.js +1 -0
- package/dist/browser/assets/settings-BNIy3TaP.js +1 -0
- package/dist/browser/assets/useInfiniteQuery-03AIcFvA.js +1 -0
- package/dist/browser/assets/useKeyboardHint-DN1hAi8g.js +1 -0
- package/dist/browser/index.html +34 -13
- package/dist/browser/licenses/rocket-in-space-lottie.txt +29 -0
- package/dist/i18n/en/block.md +4 -6
- package/dist/i18n/en/changelog.md +24 -0
- package/dist/i18n/en/docs/commit.md +1 -1
- package/dist/i18n/en/docs/workflow.md +7 -7
- package/dist/i18n/ko/block.md +4 -6
- package/dist/i18n/ko/changelog.md +24 -0
- package/dist/i18n/ko/docs/commit.md +1 -1
- package/dist/i18n/ko/docs/workflow.md +5 -5
- package/dist/main.js +411 -150
- package/package.json +1 -1
- package/dist/browser/assets/Banner-DQ1G6Jkv.js +0 -1
- package/dist/browser/assets/Selector-BlDYK5Fb.js +0 -2
- package/dist/browser/assets/Tab-BoCyIuQw.js +0 -1
- package/dist/browser/assets/Token-CYBSUyAu.js +0 -1
- package/dist/browser/assets/about-ClxCgIMf.js +0 -3
- package/dist/browser/assets/activity-timeline-i0lmNZ1o.js +0 -2
- package/dist/browser/assets/changelog-CxmMo2wk.css +0 -1
- package/dist/browser/assets/changelog-bGtJx397.js +0 -2
- package/dist/browser/assets/commit-5TIiQrYh.js +0 -4
- package/dist/browser/assets/contributor-C1R6Q471.js +0 -1
- package/dist/browser/assets/contributors-DjNETDIr.js +0 -1
- package/dist/browser/assets/contributors._email-DXxCGNZx.js +0 -1
- package/dist/browser/assets/contributors.index-ByVvGuYC.js +0 -1
- package/dist/browser/assets/dashboard-CMSj2wu3.css +0 -1
- package/dist/browser/assets/dashboard.index-RoAwRn4H.js +0 -1
- package/dist/browser/assets/document-BwoITy_-.js +0 -2
- package/dist/browser/assets/document-CwA2dxtP.js +0 -19
- package/dist/browser/assets/document-DEGaf2yT.css +0 -1
- package/dist/browser/assets/features-CttwIYBf.js +0 -2
- package/dist/browser/assets/features-ZYCEDoiE.css +0 -1
- package/dist/browser/assets/features._featureId-DPctVYNz.js +0 -1
- package/dist/browser/assets/features.index-lcNtlMn8.js +0 -1
- package/dist/browser/assets/getting-started-Chwezama.js +0 -1
- package/dist/browser/assets/git-CtsTwkaq.js +0 -1
- package/dist/browser/assets/git-D_wcK2vC.css +0 -1
- package/dist/browser/assets/index-CmU7dwFQ.css +0 -1
- package/dist/browser/assets/index-iSt1IRzY.js +0 -48
- package/dist/browser/assets/instructions-DULmclHB.js +0 -1
- package/dist/browser/assets/instructions._instructionId-CBz40hpF.js +0 -1
- package/dist/browser/assets/instructions.agents-CDpXylSu.js +0 -1
- package/dist/browser/assets/instructions.index-BZ5tCMZJ.js +0 -1
- package/dist/browser/assets/lazyRouteComponent-DhTs_UEV.js +0 -1
- package/dist/browser/assets/load-more-DxscRoh6.js +0 -1
- package/dist/browser/assets/page-header-B9LQWl7J.js +0 -1
- package/dist/browser/assets/page-header-atX8Nsmd.css +0 -1
- package/dist/browser/assets/records-Dk3shbYl.css +0 -1
- package/dist/browser/assets/records-page-B4tDip2H.css +0 -1
- package/dist/browser/assets/records-page-BjyFUmMr.js +0 -1
- package/dist/browser/assets/records._recordId-vwjWdPRX.js +0 -1
- package/dist/browser/assets/records.commits._commit-CYYgrOxv.js +0 -1
- package/dist/browser/assets/records.index-N49ep6ay.js +0 -1
- package/dist/browser/assets/records.working-CcYY8eyI.js +0 -1
- package/dist/browser/assets/request-state-BeiYxf95.js +0 -1
- package/dist/browser/assets/search-palette-BCEUlRVv.js +0 -561
- package/dist/browser/assets/settings-I5Mn86wq.js +0 -1
- package/dist/browser/assets/useInfiniteQuery-tqfloUvn.js +0 -1
- package/dist/browser/assets/useKeyboardHint-HHpn4XUs.js +0 -1
package/dist/main.js
CHANGED
|
@@ -3407,6 +3407,8 @@ var messages_default = {
|
|
|
3407
3407
|
"config.invalidFields": "\uD504\uB85C\uC81D\uD2B8 \uC124\uC815\uC758 \uD544\uB4DC\uB098 \uAC12\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
3408
3408
|
"config.jsonUnreadableShort": "\uC124\uC815 JSON\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
3409
3409
|
"config.schemaFields": "schemaVersion\uACFC baseline \uC124\uC815 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
3410
|
+
"config.cliVersion": "\uC124\uC815\uC758 cli\uB294 0.8.3 \uAC19\uC740 \uBC30\uD3EC \uBC84\uC804\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
3411
|
+
"config.language": "\uC124\uC815\uC758 language\uB294 {languages} \uC911 \uD558\uB098\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
3410
3412
|
"document.pathTooLong": "\uC704\uD0A4 \uD398\uC774\uC9C0 \uACBD\uB85C \uAE4A\uC774 \uB610\uB294 \uAE38\uC774 \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4: {path}",
|
|
3411
3413
|
"document.fileName": "\uC704\uD0A4 \uD398\uC774\uC9C0 \uD30C\uC77C \uC774\uB984\uC740 \uC18C\uBB38\uC790\xB7\uC22B\uC790\xB7\uD558\uC774\uD508\uACFC .md\uC5EC\uC57C \uD569\uB2C8\uB2E4(\uB8E8\uD2B8\uC758 README.md\xB7ARCHITECTURE.md \uAC19\uC740 \uB300\uBB38\uC790 \uC774\uB984 \uC608\uC678): {path}",
|
|
3412
3414
|
"document.folderName": "\uC704\uD0A4 \uD3F4\uB354 \uC774\uB984\uC740 \uC18C\uBB38\uC790\xB7\uC22B\uC790\xB7\uD558\uC774\uD508\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: {path}",
|
|
@@ -3524,6 +3526,8 @@ var messages_default2 = {
|
|
|
3524
3526
|
"config.invalidFields": "Invalid project configuration fields or values.",
|
|
3525
3527
|
"config.jsonUnreadableShort": "Could not read configuration JSON.",
|
|
3526
3528
|
"config.schemaFields": "Check the schemaVersion and baseline fields.",
|
|
3529
|
+
"config.cliVersion": "The config field cli must be a release version such as 0.8.3.",
|
|
3530
|
+
"config.language": "The config field language must be one of {languages}.",
|
|
3527
3531
|
"document.pathTooLong": "Wiki page path exceeds the depth or length limit: {path}",
|
|
3528
3532
|
"document.fileName": "Wiki filenames must use lowercase letters, digits, hyphens and .md; uppercase root names such as README.md and ARCHITECTURE.md are allowed: {path}",
|
|
3529
3533
|
"document.folderName": "Wiki folder names must use lowercase letters, digits and hyphens: {path}",
|
|
@@ -3682,6 +3686,8 @@ var InitError = class extends Error {
|
|
|
3682
3686
|
};
|
|
3683
3687
|
var SCHEMA_VERSION = 3;
|
|
3684
3688
|
var PREVIOUS_SCHEMA_VERSION = 2;
|
|
3689
|
+
var PROJECT_LANGUAGES = ["ko", "en"];
|
|
3690
|
+
var CLI_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
3685
3691
|
var object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3686
3692
|
var keys = (value, expected) => Object.keys(value).sort().join(",") === expected.sort().join(",");
|
|
3687
3693
|
function parseBaseline(value) {
|
|
@@ -3714,7 +3720,7 @@ function parseManagedConfig(text4) {
|
|
|
3714
3720
|
}
|
|
3715
3721
|
if (!object(value) || !("schemaVersion" in value))
|
|
3716
3722
|
throw new InitError("UNSUPPORTED_FORMAT", t("config.unsupportedFormat"));
|
|
3717
|
-
if (!
|
|
3723
|
+
if (!("baseline" in value))
|
|
3718
3724
|
throw new InitError("INVALID_CONFIG", t("config.schemaFields"));
|
|
3719
3725
|
if (value.schemaVersion !== SCHEMA_VERSION) {
|
|
3720
3726
|
const found = value.schemaVersion;
|
|
@@ -3723,7 +3729,35 @@ function parseManagedConfig(text4) {
|
|
|
3723
3729
|
throw new InitError("UNSUPPORTED_SCHEMA", t("config.migrationRequired"));
|
|
3724
3730
|
throw new InitError("UNSUPPORTED_SCHEMA", newer ? t("config.newerSchema", { version: String(found) }) : t("config.unsupportedSchema", { version: String(found) }));
|
|
3725
3731
|
}
|
|
3726
|
-
|
|
3732
|
+
const config2 = { schemaVersion: SCHEMA_VERSION, baseline: parseBaseline(value.baseline) };
|
|
3733
|
+
if ("cli" in value) {
|
|
3734
|
+
if (typeof value.cli !== "string" || !CLI_VERSION_PATTERN.test(value.cli))
|
|
3735
|
+
throw new InitError("INVALID_CONFIG", t("config.cliVersion"));
|
|
3736
|
+
config2.cli = value.cli;
|
|
3737
|
+
}
|
|
3738
|
+
if ("language" in value) {
|
|
3739
|
+
if (!PROJECT_LANGUAGES.includes(value.language))
|
|
3740
|
+
throw new InitError("INVALID_CONFIG", t("config.language", { languages: PROJECT_LANGUAGES.join(", ") }));
|
|
3741
|
+
config2.language = value.language;
|
|
3742
|
+
}
|
|
3743
|
+
return config2;
|
|
3744
|
+
}
|
|
3745
|
+
function formatManagedConfig(config2, previous) {
|
|
3746
|
+
let unknown2 = {};
|
|
3747
|
+
if (previous !== void 0) {
|
|
3748
|
+
const value = JSON.parse(previous);
|
|
3749
|
+
if (object(value)) {
|
|
3750
|
+
const { schemaVersion: _s, baseline: _b, cli: _c, language: _l, ...rest } = value;
|
|
3751
|
+
unknown2 = rest;
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
const known = {
|
|
3755
|
+
schemaVersion: config2.schemaVersion,
|
|
3756
|
+
baseline: config2.baseline,
|
|
3757
|
+
...config2.cli === void 0 ? {} : { cli: config2.cli },
|
|
3758
|
+
...config2.language === void 0 ? {} : { language: config2.language }
|
|
3759
|
+
};
|
|
3760
|
+
return JSON.stringify({ ...known, ...unknown2 }, null, 2) + "\n";
|
|
3727
3761
|
}
|
|
3728
3762
|
|
|
3729
3763
|
// ../../packages/core/dist/formats/links.js
|
|
@@ -25400,9 +25434,9 @@ var projectInitV8 = external_exports.discriminatedUnion("ok", [
|
|
|
25400
25434
|
external_exports.strictObject({ contract: external_exports.literal("project-init"), version: external_exports.literal(8), ok: external_exports.literal(false), error: external_exports.strictObject({ code: external_exports.string(), message: external_exports.string() }) })
|
|
25401
25435
|
]);
|
|
25402
25436
|
|
|
25403
|
-
// ../../packages/contracts/dist/versions/update-
|
|
25437
|
+
// ../../packages/contracts/dist/versions/update-v6.js
|
|
25404
25438
|
var commitReason = external_exports.enum(["untracked", "other-changes", "commit-failed"]);
|
|
25405
|
-
var
|
|
25439
|
+
var updateCommit = external_exports.strictObject({
|
|
25406
25440
|
state: external_exports.enum(["not-requested", "nothing", "committed", "skipped"]),
|
|
25407
25441
|
commit: external_exports.string().nullable(),
|
|
25408
25442
|
paths: external_exports.array(external_exports.string()),
|
|
@@ -25410,27 +25444,40 @@ var agentDocsCommit = external_exports.strictObject({
|
|
|
25410
25444
|
reason: commitReason.nullable(),
|
|
25411
25445
|
detail: external_exports.string().nullable()
|
|
25412
25446
|
}).refine((value) => value.state === "committed" === (value.commit !== null) && value.state === "skipped" === (value.reason !== null), "commit is set exactly when committed, reason exactly when skipped.");
|
|
25413
|
-
var
|
|
25447
|
+
var updateV6 = external_exports.discriminatedUnion("ok", [
|
|
25414
25448
|
external_exports.strictObject({
|
|
25415
25449
|
contract: external_exports.literal("update"),
|
|
25416
|
-
version: external_exports.literal(
|
|
25450
|
+
version: external_exports.literal(6),
|
|
25417
25451
|
ok: external_exports.literal(true),
|
|
25418
25452
|
cliVersion: external_exports.string().min(1),
|
|
25419
25453
|
update: updateStateV1,
|
|
25420
|
-
// Present only when a newer release exists
|
|
25421
|
-
install: external_exports.strictObject({
|
|
25422
|
-
// refreshed: blocks whose
|
|
25454
|
+
// Present only when a newer release exists; after installing it, `gitifact update` sets the project to it.
|
|
25455
|
+
install: external_exports.strictObject({ npmGlobal: external_exports.string().min(1) }).nullable(),
|
|
25456
|
+
// refreshed: blocks whose text differed were rewritten. current: every block already matched. kept: the project is on a
|
|
25457
|
+
// release newer than this CLI, so its blocks were left as they are.
|
|
25423
25458
|
// not-initialized: no .gitifact config here, so only the version check ran. no-block: no file carries a block.
|
|
25424
25459
|
// missing: files `gitifact init` would add and update does not create, e.g. CLAUDE.md when only AGENTS.md has the block.
|
|
25425
|
-
agentDocs: external_exports.strictObject({ state: external_exports.enum(["refreshed", "current", "not-initialized", "no-block"]), paths: external_exports.array(external_exports.string()), missing: external_exports.array(external_exports.string()) }),
|
|
25426
|
-
|
|
25460
|
+
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()) }),
|
|
25461
|
+
// written: .gitifact/config.json now names this release as `cli` and the block language. current: it already did.
|
|
25462
|
+
// cli is the project's release afterwards; one newer than cliVersion was kept, since an older CLI does not lower it.
|
|
25463
|
+
project: external_exports.strictObject({ state: external_exports.enum(["written", "current", "not-initialized"]), cli: external_exports.string().min(1).nullable() }),
|
|
25464
|
+
commit: updateCommit,
|
|
25427
25465
|
// The project still uses the 0.7 storage convention (schemaVersion 2): the blocks now describe commands that will refuse it
|
|
25428
25466
|
// until the documents are moved with `gitifact guide show migrate`.
|
|
25429
25467
|
migrationRequired: external_exports.boolean()
|
|
25430
25468
|
}),
|
|
25431
|
-
external_exports.strictObject({ contract: external_exports.literal("update"), version: external_exports.literal(
|
|
25469
|
+
external_exports.strictObject({ contract: external_exports.literal("update"), version: external_exports.literal(6), ok: external_exports.literal(false), error: external_exports.strictObject({ code: external_exports.string(), message: external_exports.string() }) })
|
|
25432
25470
|
]);
|
|
25433
25471
|
|
|
25472
|
+
// ../../packages/contracts/dist/versions/update-later-v1.js
|
|
25473
|
+
var updateLaterV1 = external_exports.strictObject({
|
|
25474
|
+
contract: external_exports.literal("update-later"),
|
|
25475
|
+
version: external_exports.literal(1),
|
|
25476
|
+
ok: external_exports.literal(true),
|
|
25477
|
+
cliVersion: external_exports.string().min(1),
|
|
25478
|
+
later: external_exports.strictObject({ version: external_exports.string().min(1), until: external_exports.iso.datetime() }).nullable()
|
|
25479
|
+
});
|
|
25480
|
+
|
|
25434
25481
|
// ../../packages/contracts/dist/versions/browser-session-v3.js
|
|
25435
25482
|
var browserSessionV3 = external_exports.strictObject({
|
|
25436
25483
|
contract: external_exports.literal("browser-session"),
|
|
@@ -25631,7 +25678,7 @@ var messages_default3 = {
|
|
|
25631
25678
|
"init.text.storage": "\uC800\uC7A5 \uADDC\uC57D",
|
|
25632
25679
|
"init.text.agentDocs": "\uC5D0\uC774\uC804\uD2B8 \uC9C0\uCE68",
|
|
25633
25680
|
"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.",
|
|
25634
|
-
"init.text.updateAvailable": "\uC0C8 \uBC84\uC804 {version}\uC774 \uC788\uC2B5\uB2C8\uB2E4. {command}\uB85C \
|
|
25681
|
+
"init.text.updateAvailable": "\uC0C8 \uBC84\uC804 {version}\uC774 \uC788\uC2B5\uB2C8\uB2E4. {command}\uB85C \uC124\uCE58\uD55C \uB4A4 gitifact update\uB85C \uD504\uB85C\uC81D\uD2B8\uB97C \uC0C8 \uBC84\uC804\uC5D0 \uB9DE\uCD94\uC138\uC694.",
|
|
25635
25682
|
"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.",
|
|
25636
25683
|
"config.storeNotDirectory": ".gitifact\uB294 \uB9C1\uD06C\uAC00 \uC544\uB2CC \uC77C\uBC18 \uB514\uB809\uD130\uB9AC\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
25637
25684
|
"config.fileShape": "config.json\uC740 64 KiB \uC774\uD558\uC758 \uC77C\uBC18 \uD30C\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
@@ -25666,13 +25713,13 @@ var messages_default3 = {
|
|
|
25666
25713
|
"update.text.upToDate": "\uCD5C\uC2E0 \uBC84\uC804\uC744 \uC0AC\uC6A9 \uC911\uC785\uB2C8\uB2E4.",
|
|
25667
25714
|
"update.text.disabled": "\uC0C8 \uBC84\uC804 \uD655\uC778\uC774 \uAEBC\uC838 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
25668
25715
|
"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.",
|
|
25669
|
-
"update.text.install": "\
|
|
25670
|
-
"update.text.afterInstall": "\
|
|
25716
|
+
"update.text.install": "\uC124\uCE58 \uBA85\uB839: {command}",
|
|
25717
|
+
"update.text.afterInstall": "\uC124\uCE58\uD55C \uB4A4 gitifact update\uB97C \uB2E4\uC2DC \uC2E4\uD589\uD558\uBA74 \uD504\uB85C\uC81D\uD2B8 \uAE30\uC900\uACFC \uC9C0\uCE68\uC774 \uC0C8 \uBC84\uC804\uC73C\uB85C \uBC14\uB01D\uB2C8\uB2E4. \uBE0C\uB77C\uC6B0\uC800\uB3C4 \uC0C8 \uBC84\uC804\uC73C\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
25671
25718
|
"update.text.blockRefreshed": "\uC9C0\uCE68 \uBE14\uB85D \uAC31\uC2E0: {paths}",
|
|
25672
25719
|
"update.text.blockCurrent": "\uC9C0\uCE68 \uBE14\uB85D\uC740 \uC774\uBBF8 \uD604\uC7AC \uBC84\uC804\uC785\uB2C8\uB2E4: {paths}",
|
|
25673
|
-
"update.text.noBlock": "GITIFACT \uBE14\uB85D\uC774 \uC788\uB294 \uC9C0\uCE68 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.
|
|
25720
|
+
"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.",
|
|
25674
25721
|
"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.",
|
|
25675
|
-
"update.text.missing": "{paths} \uD30C\uC77C\uC774 \uC5C6\uC5B4 Claude Code\uAC00 AGENTS.md\uC758 \uC9C0\uCE68\uC744 \uC77D\uC9C0 \uBABB\uD569\uB2C8\uB2E4.
|
|
25722
|
+
"update.text.missing": "{paths} \uD30C\uC77C\uC774 \uC5C6\uC5B4 Claude Code\uAC00 AGENTS.md\uC758 \uC9C0\uCE68\uC744 \uC77D\uC9C0 \uBABB\uD569\uB2C8\uB2E4. gitifact init\uC744 \uB2E4\uC2DC \uC2E4\uD589\uD558\uBA74 AGENTS.md\uB97C \uAC00\uC838\uC624\uB294 \uD30C\uC77C\uC744 \uB9CC\uB4ED\uB2C8\uB2E4.",
|
|
25676
25723
|
"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.",
|
|
25677
25724
|
"update.text.committed": "\uC9C0\uCE68 \uBE14\uB85D \uCEE4\uBC0B: {commit} ({paths})",
|
|
25678
25725
|
"update.text.commitNothing": "\uCEE4\uBC0B\uD560 \uC9C0\uCE68 \uBE14\uB85D \uBCC0\uACBD\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
@@ -25684,7 +25731,7 @@ var messages_default3 = {
|
|
|
25684
25731
|
"server.assetNotFound": "\uC5D0\uC14B\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25685
25732
|
"help.lang": "\uCD9C\uB825 \uC5B8\uC5B4 (ko \uB610\uB294 en)",
|
|
25686
25733
|
"help.updateCheck": "\uD30C\uC77C\uC744 \uBC14\uAFB8\uC9C0 \uC54A\uACE0 \uC0C8 \uBC84\uC804\uB9CC \uD655\uC778",
|
|
25687
|
-
"commitFiles.notRecord": ".gitifact \uC548\uC5D0\uC11C\uB294 \uAE30\uB85D\xB7\uC124\uC815\xB7\uC5D0\uC14B\uB9CC \uCEE4\uBC0B\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4: {path}",
|
|
25734
|
+
"commitFiles.notRecord": ".gitifact \uC548\uC5D0\uC11C\uB294 \uAE30\uB85D\xB7\uC124\uC815(config.json\xB7.gitattributes)\xB7\uC5D0\uC14B\uB9CC \uCEE4\uBC0B\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4: {path}",
|
|
25688
25735
|
"help.changes": "\uCEE4\uBC0B\uD558\uC9C0 \uC54A\uC740 \uBB38\uC11C \uBCC0\uACBD \uC870\uD68C\uC640 \uCEE4\uBC0B",
|
|
25689
25736
|
"help.changesList": "HEAD \uB300\uBE44 \uBC14\uB010 \uBB38\uC11C, \uCEE4\uBC0B\uD558\uC9C0 \uC54A\uC740 \uACB0\uC815\uAE30\uB85D, \uAE30\uB85D\uC774 \uC5C6\uB294 \uBCC0\uACBD, \uCEE4\uBC0B \uC785\uB825 \uD30C\uC77C \uACBD\uB85C",
|
|
25690
25737
|
"help.changesCommit": "check\uC640 \uAC19\uC740 \uAC80\uC0AC \uB4A4 \uC120\uD0DD\uD55C \uD30C\uC77C\uACFC \uACB0\uC815\uAE30\uB85D\uC744 \uCEE4\uBC0B",
|
|
@@ -25837,7 +25884,16 @@ var messages_default3 = {
|
|
|
25837
25884
|
"feedback.openUrl": "gh\uB97C \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC544\uB798 \uC8FC\uC18C\uB97C \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uC5B4 \uC774\uC288\uB97C \uC81C\uCD9C\uD558\uC138\uC694.",
|
|
25838
25885
|
"feedback.ghFailed": "gh\uB85C \uC774\uC288\uB97C \uB9CC\uB4E4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC544\uB798 \uC8FC\uC18C\uB97C \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uC5B4 \uC774\uC288\uB97C \uC81C\uCD9C\uD558\uC138\uC694.",
|
|
25839
25886
|
"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.",
|
|
25840
|
-
"feedback.title": "\uC81C\uBAA9: {title}"
|
|
25887
|
+
"feedback.title": "\uC81C\uBAA9: {title}",
|
|
25888
|
+
"update.text.projectWritten": "{path}\uC758 \uD504\uB85C\uC81D\uD2B8 \uAE30\uC900\uC744 gitifact {version}\uC73C\uB85C \uC801\uC5C8\uC2B5\uB2C8\uB2E4.",
|
|
25889
|
+
"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. {command}\uB85C \uC62C\uB9AC\uC138\uC694.",
|
|
25890
|
+
"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.",
|
|
25891
|
+
"update.later.nothing": "\uBBF8\uB8F0 \uC0C8 \uBC84\uC804 \uC548\uB0B4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(\uC9C0\uAE08 {version}).",
|
|
25892
|
+
"notice.release": "\uC0C8 \uBC84\uC804 {latest}\uAC00 \uC788\uC2B5\uB2C8\uB2E4(\uC9C0\uAE08 {version}). \uC5C5\uB370\uC774\uD2B8: {command} \uD6C4 gitifact update \xB7 \uB098\uC911\uC5D0: gitifact update --later",
|
|
25893
|
+
"notice.projectNewer": "\uC774 \uD504\uB85C\uC81D\uD2B8\uB294 gitifact {project} \uAE30\uC900\uC785\uB2C8\uB2E4(\uC2E4\uD589 \uC911 {version}). {command}\uB85C \uC62C\uB9AC\uC138\uC694.",
|
|
25894
|
+
"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.",
|
|
25895
|
+
"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",
|
|
25896
|
+
"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}"
|
|
25841
25897
|
};
|
|
25842
25898
|
|
|
25843
25899
|
// src/shared/i18n/en/messages.json
|
|
@@ -25936,7 +25992,7 @@ var messages_default4 = {
|
|
|
25936
25992
|
"init.text.storage": "Storage convention",
|
|
25937
25993
|
"init.text.agentDocs": "Agent instructions",
|
|
25938
25994
|
"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.",
|
|
25939
|
-
"init.text.updateAvailable": "Version {version} is available.
|
|
25995
|
+
"init.text.updateAvailable": "Version {version} is available. Install it with {command}, then run gitifact update to move the project to it.",
|
|
25940
25996
|
"init.failed": "Initialization failed. Check file permissions and the generated configuration and temporary files.",
|
|
25941
25997
|
"config.storeNotDirectory": ".gitifact must be a regular directory, not a link.",
|
|
25942
25998
|
"config.fileShape": "config.json must be a regular file no larger than 64 KiB.",
|
|
@@ -25971,13 +26027,13 @@ var messages_default4 = {
|
|
|
25971
26027
|
"update.text.upToDate": "You are using the latest version.",
|
|
25972
26028
|
"update.text.disabled": "Update checks are disabled.",
|
|
25973
26029
|
"update.text.unavailable": "Could not check for updates. Check your network connection.",
|
|
25974
|
-
"update.text.install": "
|
|
25975
|
-
"update.text.afterInstall": "
|
|
26030
|
+
"update.text.install": "Install command: {command}",
|
|
26031
|
+
"update.text.afterInstall": "After installing, run gitifact update again to move the project and its instructions to the new version. Restart the browser with the new version too.",
|
|
25976
26032
|
"update.text.blockRefreshed": "Instruction blocks refreshed: {paths}",
|
|
25977
26033
|
"update.text.blockCurrent": "Instruction blocks are already current: {paths}",
|
|
25978
|
-
"update.text.noBlock": "No instruction files contain a GITIFACT block. Run
|
|
26034
|
+
"update.text.noBlock": "No instruction files contain a GITIFACT block. Run gitifact init to install one.",
|
|
25979
26035
|
"update.text.notInitialized": "Only the version was checked because this project is not initialized.",
|
|
25980
|
-
"update.text.missing": "{paths} is missing, so Claude Code cannot load the AGENTS.md instructions. Rerun
|
|
26036
|
+
"update.text.missing": "{paths} is missing, so Claude Code cannot load the AGENTS.md instructions. Rerun gitifact init to create the import file.",
|
|
25981
26037
|
"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.",
|
|
25982
26038
|
"update.text.committed": "Instruction blocks committed: {commit} ({paths})",
|
|
25983
26039
|
"update.text.commitNothing": "No instruction block changes to commit.",
|
|
@@ -25989,7 +26045,7 @@ var messages_default4 = {
|
|
|
25989
26045
|
"server.assetNotFound": "Asset not found.",
|
|
25990
26046
|
"help.lang": "Output language (ko or en)",
|
|
25991
26047
|
"help.updateCheck": "Check for a newer version without changing files",
|
|
25992
|
-
"commitFiles.notRecord": "Inside .gitifact only records, the configuration and assets can be committed: {path}",
|
|
26048
|
+
"commitFiles.notRecord": "Inside .gitifact only records, the configuration (config.json, .gitattributes) and assets can be committed: {path}",
|
|
25993
26049
|
"help.changes": "Inspect and commit uncommitted document changes",
|
|
25994
26050
|
"help.changesList": "Documents changed since HEAD, uncommitted records, changes without a record, and the commit input path",
|
|
25995
26051
|
"help.changesCommit": "Check like the check command, then commit the selected files and records",
|
|
@@ -26142,7 +26198,16 @@ var messages_default4 = {
|
|
|
26142
26198
|
"feedback.openUrl": "gh is not available. Open the address below in a browser and submit the issue.",
|
|
26143
26199
|
"feedback.ghFailed": "gh could not create the issue. Open the address below in a browser and submit the issue.",
|
|
26144
26200
|
"feedback.truncated": "The body is long, so the address holds only its beginning. Paste the full body below into the page.",
|
|
26145
|
-
"feedback.title": "Title: {title}"
|
|
26201
|
+
"feedback.title": "Title: {title}",
|
|
26202
|
+
"update.text.projectWritten": "Set the project to gitifact {version} in {path}.",
|
|
26203
|
+
"update.text.projectAhead": "The project is set to gitifact {project}. This CLI ({version}) is older, so it was not lowered. Install it with {command}.",
|
|
26204
|
+
"update.later.postponed": "The notice for {latest} is quiet until {until}. A newer release is announced right away.",
|
|
26205
|
+
"update.later.nothing": "No newer release to postpone (running {version}).",
|
|
26206
|
+
"notice.release": "Version {latest} is available (running {version}). Update: {command}, then gitifact update \xB7 Later: gitifact update --later",
|
|
26207
|
+
"notice.projectNewer": "This project is set to gitifact {project} (running {version}). Install it with {command}.",
|
|
26208
|
+
"notice.projectOlder": "This CLI ({version}) is newer than the project ({project}). Run gitifact update to move the project to it.",
|
|
26209
|
+
"help.updateLater": "Quiet the announced newer release for 24 hours; a release newer than it is announced right away",
|
|
26210
|
+
"update.text.blockKept": "The project is set to a newer release than this CLI, so the instruction blocks were left as they are: {paths}"
|
|
26146
26211
|
};
|
|
26147
26212
|
|
|
26148
26213
|
// src/shared/i18n/index.ts
|
|
@@ -28982,15 +29047,15 @@ function boilerplateFor(path3) {
|
|
|
28982
29047
|
return "# " + name2 + "\n\nProject-specific guidance for AI coding agents.\n";
|
|
28983
29048
|
}
|
|
28984
29049
|
var readBundledBlock = (lang) => readFile12(new URL("./i18n/" + lang + "/block.md", import.meta.url), "utf8");
|
|
28985
|
-
async function renderAgentBlock(
|
|
29050
|
+
async function renderAgentBlock(controls = {}, lang = getLanguage()) {
|
|
28986
29051
|
const body2 = await (controls.readBlock ?? readBundledBlock)(lang);
|
|
28987
|
-
|
|
28988
|
-
return AGENT_START + "\n" + filled + "\n" + AGENT_END;
|
|
29052
|
+
return AGENT_START + "\n" + body2.trimEnd().replace(/\{topics\}/g, guideTopics.join(", ")) + "\n" + AGENT_END;
|
|
28989
29053
|
}
|
|
28990
|
-
function
|
|
28991
|
-
const match = /^gitifact v
|
|
28992
|
-
if (!match) return
|
|
28993
|
-
|
|
29054
|
+
function legacyBlockLanguage(text4) {
|
|
29055
|
+
const match = /^gitifact v\S+(?: · ([a-z][a-z-]*))? · .*schemaVersion \d+$/m.exec(text4);
|
|
29056
|
+
if (!match) return void 0;
|
|
29057
|
+
const language = match[1] ?? "ko";
|
|
29058
|
+
return language === "ko" || language === "en" ? language : void 0;
|
|
28994
29059
|
}
|
|
28995
29060
|
function findBlock(text4) {
|
|
28996
29061
|
const start = text4.indexOf(AGENT_START);
|
|
@@ -29052,14 +29117,26 @@ function removeBlock(text4, boilerplate) {
|
|
|
29052
29117
|
}
|
|
29053
29118
|
|
|
29054
29119
|
// src/commands/agent-docs.ts
|
|
29055
|
-
var skippedAgentDocs = { mode: "skip", paths: [], writes: [], missing: [] };
|
|
29120
|
+
var skippedAgentDocs = (language = explicitLanguage() ?? getLanguage()) => ({ mode: "skip", paths: [], writes: [], missing: [], language });
|
|
29121
|
+
var blockOf = (text4) => {
|
|
29122
|
+
try {
|
|
29123
|
+
const found = findBlock(text4);
|
|
29124
|
+
return found ? text4.slice(found.start, found.end) : void 0;
|
|
29125
|
+
} catch {
|
|
29126
|
+
return void 0;
|
|
29127
|
+
}
|
|
29128
|
+
};
|
|
29056
29129
|
async function planAgentDocs(root, options) {
|
|
29057
|
-
if (options.skip) return skippedAgentDocs;
|
|
29130
|
+
if (options.skip) return skippedAgentDocs(explicitLanguage() ?? options.language ?? getLanguage());
|
|
29058
29131
|
const existing = /* @__PURE__ */ new Map();
|
|
29059
29132
|
for (const path3 of candidatePaths) {
|
|
29060
29133
|
const text4 = await managedRead(root, path3);
|
|
29061
29134
|
if (text4 !== null) existing.set(path3, text4);
|
|
29062
29135
|
}
|
|
29136
|
+
const language = explicitLanguage() ?? options.language ?? [...existing.values()].map((text4) => {
|
|
29137
|
+
const block2 = blockOf(text4);
|
|
29138
|
+
return block2 === void 0 ? void 0 : legacyBlockLanguage(block2);
|
|
29139
|
+
}).find(Boolean) ?? getLanguage();
|
|
29063
29140
|
const writes = [];
|
|
29064
29141
|
const paths2 = [];
|
|
29065
29142
|
if (options.remove) {
|
|
@@ -29075,19 +29152,14 @@ async function planAgentDocs(root, options) {
|
|
|
29075
29152
|
paths2.push(CLAUDE_WRAPPER_PATH);
|
|
29076
29153
|
writes.push({ path: CLAUDE_WRAPPER_PATH, previous: wrapper, next: null });
|
|
29077
29154
|
}
|
|
29078
|
-
return { mode: "remove", paths: paths2, writes, missing: [] };
|
|
29155
|
+
return { mode: "remove", paths: paths2, writes, missing: [], language };
|
|
29079
29156
|
}
|
|
29080
|
-
|
|
29081
|
-
const blockFor = async (
|
|
29082
|
-
const stored = previous ? parseAgentBlock(previous)?.language : void 0;
|
|
29083
|
-
const language = explicitLanguage() ?? (stored === "ko" || stored === "en" ? stored : getLanguage());
|
|
29084
|
-
if (!blocks.has(language)) blocks.set(language, await renderAgentBlock(options.version, options, language));
|
|
29085
|
-
return blocks.get(language);
|
|
29086
|
-
};
|
|
29157
|
+
let block;
|
|
29158
|
+
const blockFor = async () => block ??= await renderAgentBlock(options, language);
|
|
29087
29159
|
const { inject, create } = options.onlyExisting ? { inject: candidatePaths.filter((path3) => existing.has(path3) && findBlock(existing.get(path3)) && !isWrapperFile(existing.get(path3))), create: null } : resolveAgentPaths(options.agent, existing);
|
|
29088
29160
|
for (const path3 of inject) {
|
|
29089
29161
|
const previous = existing.get(path3);
|
|
29090
|
-
const next = injectBlock(previous, await blockFor(
|
|
29162
|
+
const next = injectBlock(previous, await blockFor(), boilerplateFor(path3));
|
|
29091
29163
|
paths2.push(path3);
|
|
29092
29164
|
if (next !== previous) writes.push({ path: path3, previous, next });
|
|
29093
29165
|
}
|
|
@@ -29107,7 +29179,7 @@ async function planAgentDocs(root, options) {
|
|
|
29107
29179
|
if (paths2.includes(path3) || !isWrapperFile(text4) || !findBlock(text4)) continue;
|
|
29108
29180
|
writes.push({ path: path3, previous: text4, next: removeBlock(text4, boilerplateFor(path3)) });
|
|
29109
29181
|
}
|
|
29110
|
-
return { mode: "install", paths: paths2, writes, missing: missing2 };
|
|
29182
|
+
return { mode: "install", paths: paths2, writes, missing: missing2, language };
|
|
29111
29183
|
}
|
|
29112
29184
|
async function applyAgentDocs(root, plan, recheck) {
|
|
29113
29185
|
for (const write of plan.writes) await managedWrite(root, write.path, write.previous, write.next, recheck);
|
|
@@ -29156,12 +29228,32 @@ async function resolveUpdate(current2, fetchLatest, signal, timeoutMs = updateCh
|
|
|
29156
29228
|
var npmGlobalInstall = (version2) => "npm install -g gitifact@" + version2;
|
|
29157
29229
|
var npxUpdate = (version2) => "npx --yes gitifact@" + version2 + " update";
|
|
29158
29230
|
|
|
29231
|
+
// src/commands/project-settings.ts
|
|
29232
|
+
function settleConfig(config2, version2, language) {
|
|
29233
|
+
const cli = !CLI_VERSION_PATTERN.test(version2) || config2.cli !== void 0 && !isNewerRelease(version2, config2.cli) ? config2.cli : version2;
|
|
29234
|
+
const next = { ...config2, ...cli === void 0 ? {} : { cli }, language };
|
|
29235
|
+
return { config: next, changed: next.cli !== config2.cli || next.language !== config2.language };
|
|
29236
|
+
}
|
|
29237
|
+
function projectSettings(text4) {
|
|
29238
|
+
if (text4 === void 0) return {};
|
|
29239
|
+
try {
|
|
29240
|
+
const value = JSON.parse(text4);
|
|
29241
|
+
return {
|
|
29242
|
+
...typeof value.cli === "string" && CLI_VERSION_PATTERN.test(value.cli) ? { cli: value.cli } : {},
|
|
29243
|
+
...value.language === "ko" || value.language === "en" ? { language: value.language } : {}
|
|
29244
|
+
};
|
|
29245
|
+
} catch {
|
|
29246
|
+
return {};
|
|
29247
|
+
}
|
|
29248
|
+
}
|
|
29249
|
+
|
|
29159
29250
|
// src/commands/spec-init.ts
|
|
29160
29251
|
async function initializeSpecProject(cwd, dryRun = false, env = process.env, beforePublish, agentDocs, update = disabledUpdate) {
|
|
29161
29252
|
const repo = initRepository(cwd, env);
|
|
29162
29253
|
const first = await repo.inspect();
|
|
29163
29254
|
const root = first.state.repository.rootPath;
|
|
29164
|
-
const
|
|
29255
|
+
const language = projectSettings(await readConfigFile(root).catch(() => void 0)).language;
|
|
29256
|
+
let docsPlan = agentDocs ? await planAgentDocs(root, { ...agentDocs, language }) : skippedAgentDocs(language);
|
|
29165
29257
|
const result = async (config3, outcome, lineEndings = false) => {
|
|
29166
29258
|
const checked = await update;
|
|
29167
29259
|
return projectInitV8.parse({
|
|
@@ -29182,16 +29274,25 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
|
|
|
29182
29274
|
const existing = async (text5) => {
|
|
29183
29275
|
const config3 = parseManagedConfig(text5);
|
|
29184
29276
|
await repo.validateBaseline(config3, root, first.state.head.commit, first.state.repository.objectFormat);
|
|
29277
|
+
let current2 = text5;
|
|
29185
29278
|
const unchanged = async () => {
|
|
29186
|
-
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !==
|
|
29279
|
+
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !== current2) throw new InitError("INPUT_CHANGED", t2("init.inputChanged"));
|
|
29187
29280
|
};
|
|
29188
29281
|
await unchanged();
|
|
29282
|
+
if (agentDocs && config3.cli && isNewerRelease(config3.cli, agentDocs.version) && docsPlan.mode === "install") docsPlan = skippedAgentDocs(docsPlan.language);
|
|
29189
29283
|
if (dryRun) return result(config3, "already-initialized");
|
|
29284
|
+
const settled2 = agentDocs ? settleConfig(config3, agentDocs.version, docsPlan.language) : { config: config3, changed: false };
|
|
29285
|
+
if (settled2.changed) {
|
|
29286
|
+
const next = formatManagedConfig(settled2.config, text5);
|
|
29287
|
+
await publishConfig(root, next, unchanged, void 0, true);
|
|
29288
|
+
current2 = next;
|
|
29289
|
+
}
|
|
29190
29290
|
await applyAgentDocs(root, docsPlan, unchanged);
|
|
29191
|
-
return result(
|
|
29291
|
+
return result(settled2.config, "already-initialized", await writeLineEndings(root));
|
|
29192
29292
|
};
|
|
29193
|
-
const
|
|
29194
|
-
const
|
|
29293
|
+
const base = { schemaVersion: SCHEMA_VERSION, baseline: first.state.head.commit ? { kind: "commit", objectFormat: first.state.repository.objectFormat, commit: first.state.head.commit } : { kind: "empty" } };
|
|
29294
|
+
const config2 = agentDocs ? settleConfig(base, agentDocs.version, docsPlan.language).config : base;
|
|
29295
|
+
const text4 = formatManagedConfig(config2);
|
|
29195
29296
|
const finish = async (outcome) => {
|
|
29196
29297
|
const published = async () => {
|
|
29197
29298
|
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !== text4) throw new InitError("INPUT_CHANGED_AFTER_WRITE", t2("init.changedAfterWrite"));
|
|
@@ -29241,6 +29342,53 @@ var fetchLatestVersion = async (signal) => {
|
|
|
29241
29342
|
return latest;
|
|
29242
29343
|
};
|
|
29243
29344
|
|
|
29345
|
+
// src/adapters/filesystem/user-cache.ts
|
|
29346
|
+
import { mkdir as mkdir5, readFile as readFile13, rename as rename3, unlink as unlink3, writeFile as writeFile3 } from "node:fs/promises";
|
|
29347
|
+
import { homedir } from "node:os";
|
|
29348
|
+
import { join as join15 } from "node:path";
|
|
29349
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
29350
|
+
function userCacheDirectory(env = process.env, platform = process.platform, home = homedir()) {
|
|
29351
|
+
if (env.GITIFACT_CACHE_DIR) return env.GITIFACT_CACHE_DIR;
|
|
29352
|
+
if (platform === "win32") return join15(env.LOCALAPPDATA || join15(home, "AppData", "Local"), "gitifact");
|
|
29353
|
+
if (platform === "darwin") return join15(home, "Library", "Caches", "gitifact");
|
|
29354
|
+
return join15(env.XDG_CACHE_HOME || join15(home, ".cache"), "gitifact");
|
|
29355
|
+
}
|
|
29356
|
+
var cacheFile = (env) => join15(userCacheDirectory(env), "update.json");
|
|
29357
|
+
var isTime = (value) => typeof value === "string" && !Number.isNaN(Date.parse(value));
|
|
29358
|
+
async function readUpdateCache(env = process.env) {
|
|
29359
|
+
let value;
|
|
29360
|
+
try {
|
|
29361
|
+
value = JSON.parse(await readFile13(cacheFile(env), "utf8"));
|
|
29362
|
+
} catch {
|
|
29363
|
+
return {};
|
|
29364
|
+
}
|
|
29365
|
+
if (typeof value !== "object" || value === null) return {};
|
|
29366
|
+
const later = value.later;
|
|
29367
|
+
return {
|
|
29368
|
+
...isTime(value.checkedAt) ? { checkedAt: value.checkedAt } : {},
|
|
29369
|
+
...typeof value.latest === "string" ? { latest: value.latest } : {},
|
|
29370
|
+
...isTime(value.checkingSince) ? { checkingSince: value.checkingSince } : {},
|
|
29371
|
+
...later && typeof later.version === "string" && isTime(later.until) ? { later: { version: later.version, until: later.until } } : {}
|
|
29372
|
+
};
|
|
29373
|
+
}
|
|
29374
|
+
async function changeUpdateCache(env, change2) {
|
|
29375
|
+
const directory = userCacheDirectory(env);
|
|
29376
|
+
const temporary = join15(directory, "update-" + randomUUID5() + ".tmp");
|
|
29377
|
+
try {
|
|
29378
|
+
const next = change2(await readUpdateCache(env));
|
|
29379
|
+
await mkdir5(directory, { recursive: true });
|
|
29380
|
+
await writeFile3(temporary, JSON.stringify(next) + "\n", "utf8");
|
|
29381
|
+
await rename3(temporary, cacheFile(env));
|
|
29382
|
+
} catch {
|
|
29383
|
+
await unlink3(temporary).catch(() => {
|
|
29384
|
+
});
|
|
29385
|
+
}
|
|
29386
|
+
}
|
|
29387
|
+
async function recordUpdateCheck(env, update, now = Date.now()) {
|
|
29388
|
+
if (update.status === "disabled" || update.status === "checking") return;
|
|
29389
|
+
await changeUpdateCache(env, ({ checkingSince: _done, ...cache }) => ({ ...cache, checkedAt: new Date(now).toISOString(), ...update.latestVersion ? { latest: update.latestVersion } : {} }));
|
|
29390
|
+
}
|
|
29391
|
+
|
|
29244
29392
|
// src/commands/init.ts
|
|
29245
29393
|
async function runInit(options, version2) {
|
|
29246
29394
|
const cancel = new AbortController();
|
|
@@ -29255,9 +29403,10 @@ async function runInit(options, version2) {
|
|
|
29255
29403
|
update
|
|
29256
29404
|
);
|
|
29257
29405
|
if (!dto.ok) throw new Error("unreachable");
|
|
29406
|
+
await recordUpdateCheck(process.env, dto.update);
|
|
29258
29407
|
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") + ")");
|
|
29259
29408
|
const lineEndings = dto.lineEndings.created ? t2("init.text.lineEndings", { path: dto.lineEndings.path }) + "\n" : "";
|
|
29260
|
-
const newer = dto.install ? t2("init.text.updateAvailable", { version: dto.update.latestVersion, command: dto.install.
|
|
29409
|
+
const newer = dto.install ? t2("init.text.updateAvailable", { version: dto.update.latestVersion, command: dto.install.npmGlobal }) + "\n" : "";
|
|
29261
29410
|
process.stdout.write(options.format === "text" ? `${dto.outcome}: ${dto.rootPath}/.gitifact/config.json
|
|
29262
29411
|
${t2("init.text.storage")}: schemaVersion ${dto.schemaVersion}
|
|
29263
29412
|
${t2("init.text.agentDocs")}: ${docs}
|
|
@@ -29272,17 +29421,17 @@ ${lineEndings}${newer}` : JSON.stringify(dto) + "\n");
|
|
|
29272
29421
|
}
|
|
29273
29422
|
|
|
29274
29423
|
// src/commands/documents.ts
|
|
29275
|
-
import { readFile as
|
|
29276
|
-
import { join as
|
|
29424
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
29425
|
+
import { join as join17 } from "node:path";
|
|
29277
29426
|
|
|
29278
29427
|
// src/commands/project.ts
|
|
29279
|
-
import { join as
|
|
29428
|
+
import { join as join16 } from "node:path";
|
|
29280
29429
|
var operations = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"];
|
|
29281
29430
|
async function openProject(cwd, options = {}) {
|
|
29282
29431
|
const reader = storeReader(cwd);
|
|
29283
29432
|
const location = await reader.location();
|
|
29284
29433
|
if (options.writing) {
|
|
29285
|
-
for (const marker2 of operations) if (await fileInfo(
|
|
29434
|
+
for (const marker2 of operations) if (await fileInfo(join16(location.gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
|
|
29286
29435
|
if (await reader.hasUnmerged()) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
29287
29436
|
}
|
|
29288
29437
|
const raw = await readConfigFile(location.root);
|
|
@@ -29446,7 +29595,7 @@ async function working(project) {
|
|
|
29446
29595
|
const { documents } = await project.cache.documents.list();
|
|
29447
29596
|
return {
|
|
29448
29597
|
byId: new Map(documents.map((d) => [d.id, d])),
|
|
29449
|
-
read: (path3) =>
|
|
29598
|
+
read: (path3) => readFile14(join17(project.root, ...path3.split("/")), "utf8"),
|
|
29450
29599
|
referencing: async (id) => [...new Set((await project.cache.documents.referencing(id)).map((r) => r.from))]
|
|
29451
29600
|
};
|
|
29452
29601
|
}
|
|
@@ -29645,14 +29794,14 @@ var runSpecsNew = (kind2, path3, options) => runCommand("specs", options.format,
|
|
|
29645
29794
|
|
|
29646
29795
|
// src/queries/instructions.ts
|
|
29647
29796
|
import { lstat as lstat12 } from "node:fs/promises";
|
|
29648
|
-
import { join as
|
|
29797
|
+
import { join as join18 } from "node:path";
|
|
29649
29798
|
var AGENTS = "AGENTS.md";
|
|
29650
29799
|
async function listInstructions(source2, options, request) {
|
|
29651
29800
|
const listed3 = await source2.cache.documents.list();
|
|
29652
29801
|
const problems = listed3.problems;
|
|
29653
29802
|
const states = await documentStates(source2, listed3.documents);
|
|
29654
29803
|
const documents = states.documents;
|
|
29655
|
-
const agents2 = { path: AGENTS, exists: !!(await lstat12(
|
|
29804
|
+
const agents2 = { path: AGENTS, exists: !!(await lstat12(join18(source2.root, AGENTS)).catch(() => void 0))?.isFile() };
|
|
29656
29805
|
const historyNeeded = options.sort === "updated" || options.author !== void 0 || !!options.withUpdated;
|
|
29657
29806
|
const latest = /* @__PURE__ */ new Map();
|
|
29658
29807
|
const newest = /* @__PURE__ */ new Map();
|
|
@@ -29751,7 +29900,7 @@ var runInstructionsNew = (name2, options) => runCommand("instructions", options.
|
|
|
29751
29900
|
|
|
29752
29901
|
// src/adapters/filesystem/document-warnings.ts
|
|
29753
29902
|
import { lstat as lstat13, readdir as readdir6 } from "node:fs/promises";
|
|
29754
|
-
import { join as
|
|
29903
|
+
import { join as join19 } from "node:path";
|
|
29755
29904
|
var info2 = async (path3) => lstat13(path3).catch((e) => {
|
|
29756
29905
|
if (e.code === "ENOENT") return void 0;
|
|
29757
29906
|
throw e;
|
|
@@ -29760,11 +29909,11 @@ var posix = (path3) => path3.split("\\").join("/");
|
|
|
29760
29909
|
async function listAssets(root) {
|
|
29761
29910
|
const out = [];
|
|
29762
29911
|
async function visit2(relative, depth) {
|
|
29763
|
-
const stat3 = await info2(
|
|
29912
|
+
const stat3 = await info2(join19(root, relative));
|
|
29764
29913
|
if (!stat3 || stat3.isSymbolicLink()) return;
|
|
29765
29914
|
if (stat3.isDirectory()) {
|
|
29766
29915
|
if (depth > 8 || out.length > 4e3) return;
|
|
29767
|
-
for (const name2 of (await readdir6(
|
|
29916
|
+
for (const name2 of (await readdir6(join19(root, relative))).sort()) await visit2(relative + "/" + name2, depth + 1);
|
|
29768
29917
|
} else if (stat3.isFile()) out.push({ path: posix(relative), bytes: stat3.size });
|
|
29769
29918
|
}
|
|
29770
29919
|
await visit2(ASSETS_DIR, 0);
|
|
@@ -29773,7 +29922,7 @@ async function listAssets(root) {
|
|
|
29773
29922
|
async function readDocumentWarnings(root, documents) {
|
|
29774
29923
|
const outside = [...new Set(documentBodyLinks(documents).map((l) => l.target).filter((t3) => !t3.startsWith(".gitifact/") || t3.startsWith(INSTRUCTIONS_ROOT + "/")))];
|
|
29775
29924
|
const existing = /* @__PURE__ */ new Set();
|
|
29776
|
-
for (const target of outside) if ((await info2(
|
|
29925
|
+
for (const target of outside) if ((await info2(join19(root, ...target.split("/"))))?.isFile()) existing.add(target);
|
|
29777
29926
|
return documentWarnings(documents, await listAssets(root), existing);
|
|
29778
29927
|
}
|
|
29779
29928
|
|
|
@@ -29796,15 +29945,15 @@ var runCheck = (options) => runCommand("check", options.format, async () => {
|
|
|
29796
29945
|
});
|
|
29797
29946
|
|
|
29798
29947
|
// src/commands/changes.ts
|
|
29799
|
-
import { randomUUID as
|
|
29800
|
-
import { mkdir as
|
|
29801
|
-
import { join as
|
|
29948
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
29949
|
+
import { mkdir as mkdir7, open as open5, readFile as readFile17, rename as rename4, rmdir, unlink as unlink5, writeFile as writeFile5 } from "node:fs/promises";
|
|
29950
|
+
import { join as join22 } from "node:path";
|
|
29802
29951
|
|
|
29803
29952
|
// src/adapters/filesystem/agent-inputs.ts
|
|
29804
29953
|
import { createHash as createHash4, randomBytes as randomBytes2 } from "node:crypto";
|
|
29805
|
-
import { lstat as lstat14, mkdir as
|
|
29954
|
+
import { lstat as lstat14, mkdir as mkdir6, readdir as readdir7, realpath as realpath3, unlink as unlink4, writeFile as writeFile4 } from "node:fs/promises";
|
|
29806
29955
|
import { tmpdir } from "node:os";
|
|
29807
|
-
import { basename, dirname as dirname2, join as
|
|
29956
|
+
import { basename, dirname as dirname2, join as join20 } from "node:path";
|
|
29808
29957
|
var maxAge = 7 * 24 * 60 * 60 * 1e3;
|
|
29809
29958
|
var info3 = (path3) => lstat14(path3).catch((e) => {
|
|
29810
29959
|
if (e.code === "ENOENT") return void 0;
|
|
@@ -29813,16 +29962,16 @@ var info3 = (path3) => lstat14(path3).catch((e) => {
|
|
|
29813
29962
|
var comparable = (path3) => process.platform === "win32" ? path3.toLowerCase() : path3;
|
|
29814
29963
|
async function candidates(root, controls) {
|
|
29815
29964
|
const key = createHash4("sha256").update(comparable(await realpath3(root))).digest("hex").slice(0, 16);
|
|
29816
|
-
return { system:
|
|
29965
|
+
return { system: join20((controls.tmpdir ?? tmpdir)(), "gitifact", key), project: join20(root, ".gitifact", "tmp") };
|
|
29817
29966
|
}
|
|
29818
29967
|
async function writable(directory) {
|
|
29819
29968
|
try {
|
|
29820
|
-
await
|
|
29969
|
+
await mkdir6(directory, { recursive: true });
|
|
29821
29970
|
const stat3 = await info3(directory);
|
|
29822
29971
|
if (!stat3?.isDirectory() || stat3.isSymbolicLink()) return false;
|
|
29823
|
-
const probe =
|
|
29824
|
-
await
|
|
29825
|
-
await
|
|
29972
|
+
const probe = join20(directory, ".probe-" + randomBytes2(8).toString("hex"));
|
|
29973
|
+
await writeFile4(probe, "", { flag: "wx" });
|
|
29974
|
+
await unlink4(probe);
|
|
29826
29975
|
return true;
|
|
29827
29976
|
} catch {
|
|
29828
29977
|
return false;
|
|
@@ -29834,7 +29983,7 @@ async function prepareAgentInputs(root, controls = {}) {
|
|
|
29834
29983
|
if (await writable(system)) directory = system;
|
|
29835
29984
|
else if (await writable(project)) {
|
|
29836
29985
|
directory = project;
|
|
29837
|
-
await
|
|
29986
|
+
await writeFile4(join20(project, ".gitignore"), "*\n", { flag: "wx" }).catch((e) => {
|
|
29838
29987
|
if (e.code !== "EEXIST") throw e;
|
|
29839
29988
|
});
|
|
29840
29989
|
}
|
|
@@ -29842,10 +29991,10 @@ async function prepareAgentInputs(root, controls = {}) {
|
|
|
29842
29991
|
const now = (controls.now ?? Date.now)();
|
|
29843
29992
|
for (const name2 of await readdir7(directory).catch(() => [])) {
|
|
29844
29993
|
if (name2 === ".gitignore") continue;
|
|
29845
|
-
const stat3 = await info3(
|
|
29846
|
-
if (stat3?.isFile() && now - stat3.mtimeMs > maxAge) await
|
|
29994
|
+
const stat3 = await info3(join20(directory, name2)).catch(() => void 0);
|
|
29995
|
+
if (stat3?.isFile() && now - stat3.mtimeMs > maxAge) await unlink4(join20(directory, name2)).catch(() => void 0);
|
|
29847
29996
|
}
|
|
29848
|
-
return { commit:
|
|
29997
|
+
return { commit: join20(directory, "commit.json") };
|
|
29849
29998
|
}
|
|
29850
29999
|
async function discardAgentInput(root, file2, controls = {}) {
|
|
29851
30000
|
try {
|
|
@@ -29858,7 +30007,7 @@ async function discardAgentInput(root, file2, controls = {}) {
|
|
|
29858
30007
|
if (await info3(directory) && comparable(await realpath3(directory)) === parent) managed = true;
|
|
29859
30008
|
}
|
|
29860
30009
|
if (!managed || basename(file2) === ".gitignore") return false;
|
|
29861
|
-
await
|
|
30010
|
+
await unlink4(file2);
|
|
29862
30011
|
return true;
|
|
29863
30012
|
} catch {
|
|
29864
30013
|
return false;
|
|
@@ -29867,13 +30016,13 @@ async function discardAgentInput(root, file2, controls = {}) {
|
|
|
29867
30016
|
|
|
29868
30017
|
// src/commands/commit-files.ts
|
|
29869
30018
|
import { createHash as createHash5 } from "node:crypto";
|
|
29870
|
-
import { lstat as lstat15, readFile as
|
|
29871
|
-
import { join as
|
|
30019
|
+
import { lstat as lstat15, readFile as readFile15 } from "node:fs/promises";
|
|
30020
|
+
import { join as join21 } from "node:path";
|
|
29872
30021
|
var fail3 = (message) => {
|
|
29873
30022
|
throw new CommandError("INVALID_COMMIT", message);
|
|
29874
30023
|
};
|
|
29875
30024
|
var hash2 = (value) => createHash5("sha256").update(value).digest("hex");
|
|
29876
|
-
var optional2 = (path3) =>
|
|
30025
|
+
var optional2 = (path3) => readFile15(path3).catch((e) => {
|
|
29877
30026
|
if (e.code === "ENOENT") return null;
|
|
29878
30027
|
throw e;
|
|
29879
30028
|
});
|
|
@@ -29903,14 +30052,14 @@ async function fingerprint(root, path3) {
|
|
|
29903
30052
|
validPath2(path3);
|
|
29904
30053
|
const parts = path3.split("/");
|
|
29905
30054
|
for (let i = 1; i <= parts.length; i++) {
|
|
29906
|
-
const target =
|
|
30055
|
+
const target = join21(root, ...parts.slice(0, i));
|
|
29907
30056
|
const stat3 = await info4(target);
|
|
29908
30057
|
if (!stat3) return null;
|
|
29909
30058
|
if (stat3.isSymbolicLink() || (i < parts.length ? !stat3.isDirectory() : !stat3.isFile())) fail3(t2("commitFiles.linkOrDirectory"));
|
|
29910
|
-
if (i < parts.length && await info4(
|
|
30059
|
+
if (i < parts.length && await info4(join21(target, ".git"))) fail3(t2("commitFiles.nestedRepository"));
|
|
29911
30060
|
if (i === parts.length) {
|
|
29912
30061
|
if (stat3.nlink !== 1 || stat3.size > 16 * 1024 * 1024) fail3(t2("commitFiles.hardLinkOrSize"));
|
|
29913
|
-
return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await
|
|
30062
|
+
return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await readFile15(target)]));
|
|
29914
30063
|
}
|
|
29915
30064
|
}
|
|
29916
30065
|
return null;
|
|
@@ -29937,14 +30086,15 @@ function policyPaths(files) {
|
|
|
29937
30086
|
}
|
|
29938
30087
|
return [...all].sort();
|
|
29939
30088
|
}
|
|
30089
|
+
var storeFiles = /* @__PURE__ */ new Set([".gitifact/config.json", LINE_ENDINGS_PATH]);
|
|
29940
30090
|
function checkStoreSelection(selected2) {
|
|
29941
|
-
for (const p of selected2.filter((p2) => p2.startsWith(".gitifact/") && !record3(p2) && p2
|
|
30091
|
+
for (const p of selected2.filter((p2) => p2.startsWith(".gitifact/") && !record3(p2) && !storeFiles.has(p2))) {
|
|
29942
30092
|
if (!isAssetPath(p) && !instructionFile2(p)) fail3(t2("commitFiles.notRecord", { path: p }));
|
|
29943
30093
|
}
|
|
29944
30094
|
}
|
|
29945
30095
|
|
|
29946
30096
|
// src/commands/input.ts
|
|
29947
|
-
import { readFile as
|
|
30097
|
+
import { readFile as readFile16, stat as stat2 } from "node:fs/promises";
|
|
29948
30098
|
var LIMIT2 = 1024 * 1024;
|
|
29949
30099
|
async function readJsonInput(file2, stdin = process.stdin) {
|
|
29950
30100
|
const bytes = file2 === "-" ? await readStdin(stdin) : await readInputFile(file2);
|
|
@@ -29957,7 +30107,7 @@ async function readJsonInput(file2, stdin = process.stdin) {
|
|
|
29957
30107
|
async function readInputFile(path3) {
|
|
29958
30108
|
const source2 = await stat2(path3).catch(() => void 0);
|
|
29959
30109
|
if (!source2?.isFile() || source2.size > LIMIT2) throw new CommandError("INVALID_INPUT", t2("input.file"));
|
|
29960
|
-
return
|
|
30110
|
+
return readFile16(path3);
|
|
29961
30111
|
}
|
|
29962
30112
|
async function readStdin(stream) {
|
|
29963
30113
|
const chunks = [];
|
|
@@ -30057,7 +30207,7 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30057
30207
|
...stdin ? { input: stdin } : {}
|
|
30058
30208
|
});
|
|
30059
30209
|
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();
|
|
30060
|
-
const busy =
|
|
30210
|
+
const busy = join22(gitDir, "gitifact-changes-commit.lock");
|
|
30061
30211
|
if (await info4(busy)) fail3(t2("commit.busy", { path: busy }));
|
|
30062
30212
|
if ((await staged()).length) fail3(t2("commit.existingStaging"));
|
|
30063
30213
|
const indexHash = hash2(await optional2(indexPath) ?? Buffer.alloc(0));
|
|
@@ -30096,7 +30246,7 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30096
30246
|
if (!same2(base, await project.reader.baseline())) fail3(t2("commit.headChanged"));
|
|
30097
30247
|
return { outcome: "dry-run", committed: false, ...summary, commit: void 0 };
|
|
30098
30248
|
}
|
|
30099
|
-
const temporary =
|
|
30249
|
+
const temporary = join22(gitDir, "gitifact-commit-index-" + randomUUID6());
|
|
30100
30250
|
let owned = false;
|
|
30101
30251
|
let uncertain = false;
|
|
30102
30252
|
let commitStarted = false;
|
|
@@ -30104,7 +30254,7 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30104
30254
|
let committed2;
|
|
30105
30255
|
try {
|
|
30106
30256
|
try {
|
|
30107
|
-
await
|
|
30257
|
+
await mkdir7(busy);
|
|
30108
30258
|
owned = true;
|
|
30109
30259
|
} catch (e) {
|
|
30110
30260
|
if (e.code === "EEXIST") fail3(t2("commit.busy", { path: busy }));
|
|
@@ -30115,31 +30265,31 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30115
30265
|
if (hash2(original ?? Buffer.alloc(0)) !== indexHash || (await staged()).length) fail3(t2("commit.indexChanged"));
|
|
30116
30266
|
const before = await hashes([...started.keys()]);
|
|
30117
30267
|
for (const [path3, value] of started) if (before.get(path3) !== value) fail3(t2("commit.fileChangedRunning", { path: path3 }));
|
|
30118
|
-
await
|
|
30268
|
+
await writeFile5(join22(busy, "recovery.json"), JSON.stringify({ before: base, originalIndex: original?.toString("base64") ?? null, temporary, paths: selected2, message }));
|
|
30119
30269
|
const locked = await hashes([.../* @__PURE__ */ new Set([...selected2, ...contextPaths])]);
|
|
30120
|
-
if (original) await
|
|
30270
|
+
if (original) await writeFile5(temporary, original, { flag: "wx" });
|
|
30121
30271
|
else await git(["read-tree", "--empty"], temporary);
|
|
30122
30272
|
await git(["add", "--pathspec-from-file=-", "--pathspec-file-nul"], temporary, Buffer.from(stageable.join("\0")));
|
|
30123
30273
|
const actual = await staged(temporary);
|
|
30124
30274
|
if (!actual.length || actual.some((p) => !selected2.includes(p))) fail3(t2("commit.unexpectedFiles"));
|
|
30125
|
-
const
|
|
30126
|
-
if (
|
|
30127
|
-
const output2 = await git(["cat-file", "--batch"], temporary, Buffer.from(
|
|
30275
|
+
const storeFiles2 = selected2.filter((p) => record3(p) && locked.get(p) !== null);
|
|
30276
|
+
if (storeFiles2.length) {
|
|
30277
|
+
const output2 = await git(["cat-file", "--batch"], temporary, Buffer.from(storeFiles2.map((p) => ":" + p).join("\n") + "\n"));
|
|
30128
30278
|
let offset = 0;
|
|
30129
|
-
for (const path3 of
|
|
30279
|
+
for (const path3 of storeFiles2) {
|
|
30130
30280
|
const end = output2.indexOf(10, offset);
|
|
30131
30281
|
const header = output2.subarray(offset, end).toString("utf8").split(" ");
|
|
30132
30282
|
const size = Number(header[2]);
|
|
30133
30283
|
if (end < 0 || header[1] !== "blob" || !Number.isSafeInteger(size) || output2[end + 1 + size] !== 10) fail3(t2("commit.stagedUnreadable", { path: path3 }));
|
|
30134
30284
|
const blob = output2.subarray(end + 1, end + 1 + size);
|
|
30135
|
-
const file2 = await
|
|
30285
|
+
const file2 = await readFile17(join22(root, path3));
|
|
30136
30286
|
if (!blob.equals(file2) && !blob.equals(Buffer.from(file2.toString("latin1").replace(/\r\n/g, "\n"), "latin1"))) fail3(t2("commit.filterChanged"));
|
|
30137
30287
|
offset = end + size + 2;
|
|
30138
30288
|
}
|
|
30139
30289
|
}
|
|
30140
30290
|
const again = await hashes([...locked.keys()]);
|
|
30141
30291
|
for (const [path3, value] of locked) if (again.get(path3) !== value) fail3(t2("commit.fileChangedPreparing", { path: path3 }));
|
|
30142
|
-
for (const name2 of integration) if (await info4(
|
|
30292
|
+
for (const name2 of integration) if (await info4(join22(gitDir, name2))) fail3(t2("commit.integrationStarted"));
|
|
30143
30293
|
if (!same2(base, await project.reader.baseline())) fail3(t2("commit.headChanged"));
|
|
30144
30294
|
const tree = (await git(["write-tree"], temporary)).toString("utf8").trim();
|
|
30145
30295
|
commitStarted = true;
|
|
@@ -30154,10 +30304,10 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30154
30304
|
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"));
|
|
30155
30305
|
if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== indexHash) fail3(t2("commit.indexChangedAfter"));
|
|
30156
30306
|
if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail3(t2("commit.hookChangedStaging"));
|
|
30157
|
-
await lock.writeFile(await
|
|
30307
|
+
await lock.writeFile(await readFile17(temporary));
|
|
30158
30308
|
await lock.sync();
|
|
30159
30309
|
await lock.close();
|
|
30160
|
-
await
|
|
30310
|
+
await rename4(indexPath + ".lock", indexPath);
|
|
30161
30311
|
indexLock = void 0;
|
|
30162
30312
|
committed2 = { commit: after.head, paths: actual };
|
|
30163
30313
|
} catch (error62) {
|
|
@@ -30174,12 +30324,12 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30174
30324
|
await indexLock?.close().catch(() => {
|
|
30175
30325
|
});
|
|
30176
30326
|
if (!uncertain) {
|
|
30177
|
-
if (indexLock) await
|
|
30327
|
+
if (indexLock) await unlink5(indexPath + ".lock").catch(() => {
|
|
30178
30328
|
});
|
|
30179
|
-
await
|
|
30329
|
+
await unlink5(temporary).catch(() => {
|
|
30180
30330
|
});
|
|
30181
30331
|
if (owned) {
|
|
30182
|
-
await
|
|
30332
|
+
await unlink5(join22(busy, "recovery.json")).catch(() => {
|
|
30183
30333
|
});
|
|
30184
30334
|
await rmdir(busy);
|
|
30185
30335
|
}
|
|
@@ -30189,8 +30339,8 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30189
30339
|
}
|
|
30190
30340
|
|
|
30191
30341
|
// src/commands/records.ts
|
|
30192
|
-
import { readFile as
|
|
30193
|
-
import { join as
|
|
30342
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
30343
|
+
import { join as join23 } from "node:path";
|
|
30194
30344
|
var runRecordsNew = (options) => runCommand("records", options.format, async () => {
|
|
30195
30345
|
if (/[\r\n]/.test(options.title)) throw new CommandError("INVALID_VALUE", t2("docs.singleLine", { field: "title" }));
|
|
30196
30346
|
const docs = [...new Set(options.docs.flatMap((d) => d.split(",")).map((d) => d.trim()).filter(Boolean))];
|
|
@@ -30226,7 +30376,7 @@ var runRecordsShow = (ids, options) => runCommand("records", options.format, asy
|
|
|
30226
30376
|
const shown = await Promise.all([...new Set(ids)].map(async (id) => {
|
|
30227
30377
|
const path3 = await findRecord(project.root, id);
|
|
30228
30378
|
if (!path3) return { id, missing: true };
|
|
30229
|
-
const source2 = await
|
|
30379
|
+
const source2 = await readFile18(join23(project.root, ...path3.split("/")), "utf8");
|
|
30230
30380
|
const log = project.reader.decode(await project.reader.run(["log", "-1", "--diff-filter=A", "--format=%H%x00%aN%x00%aI", "--", path3])).trim();
|
|
30231
30381
|
const [commit, author, date5] = log.split("\0");
|
|
30232
30382
|
return { id, path: path3, text: source2, commit: commit ? { commit, author, date: date5 } : null };
|
|
@@ -30334,9 +30484,7 @@ async function readThrough(project, head, filter, id) {
|
|
|
30334
30484
|
}
|
|
30335
30485
|
|
|
30336
30486
|
// src/commands/feedback.ts
|
|
30337
|
-
import { readFile as readFile18 } from "node:fs/promises";
|
|
30338
30487
|
import { release as release3 } from "node:os";
|
|
30339
|
-
import { dirname as dirname3, join as join23 } from "node:path";
|
|
30340
30488
|
|
|
30341
30489
|
// src/adapters/github/issue.ts
|
|
30342
30490
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -30390,6 +30538,17 @@ function newIssueUrl(title, body2, marker2) {
|
|
|
30390
30538
|
return { url: address(characters.slice(0, low).join("") + marker2), truncated: true };
|
|
30391
30539
|
}
|
|
30392
30540
|
|
|
30541
|
+
// src/shared/project-config.ts
|
|
30542
|
+
import { readFile as readFile19 } from "node:fs/promises";
|
|
30543
|
+
import { dirname as dirname3, join as join24 } from "node:path";
|
|
30544
|
+
async function findProjectConfig(from) {
|
|
30545
|
+
for (let folder = from; ; folder = dirname3(folder)) {
|
|
30546
|
+
const text4 = await readFile19(join24(folder, ".gitifact", "config.json"), "utf8").catch(() => void 0);
|
|
30547
|
+
if (text4 !== void 0) return { root: folder, text: text4 };
|
|
30548
|
+
if (dirname3(folder) === folder) return void 0;
|
|
30549
|
+
}
|
|
30550
|
+
}
|
|
30551
|
+
|
|
30393
30552
|
// src/commands/feedback.ts
|
|
30394
30553
|
var types = ["bug", "idea"];
|
|
30395
30554
|
function parseFeedback(input2) {
|
|
@@ -30402,17 +30561,13 @@ function parseFeedback(input2) {
|
|
|
30402
30561
|
return { type, title: title.trim(), body: body2.trim() };
|
|
30403
30562
|
}
|
|
30404
30563
|
async function schemaVersion(from) {
|
|
30405
|
-
|
|
30406
|
-
|
|
30407
|
-
|
|
30408
|
-
|
|
30409
|
-
|
|
30410
|
-
|
|
30411
|
-
|
|
30412
|
-
return "none";
|
|
30413
|
-
}
|
|
30414
|
-
}
|
|
30415
|
-
if (dirname3(folder) === folder) return "none";
|
|
30564
|
+
const config2 = (await findProjectConfig(from))?.text;
|
|
30565
|
+
if (config2 === void 0) return "none";
|
|
30566
|
+
try {
|
|
30567
|
+
const value = JSON.parse(config2).schemaVersion;
|
|
30568
|
+
return typeof value === "number" ? String(value) : "none";
|
|
30569
|
+
} catch {
|
|
30570
|
+
return "none";
|
|
30416
30571
|
}
|
|
30417
30572
|
}
|
|
30418
30573
|
async function issueBody(feedback, version2, cwd) {
|
|
@@ -30449,6 +30604,11 @@ var runFeedback = (options, version2, run) => runCommand("feedback", options.for
|
|
|
30449
30604
|
return { json: { ...sent, title: feedback.title, body: body2 }, text: text2(out) };
|
|
30450
30605
|
});
|
|
30451
30606
|
|
|
30607
|
+
// src/commands/update.ts
|
|
30608
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
30609
|
+
import { join as join25 } from "node:path";
|
|
30610
|
+
import { isDeepStrictEqual } from "node:util";
|
|
30611
|
+
|
|
30452
30612
|
// src/adapters/git/agent-docs-commit.ts
|
|
30453
30613
|
function agentDocsGit(root, inherited = process.env) {
|
|
30454
30614
|
const env = { ...inherited, GIT_OPTIONAL_LOCKS: "0", GIT_NO_LAZY_FETCH: "1", GIT_TERMINAL_PROMPT: "0", GIT_LITERAL_PATHSPECS: "1", LC_ALL: "C" };
|
|
@@ -30480,9 +30640,11 @@ function agentDocsGit(root, inherited = process.env) {
|
|
|
30480
30640
|
}
|
|
30481
30641
|
|
|
30482
30642
|
// src/commands/update.ts
|
|
30483
|
-
var
|
|
30643
|
+
var CONFIG_PATH = ".gitifact/config.json";
|
|
30644
|
+
var updateCommitMessage = (version2) => "chore(gitifact): update project to gitifact v" + version2;
|
|
30484
30645
|
var commitState = (state2, extra = {}) => ({ state: state2, commit: null, paths: [], message: null, reason: null, detail: null, ...extra });
|
|
30485
|
-
|
|
30646
|
+
var notInitialized = { docs: { state: "not-initialized", paths: [], missing: [] }, project: { state: "not-initialized", cli: null } };
|
|
30647
|
+
async function refreshProject(cwd, version2, env, controls) {
|
|
30486
30648
|
const repo = initRepository(cwd, env);
|
|
30487
30649
|
let first;
|
|
30488
30650
|
let config2;
|
|
@@ -30490,20 +30652,28 @@ async function refreshBlocks(cwd, version2, env, controls) {
|
|
|
30490
30652
|
first = await repo.inspect();
|
|
30491
30653
|
config2 = await readConfigFile(first.state.repository.rootPath);
|
|
30492
30654
|
} catch (error62) {
|
|
30493
|
-
if (error62 instanceof RepositoryReadError && error62.code === "NOT_A_REPOSITORY") return
|
|
30655
|
+
if (error62 instanceof RepositoryReadError && error62.code === "NOT_A_REPOSITORY") return notInitialized;
|
|
30494
30656
|
throw error62;
|
|
30495
30657
|
}
|
|
30496
|
-
if (config2 === void 0) return
|
|
30658
|
+
if (config2 === void 0) return notInitialized;
|
|
30497
30659
|
const root = first.state.repository.rootPath;
|
|
30498
|
-
const
|
|
30660
|
+
const parsed2 = needsMigration(config2) ? void 0 : parseManagedConfig(config2);
|
|
30661
|
+
const plan = await planAgentDocs(root, { version: version2, onlyExisting: true, language: parsed2?.language, ...controls });
|
|
30499
30662
|
const { missing: missing2 } = plan;
|
|
30500
|
-
if (
|
|
30501
|
-
|
|
30663
|
+
if (parsed2?.cli && isNewerRelease(parsed2.cli, version2)) return { docs: { state: "kept", paths: plan.paths, missing: missing2, root }, project: { state: "current", cli: parsed2.cli } };
|
|
30664
|
+
let current2 = config2;
|
|
30502
30665
|
const unchanged = async () => {
|
|
30503
|
-
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !==
|
|
30666
|
+
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !== current2) throw new InitError("INPUT_CHANGED", t2("init.inputChanged"));
|
|
30504
30667
|
};
|
|
30505
|
-
const
|
|
30506
|
-
return {
|
|
30668
|
+
const docs = plan.paths.length === 0 ? { state: "no-block", paths: [], missing: missing2, root } : plan.writes.length === 0 ? { state: "current", paths: plan.paths, missing: missing2, root, candidates: plan.paths } : { state: "refreshed", paths: await applyAgentDocs(root, plan, unchanged), missing: missing2, root, candidates: plan.paths };
|
|
30669
|
+
if (!parsed2) return { docs, project: { state: "current", cli: null } };
|
|
30670
|
+
const settled2 = settleConfig(parsed2, version2, plan.language);
|
|
30671
|
+
if (settled2.changed) {
|
|
30672
|
+
const next = formatManagedConfig(settled2.config, config2);
|
|
30673
|
+
await publishConfig(root, next, unchanged, void 0, true);
|
|
30674
|
+
current2 = next;
|
|
30675
|
+
}
|
|
30676
|
+
return { docs: { ...docs, root }, project: { state: settled2.changed ? "written" : "current", cli: settled2.config.cli ?? null } };
|
|
30507
30677
|
}
|
|
30508
30678
|
function outsideBlock(text4) {
|
|
30509
30679
|
const normalized2 = text4.replace(/\r\n/g, "\n");
|
|
@@ -30514,12 +30684,20 @@ function outsideBlock(text4) {
|
|
|
30514
30684
|
return null;
|
|
30515
30685
|
}
|
|
30516
30686
|
}
|
|
30517
|
-
|
|
30518
|
-
|
|
30687
|
+
function withoutSettings(text4) {
|
|
30688
|
+
try {
|
|
30689
|
+
const { cli: _c, language: _l, ...rest } = JSON.parse(text4);
|
|
30690
|
+
return rest;
|
|
30691
|
+
} catch {
|
|
30692
|
+
return null;
|
|
30693
|
+
}
|
|
30694
|
+
}
|
|
30695
|
+
async function commitUpdate(docs, version2, env) {
|
|
30696
|
+
if (!docs.root) return commitState("nothing");
|
|
30519
30697
|
const git = agentDocsGit(docs.root, env);
|
|
30520
30698
|
const head = await git.head();
|
|
30521
30699
|
const changed = [];
|
|
30522
|
-
for (const path3 of docs.candidates) {
|
|
30700
|
+
for (const path3 of docs.candidates ?? []) {
|
|
30523
30701
|
const working2 = await managedRead(docs.root, path3);
|
|
30524
30702
|
const committed2 = head ? await git.committed(head, path3) : null;
|
|
30525
30703
|
if (working2 === null) continue;
|
|
@@ -30529,8 +30707,16 @@ async function commitBlocks(docs, version2, env) {
|
|
|
30529
30707
|
if (before === null || before !== outsideBlock(working2)) return commitState("skipped", { paths: [path3], reason: "other-changes" });
|
|
30530
30708
|
changed.push(path3);
|
|
30531
30709
|
}
|
|
30710
|
+
const workingConfig = await readFile20(join25(docs.root, CONFIG_PATH), "utf8").catch(() => null);
|
|
30711
|
+
const committedConfig = head ? await git.committed(head, CONFIG_PATH) : null;
|
|
30712
|
+
if (workingConfig !== null && committedConfig?.replace(/\r\n/g, "\n") !== workingConfig.replace(/\r\n/g, "\n")) {
|
|
30713
|
+
if (committedConfig === null) return commitState("skipped", { paths: [CONFIG_PATH], reason: "untracked" });
|
|
30714
|
+
const before = withoutSettings(committedConfig);
|
|
30715
|
+
if (before === null || !isDeepStrictEqual(before, withoutSettings(workingConfig))) return commitState("skipped", { paths: [CONFIG_PATH], reason: "other-changes" });
|
|
30716
|
+
changed.push(CONFIG_PATH);
|
|
30717
|
+
}
|
|
30532
30718
|
if (changed.length === 0) return commitState("nothing");
|
|
30533
|
-
const message =
|
|
30719
|
+
const message = updateCommitMessage(version2);
|
|
30534
30720
|
let failure2;
|
|
30535
30721
|
try {
|
|
30536
30722
|
await git.commitOnly(changed, message);
|
|
@@ -30544,20 +30730,23 @@ async function commitBlocks(docs, version2, env) {
|
|
|
30544
30730
|
return commitState("committed", { commit: after, paths: await git.changedPaths(after), message });
|
|
30545
30731
|
}
|
|
30546
30732
|
async function updateCommand(cwd, version2, env = process.env, controls = {}) {
|
|
30547
|
-
const [update,
|
|
30733
|
+
const [update, refreshed] = await Promise.all([
|
|
30548
30734
|
updateCheckDisabled(env) ? disabledUpdate : resolveUpdate(version2, controls.fetchLatest ?? fetchLatestVersion, void 0, controls.timeoutMs),
|
|
30549
|
-
|
|
30735
|
+
refreshProject(cwd, version2, env, controls)
|
|
30550
30736
|
]);
|
|
30551
|
-
|
|
30552
|
-
const
|
|
30553
|
-
|
|
30737
|
+
await recordUpdateCheck(env, update, controls.now?.());
|
|
30738
|
+
const { docs, project } = refreshed;
|
|
30739
|
+
const commit = controls.commit ? await commitUpdate(docs, version2, env) : commitState("not-requested");
|
|
30740
|
+
const config2 = await readConfigFile(docs.root ?? cwd).catch(() => void 0);
|
|
30741
|
+
return updateV6.parse({
|
|
30554
30742
|
contract: "update",
|
|
30555
|
-
version:
|
|
30743
|
+
version: 6,
|
|
30556
30744
|
ok: true,
|
|
30557
30745
|
cliVersion: version2,
|
|
30558
30746
|
update,
|
|
30559
|
-
install: update.status === "available" ? {
|
|
30560
|
-
agentDocs: { state:
|
|
30747
|
+
install: update.status === "available" ? { npmGlobal: npmGlobalInstall(update.latestVersion) } : null,
|
|
30748
|
+
agentDocs: { state: docs.state, paths: docs.paths, missing: docs.missing },
|
|
30749
|
+
project,
|
|
30561
30750
|
commit,
|
|
30562
30751
|
migrationRequired: config2 !== void 0 && needsMigration(config2)
|
|
30563
30752
|
});
|
|
@@ -30572,9 +30761,11 @@ async function runUpdate(options, version2) {
|
|
|
30572
30761
|
}
|
|
30573
30762
|
const lines = [t2("update.text.current", { version: dto.cliVersion })];
|
|
30574
30763
|
lines.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"));
|
|
30575
|
-
if (dto.install) lines.push(t2("update.text.install", { command: dto.install.
|
|
30576
|
-
lines.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 === "
|
|
30577
|
-
if (dto.agentDocs.missing.length) lines.push(t2("update.text.missing", { paths: dto.agentDocs.missing.join(", ")
|
|
30764
|
+
if (dto.install) lines.push(t2("update.text.install", { command: dto.install.npmGlobal }), t2("update.text.afterInstall"));
|
|
30765
|
+
lines.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"));
|
|
30766
|
+
if (dto.agentDocs.missing.length) lines.push(t2("update.text.missing", { paths: dto.agentDocs.missing.join(", ") }));
|
|
30767
|
+
if (dto.project.state === "written") lines.push(t2("update.text.projectWritten", { path: CONFIG_PATH, version: dto.project.cli ?? dto.cliVersion }));
|
|
30768
|
+
if (dto.project.cli && isNewerRelease(dto.project.cli, dto.cliVersion)) lines.push(t2("update.text.projectAhead", { project: dto.project.cli, version: dto.cliVersion, command: npmGlobalInstall(dto.project.cli) }));
|
|
30578
30769
|
if (dto.migrationRequired) lines.push(t2("update.text.migrationRequired", { version: dto.cliVersion }));
|
|
30579
30770
|
const { commit } = dto;
|
|
30580
30771
|
if (commit.state === "committed") lines.push(t2("update.text.committed", { commit: commit.commit.slice(0, 12), paths: commit.paths.join(", ") }));
|
|
@@ -30588,7 +30779,7 @@ async function runUpdate(options, version2) {
|
|
|
30588
30779
|
} catch (error62) {
|
|
30589
30780
|
const known = error62 instanceof InitError || error62 instanceof RepositoryReadError;
|
|
30590
30781
|
const failure2 = { code: known ? error62.code : "UPDATE_FAILED", message: known ? error62.message : t2("update.failed") };
|
|
30591
|
-
process.stderr.write(options.format === "text" ? failure2.code + ": " + failure2.message + "\n" : JSON.stringify(
|
|
30782
|
+
process.stderr.write(options.format === "text" ? failure2.code + ": " + failure2.message + "\n" : JSON.stringify(updateV6.parse({ contract: "update", version: 6, ok: false, error: failure2 })) + "\n");
|
|
30592
30783
|
process.exitCode = 1;
|
|
30593
30784
|
}
|
|
30594
30785
|
}
|
|
@@ -30596,6 +30787,7 @@ async function runUpdate(options, version2) {
|
|
|
30596
30787
|
// src/commands/update-check.ts
|
|
30597
30788
|
async function checkUpdateCommand(version2, env = process.env, controls = {}) {
|
|
30598
30789
|
const update = updateCheckDisabled(env) ? disabledUpdate : await resolveUpdate(version2, controls.fetchLatest ?? fetchLatestVersion, void 0, controls.timeoutMs);
|
|
30790
|
+
await recordUpdateCheck(env, update, controls.now?.());
|
|
30599
30791
|
return updateCheckV1.parse({
|
|
30600
30792
|
contract: "update-check",
|
|
30601
30793
|
version: 1,
|
|
@@ -30616,10 +30808,73 @@ async function runUpdateCheck(format2, version2) {
|
|
|
30616
30808
|
t2("update.text.current", { version: dto.cliVersion }),
|
|
30617
30809
|
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")
|
|
30618
30810
|
];
|
|
30619
|
-
if (
|
|
30811
|
+
if (state2.status === "available") lines.push(t2("update.text.install", { command: npmGlobalInstall(state2.latestVersion) }), t2("update.text.afterInstall"));
|
|
30620
30812
|
process.stdout.write(lines.join("\n") + "\n");
|
|
30621
30813
|
}
|
|
30622
30814
|
|
|
30815
|
+
// src/commands/version-notice.ts
|
|
30816
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
30817
|
+
import { homedir as homedir2 } from "node:os";
|
|
30818
|
+
var REFRESH_AFTER_MS = 60 * 60 * 1e3;
|
|
30819
|
+
var CHECKING_WINDOW_MS = 5 * 60 * 1e3;
|
|
30820
|
+
var LATER_MS = 24 * 60 * 60 * 1e3;
|
|
30821
|
+
var REFRESH_COMMAND = "__refresh-update";
|
|
30822
|
+
var noticeScope = (command) => ({ release: command !== "init" && command !== "update", projectOlder: command !== "init" && command !== "update" });
|
|
30823
|
+
function chooseNotice(running2, project, cache, now, scope = { release: true, projectOlder: true }) {
|
|
30824
|
+
if (project && isNewerRelease(project, running2)) return { kind: "project-newer", project };
|
|
30825
|
+
const latest = cache.latest;
|
|
30826
|
+
const postponed = cache.later !== void 0 && cache.later.version === latest && now < Date.parse(cache.later.until);
|
|
30827
|
+
if (scope.release && latest && isNewerRelease(latest, running2) && !postponed) return { kind: "release", latest };
|
|
30828
|
+
if (scope.projectOlder && project && isNewerRelease(running2, project)) return { kind: "project-older", project };
|
|
30829
|
+
return null;
|
|
30830
|
+
}
|
|
30831
|
+
function noticeText(notice, running2) {
|
|
30832
|
+
if (notice.kind === "project-newer") return t2("notice.projectNewer", { project: notice.project, version: running2, command: npmGlobalInstall(notice.project) });
|
|
30833
|
+
if (notice.kind === "release") return t2("notice.release", { latest: notice.latest, version: running2, command: npmGlobalInstall(notice.latest) });
|
|
30834
|
+
return t2("notice.projectOlder", { project: notice.project, version: running2 });
|
|
30835
|
+
}
|
|
30836
|
+
var needsRefresh = (cache, now) => !(cache.checkedAt && now - Date.parse(cache.checkedAt) < REFRESH_AFTER_MS) && !(cache.checkingSince && now - Date.parse(cache.checkingSince) < CHECKING_WINDOW_MS);
|
|
30837
|
+
var spawnRefresh = () => {
|
|
30838
|
+
const child = spawn3(process.execPath, [...process.execArgv, process.argv[1], REFRESH_COMMAND], { cwd: homedir2(), detached: true, stdio: "ignore", windowsHide: true });
|
|
30839
|
+
child.on("error", () => {
|
|
30840
|
+
});
|
|
30841
|
+
child.unref();
|
|
30842
|
+
};
|
|
30843
|
+
async function noticeVersion(version2, command, controls = {}) {
|
|
30844
|
+
const env = controls.env ?? process.env;
|
|
30845
|
+
const now = controls.now ?? Date.now();
|
|
30846
|
+
try {
|
|
30847
|
+
const project = projectSettings((await findProjectConfig(controls.cwd ?? process.cwd()))?.text).cli;
|
|
30848
|
+
const scope = noticeScope(command);
|
|
30849
|
+
let cache = {};
|
|
30850
|
+
if (!updateCheckDisabled(env)) {
|
|
30851
|
+
cache = await readUpdateCache(env);
|
|
30852
|
+
if (scope.release && needsRefresh(cache, now)) {
|
|
30853
|
+
await changeUpdateCache(env, (current2) => ({ ...current2, checkingSince: new Date(now).toISOString() }));
|
|
30854
|
+
(controls.refresh ?? spawnRefresh)();
|
|
30855
|
+
}
|
|
30856
|
+
}
|
|
30857
|
+
const notice = chooseNotice(version2, project, cache, now, scope);
|
|
30858
|
+
if (notice) (controls.write ?? ((line2) => process.stderr.write(line2 + "\n")))(noticeText(notice, version2));
|
|
30859
|
+
} catch {
|
|
30860
|
+
}
|
|
30861
|
+
}
|
|
30862
|
+
async function refreshUpdateCache(version2, env = process.env, fetchLatest = fetchLatestVersion, now) {
|
|
30863
|
+
if (updateCheckDisabled(env)) return;
|
|
30864
|
+
const update = await resolveUpdate(version2, fetchLatest);
|
|
30865
|
+
await recordUpdateCheck(env, update, now?.());
|
|
30866
|
+
}
|
|
30867
|
+
async function postponeRelease(version2, env = process.env, now = Date.now()) {
|
|
30868
|
+
const cache = await readUpdateCache(env);
|
|
30869
|
+
const later = cache.latest && isNewerRelease(cache.latest, version2) ? { version: cache.latest, until: new Date(now + LATER_MS).toISOString() } : null;
|
|
30870
|
+
if (later) await changeUpdateCache(env, (current2) => ({ ...current2, later }));
|
|
30871
|
+
return updateLaterV1.parse({ contract: "update-later", version: 1, ok: true, cliVersion: version2, later });
|
|
30872
|
+
}
|
|
30873
|
+
async function runUpdateLater(format2, version2) {
|
|
30874
|
+
const dto = await postponeRelease(version2);
|
|
30875
|
+
process.stdout.write(format2 === "json" ? JSON.stringify(dto) + "\n" : (dto.later ? t2("update.later.postponed", { latest: dto.later.version, until: new Date(dto.later.until).toLocaleString() }) : t2("update.later.nothing", { version: version2 })) + "\n");
|
|
30876
|
+
}
|
|
30877
|
+
|
|
30623
30878
|
// src/main.ts
|
|
30624
30879
|
var languageArgs = process.argv.slice(2).slice(0, process.argv.slice(2).indexOf("--") < 0 ? void 0 : process.argv.slice(2).indexOf("--"));
|
|
30625
30880
|
var selectedLanguage;
|
|
@@ -30629,11 +30884,17 @@ for (let i = 0; i < languageArgs.length; i++) {
|
|
|
30629
30884
|
if (value === "ko" || value === "en") selectedLanguage = value;
|
|
30630
30885
|
}
|
|
30631
30886
|
configureLanguage(selectedLanguage ?? environmentLanguage(), selectedLanguage);
|
|
30632
|
-
var program2 = new Command().name("gitifact").addOption(new Option("--lang <language>", t2("help.lang")).choices(["ko", "en"])).description(t2("help.program")).version("0.8.
|
|
30887
|
+
var program2 = new Command().name("gitifact").addOption(new Option("--lang <language>", t2("help.lang")).choices(["ko", "en"])).description(t2("help.program")).version("0.8.4").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
|
|
30888
|
+
program2.hook("preAction", async (_program, action) => {
|
|
30889
|
+
let top = action;
|
|
30890
|
+
while (top.parent && top.parent !== program2) top = top.parent;
|
|
30891
|
+
if (top.name() !== REFRESH_COMMAND) await noticeVersion("0.8.4", top.name());
|
|
30892
|
+
});
|
|
30893
|
+
program2.command(REFRESH_COMMAND, { hidden: true }).allowExcessArguments(false).action(() => refreshUpdateCache("0.8.4"));
|
|
30633
30894
|
var format = () => new Option("--format <format>", t2("help.format")).choices(formats).default("text");
|
|
30634
|
-
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.8.
|
|
30635
|
-
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.8.
|
|
30636
|
-
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")).action((options) => options.check ? runUpdateCheck(options.format, "0.8.
|
|
30895
|
+
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.8.4"));
|
|
30896
|
+
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.8.4"));
|
|
30897
|
+
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.8.4") : options.check ? runUpdateCheck(options.format, "0.8.4") : runUpdate(options, "0.8.4"));
|
|
30637
30898
|
var listed2 = (command, sorts) => {
|
|
30638
30899
|
command.allowExcessArguments(false).option("--q <words>", t2("help.listQ")).option("--author <name>", t2("help.listAuthor"));
|
|
30639
30900
|
if (sorts) command.addOption(new Option("--sort <key>", t2("help.listSort")).choices([...sorts]).default(sorts[0]));
|
|
@@ -30655,7 +30916,7 @@ program2.command("check").description(t2("help.check")).allowExcessArguments(fal
|
|
|
30655
30916
|
var changes = program2.command("changes").description(t2("help.changes"));
|
|
30656
30917
|
changes.command("list").description(t2("help.changesList")).allowExcessArguments(false).addOption(format()).action((o) => runChangesList(o));
|
|
30657
30918
|
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));
|
|
30658
|
-
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.8.
|
|
30919
|
+
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.8.4"));
|
|
30659
30920
|
var guide = program2.command("guide").description(t2("help.guide"));
|
|
30660
30921
|
guide.command("list").description(t2("help.guideList")).allowExcessArguments(false).addOption(format()).action((o) => runGuideList(o));
|
|
30661
30922
|
guide.command("show").description(t2("help.guideShow")).argument("<topic>", t2("help.guideTopic")).allowExcessArguments(false).addOption(format()).action((topic, o) => runGuideShow(topic, o));
|