gitifact 0.8.4 → 0.8.6
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 +1 -0
- package/dist/browser/assets/{HgiRefresh-CAJ0Xdvi.js → HgiRefresh-CnBE2KZ8.js} +1 -1
- package/dist/browser/assets/{Markdown-ev4hMr67.js → Markdown-75QVB57V.js} +1 -1
- package/dist/browser/assets/Selector-E8jyEKNB.js +2 -0
- package/dist/browser/assets/Tab-C-PhLRIZ.js +4 -0
- package/dist/browser/assets/{Table-XuC9zK9w.js → Table-Cr2jvka_.js} +2 -2
- package/dist/browser/assets/Token-BBk7tRek.js +2 -0
- package/dist/browser/assets/Token-CKcN25HT.css +1 -0
- package/dist/browser/assets/{about-vlKWfG7J.js → about-C3ewDfU2.js} +2 -2
- package/dist/browser/assets/activity-timeline-B3s0viEt.js +2 -0
- package/dist/browser/assets/changelog-DkRd6I8J.js +1 -0
- package/dist/browser/assets/commit-BHwKZ7hK.js +4 -0
- package/dist/browser/assets/{contributor-Bs3RWHQv.js → contributor-CqqvzxLh.js} +1 -1
- package/dist/browser/assets/contributors-CuMPZx6_.js +1 -0
- package/dist/browser/assets/{contributors._email-BR9sLgCs.js → contributors._email-CEcZZfAR.js} +1 -1
- package/dist/browser/assets/{contributors.index-FoYwG7VE.js → contributors.index-DNMBFxLb.js} +1 -1
- package/dist/browser/assets/dashboard.index-nV7KwM5H.js +1 -0
- package/dist/browser/assets/document-BnxE7Txb.js +2 -0
- package/dist/browser/assets/{document-DPtVyR5y.js → document-odLLdugz.js} +4 -4
- package/dist/browser/assets/features-C0YzZiS-.js +2 -0
- package/dist/browser/assets/features-FKxsPKab.css +1 -0
- package/dist/browser/assets/{features._featureId-xxpihTEs.js → features._featureId-Cmg8-2ku.js} +1 -1
- package/dist/browser/assets/{features.index-CO7APsrh.js → features.index-CBz7BmRW.js} +1 -1
- package/dist/browser/assets/getting-started-CaOhGSBe.js +1 -0
- package/dist/browser/assets/git-DwAnKiiN.js +1 -0
- package/dist/browser/assets/index-BljzO9go.js +49 -0
- package/dist/browser/assets/index-CswY1wJ4.css +1 -0
- package/dist/browser/assets/instructions-DWS_nwe0.js +1 -0
- package/dist/browser/assets/{instructions._instructionId-Bp9u9xx9.js → instructions._instructionId-l7aWWvfx.js} +1 -1
- package/dist/browser/assets/instructions.agents-t7hMe4Pv.js +1 -0
- package/dist/browser/assets/instructions.index-CHVCQBSH.js +1 -0
- package/dist/browser/assets/{lazyRouteComponent-D4lq6X5s.js → lazyRouteComponent-BZI8yQj_.js} +1 -1
- package/dist/browser/assets/load-more-BVsXjzHC.js +1 -0
- package/dist/browser/assets/page-header-CRcXie4p.js +248 -0
- package/dist/browser/assets/records._recordId-DF-NkdBL.js +1 -0
- package/dist/browser/assets/records.commits._commit-BBf_rxHJ.js +1 -0
- package/dist/browser/assets/records.docs._docId-Diev5opj.js +1 -0
- package/dist/browser/assets/records.index-DPWv9blV.js +1 -0
- package/dist/browser/assets/records.working-D5xv-dTD.js +1 -0
- package/dist/browser/assets/search-CbtiuqNx.js +1 -0
- package/dist/browser/assets/{settings-BNIy3TaP.js → settings-N1hE7l-i.js} +1 -1
- package/dist/browser/assets/{useInfiniteQuery-03AIcFvA.js → useInfiniteQuery-CrEm5UW2.js} +1 -1
- package/dist/browser/assets/{useKeyboardHint-DN1hAi8g.js → useKeyboardHint-CGJ2GVT3.js} +1 -1
- package/dist/browser/index.html +24 -24
- package/dist/i18n/en/changelog.md +26 -0
- package/dist/i18n/en/docs/design.md +2 -0
- package/dist/i18n/en/docs/spec.md +108 -7
- package/dist/i18n/ko/changelog.md +26 -0
- package/dist/i18n/ko/docs/design.md +2 -0
- package/dist/i18n/ko/docs/spec.md +108 -7
- package/dist/main.js +399 -174
- package/package.json +3 -3
- package/dist/browser/assets/Selector-CGOdL2eo.js +0 -2
- package/dist/browser/assets/Tab-BwJj0rUr.js +0 -1
- package/dist/browser/assets/Token-BV_4bSkY.js +0 -2
- package/dist/browser/assets/Token-Bqkc8eyB.css +0 -1
- package/dist/browser/assets/activity-timeline-Dmc-97N6.js +0 -2
- package/dist/browser/assets/changelog-6QcNKW8u.js +0 -1
- package/dist/browser/assets/commit-BcdbBdP4.js +0 -4
- package/dist/browser/assets/contributors-B_bVSY4J.js +0 -1
- package/dist/browser/assets/dashboard.index-BFp6Hqsf.js +0 -1
- package/dist/browser/assets/document-Q3lvgyX8.js +0 -2
- package/dist/browser/assets/features-CmvypKgf.js +0 -2
- package/dist/browser/assets/features-DUHxz0_L.css +0 -1
- package/dist/browser/assets/getting-started-11zYPwlJ.js +0 -1
- package/dist/browser/assets/git-CVY8qpaV.js +0 -1
- package/dist/browser/assets/index-BeeP8ZFW.js +0 -49
- package/dist/browser/assets/index-D1JeDnJc.css +0 -1
- package/dist/browser/assets/instructions-D3-EfbZG.js +0 -1
- package/dist/browser/assets/instructions.agents-DvFHo8x8.js +0 -1
- package/dist/browser/assets/instructions.index-zHzGHq7D.js +0 -1
- package/dist/browser/assets/load-more-CymfxLt7.js +0 -1
- package/dist/browser/assets/page-header-CVCjLFQo.js +0 -246
- package/dist/browser/assets/records._recordId-Be8aM0F-.js +0 -1
- package/dist/browser/assets/records.commits._commit-Dm3gX-bQ.js +0 -1
- package/dist/browser/assets/records.index-BgfJnGAl.js +0 -1
- package/dist/browser/assets/records.working-Eeag2L5N.js +0 -1
- package/dist/browser/assets/search-CSSuO-jR.js +0 -1
package/dist/main.js
CHANGED
|
@@ -3409,6 +3409,7 @@ var messages_default = {
|
|
|
3409
3409
|
"config.schemaFields": "schemaVersion\uACFC baseline \uC124\uC815 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
3410
3410
|
"config.cliVersion": "\uC124\uC815\uC758 cli\uB294 0.8.3 \uAC19\uC740 \uBC30\uD3EC \uBC84\uC804\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
3411
3411
|
"config.language": "\uC124\uC815\uC758 language\uB294 {languages} \uC911 \uD558\uB098\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
3412
|
+
"config.requirementStyle": "\uC124\uC815\uC758 requirementStyle\uC740 {styles} \uC911 \uD558\uB098\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
3412
3413
|
"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}",
|
|
3413
3414
|
"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}",
|
|
3414
3415
|
"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}",
|
|
@@ -3517,6 +3518,12 @@ var messages_default = {
|
|
|
3517
3518
|
"warn.ASSET_EXTENSION": "\uBE0C\uB77C\uC6B0\uC800\uAC00 \uBBF8\uB9AC \uBCF4\uC5EC \uC8FC\uC9C0 \uC54A\uB294 \uD655\uC7A5\uC790\uB77C \uB0B4\uB824\uBC1B\uAE30\uB85C\uB9CC \uC5F4\uB9BD\uB2C8\uB2E4: {path}",
|
|
3518
3519
|
"warn.UNREFERENCED_ASSET": "\uC5B4\uB5A4 \uBB38\uC11C\uB3C4 \uAC00\uB9AC\uD0A4\uC9C0 \uC54A\uB294 \uC5D0\uC14B\uC785\uB2C8\uB2E4: {path}",
|
|
3519
3520
|
"warn.ASSETS_TOTAL_SIZE": "\uC5D0\uC14B \uC804\uCCB4\uAC00 \uAD8C\uC7A5 \uD06C\uAE30(50MB)\uB97C \uB118\uC2B5\uB2C8\uB2E4: {bytes}\uBC14\uC774\uD2B8",
|
|
3521
|
+
"warn.DESIGN_OVERVIEW_LARGE": "\uC124\uACC4 overview.md\uC758 \uC808\uC774 {sections}\uAC1C\uC785\uB2C8\uB2E4. \uB367\uBD99\uC774\uAE30 \uC804\uC5D0 \uCD95 \uD30C\uC77C\uB85C \uB098\uB20C\uC9C0 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB3C\uC73C\uC138\uC694(guide show design\uC758 \uAC1C\uC815): {path}",
|
|
3522
|
+
"warn.REQUIREMENT_SCOPE_FORMAT": "\uBC94\uC704\uC640 \uC81C\uC57D\uC740 \uC218\uC6A9 \uC870\uAC74 \uC55E\uC5D0 - \uBAA9\uB85D\uC73C\uB85C\uB9CC \uC501\uB2C8\uB2E4(guide show spec): {path}",
|
|
3523
|
+
"warn.REQUIREMENT_CRITERIA_FORMAT": "\uC218\uC6A9 \uC870\uAC74 \uC544\uB798\uC5D0\uB294 \uBC88\uD638 \uD56D\uBAA9\uB9CC \uB461\uB2C8\uB2E4. \uADDC\uCE59\uC740 \uBC94\uC704\uC640 \uC81C\uC57D\uC73C\uB85C \uC62E\uAE30\uC138\uC694(guide show spec): {path}",
|
|
3524
|
+
"warn.REQUIREMENT_FLOW_FORMAT": "\uC720\uC988\uCF00\uC774\uC2A4 \uC694\uAD6C\uC0AC\uD56D\uC5D0\uB294 \uAE30\uBCF8 \uD750\uB984\uC774 \uC788\uC5B4\uC57C \uD558\uACE0, \uC808\uC740 \uBC94\uC704\uC640 \uC81C\uC57D\xB7\uC0AC\uC804 \uC870\uAC74\xB7\uAE30\uBCF8 \uD750\uB984\xB7\uB300\uCCB4 \uD750\uB984\xB7\uC0AC\uD6C4 \uC870\uAC74\xB7\uC218\uC6A9 \uC870\uAC74 \uC21C\uC11C\uC785\uB2C8\uB2E4(guide show spec): {path}",
|
|
3525
|
+
"warn.REQUIREMENT_PATH_FORMAT": "\uC720\uC988\uCF00\uC774\uC2A4 \uC694\uAD6C\uC0AC\uD56D\uC758 \uC218\uC6A9 \uC870\uAC74\uB9C8\uB2E4 \uACBD\uB85C: \uC904\uC744 \uB450\uACE0, \uAE30\uBCF8 \uD750\uB984\uACFC \uC774 \uC694\uAD6C\uC0AC\uD56D\uC758 \uB300\uCCB4 \uD750\uB984(A1\u2026)\uB9CC \uAC00\uB9AC\uD0B5\uB2C8\uB2E4(guide show spec): {path}",
|
|
3526
|
+
"warn.REQUIREMENT_STYLE_MISSING": "\uC774 \uD504\uB85C\uC81D\uD2B8\uB294 \uC694\uAD6C\uC0AC\uD56D\uC744 \uC720\uC988\uCF00\uC774\uC2A4\uB85C \uC501\uB2C8\uB2E4(config\uC758 requirementStyle). \uD504\uB860\uD2B8\uB9E4\uD130\uC5D0 style: usecase\uB97C, \uAE30\uBCF8 \uD615\uC2DD\uC73C\uB85C \uB458 \uC694\uAD6C\uC0AC\uD56D\uC774\uBA74 style: default\uB97C \uC801\uC73C\uC138\uC694(guide show spec): {path}",
|
|
3520
3527
|
"config.migrationRequired": "\uC774 \uD504\uB85C\uC81D\uD2B8\uB294 0.7 \uC800\uC7A5 \uADDC\uC57D(schemaVersion 2)\uC785\uB2C8\uB2E4. 0.8.0 CLI\uB294 \uC61B \uD615\uC2DD\uC744 \uC77D\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. gitifact guide show migrate\uC758 \uC808\uCC28\uB85C \uBB38\uC11C\uB97C \uC0C8 \uAD6C\uC870\uB85C \uC62E\uAE30\uC138\uC694."
|
|
3521
3528
|
};
|
|
3522
3529
|
|
|
@@ -3528,6 +3535,7 @@ var messages_default2 = {
|
|
|
3528
3535
|
"config.schemaFields": "Check the schemaVersion and baseline fields.",
|
|
3529
3536
|
"config.cliVersion": "The config field cli must be a release version such as 0.8.3.",
|
|
3530
3537
|
"config.language": "The config field language must be one of {languages}.",
|
|
3538
|
+
"config.requirementStyle": "The config field requirementStyle must be one of {styles}.",
|
|
3531
3539
|
"document.pathTooLong": "Wiki page path exceeds the depth or length limit: {path}",
|
|
3532
3540
|
"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}",
|
|
3533
3541
|
"document.folderName": "Wiki folder names must use lowercase letters, digits and hyphens: {path}",
|
|
@@ -3636,6 +3644,12 @@ var messages_default2 = {
|
|
|
3636
3644
|
"warn.ASSET_EXTENSION": "The browser does not preview this extension and offers it only as a download: {path}",
|
|
3637
3645
|
"warn.UNREFERENCED_ASSET": "No document refers to this asset: {path}",
|
|
3638
3646
|
"warn.ASSETS_TOTAL_SIZE": "All assets together are over the recommended size (50 MB): {bytes} bytes",
|
|
3647
|
+
"warn.DESIGN_OVERVIEW_LARGE": "The design overview.md has {sections} sections. Before adding to it, ask the user whether to split it into axis files (revising, in guide show design): {path}",
|
|
3648
|
+
"warn.REQUIREMENT_SCOPE_FORMAT": "Scope and constraints come before the acceptance criteria, as - items only (guide show spec): {path}",
|
|
3649
|
+
"warn.REQUIREMENT_CRITERIA_FORMAT": "The acceptance criteria hold numbered items only; move rules to scope and constraints (guide show spec): {path}",
|
|
3650
|
+
"warn.REQUIREMENT_FLOW_FORMAT": "A use-case requirement has a basic flow, and its sections run scope and constraints, preconditions, basic flow, alternative flows, postconditions, acceptance criteria (guide show spec): {path}",
|
|
3651
|
+
"warn.REQUIREMENT_PATH_FORMAT": "Each acceptance criterion of a use-case requirement has a Path: line naming only the basic flow and this requirement's alternative flows (A1\u2026) (guide show spec): {path}",
|
|
3652
|
+
"warn.REQUIREMENT_STYLE_MISSING": "This project writes requirements as use cases (config requirementStyle). Add style: usecase to the frontmatter, or style: default for a requirement that keeps the default shape (guide show spec): {path}",
|
|
3639
3653
|
"config.migrationRequired": "This project uses the 0.7 storage convention (schemaVersion 2). The 0.8.0 CLI does not read the old format. Move the documents to the new structure by following gitifact guide show migrate."
|
|
3640
3654
|
};
|
|
3641
3655
|
|
|
@@ -3676,6 +3690,29 @@ async function readRepositoryStatus(reader, services) {
|
|
|
3676
3690
|
};
|
|
3677
3691
|
}
|
|
3678
3692
|
|
|
3693
|
+
// ../../packages/core/dist/domain/document.js
|
|
3694
|
+
var DOC_ID_PREFIX = { feature: "S", requirement: "R", design: "D", wiki: "W", instruction: "I" };
|
|
3695
|
+
var RECORD_ID_PREFIX = "DR";
|
|
3696
|
+
var token = "[a-z2-7]{10}";
|
|
3697
|
+
var docIdPattern = new RegExp(`^[SRDWI]-${token}$`);
|
|
3698
|
+
var recordIdPattern = new RegExp(`^DR-${token}$`);
|
|
3699
|
+
var reasonIdPattern = new RegExp(`^H-${token}$`);
|
|
3700
|
+
var idPatternOf = (kind2) => new RegExp(`^${DOC_ID_PREFIX[kind2]}-${token}$`);
|
|
3701
|
+
var kindOfId = (id) => Object.entries(DOC_ID_PREFIX).find(([, prefix]) => id.startsWith(prefix + "-"))?.[0];
|
|
3702
|
+
var requirementStyles = ["default", "usecase"];
|
|
3703
|
+
var docWarning = (code, path3, values = {}) => ({ code, path: path3, message: t(`warn.${code}`, { path: path3, ...values }) });
|
|
3704
|
+
var docProblem = (code, path3, values = {}) => ({ code, path: path3, message: t(`doc.${code}`, { path: path3, ...values }) });
|
|
3705
|
+
var DocumentError = class extends Error {
|
|
3706
|
+
code;
|
|
3707
|
+
path;
|
|
3708
|
+
constructor(code, path3, message) {
|
|
3709
|
+
super(message);
|
|
3710
|
+
this.code = code;
|
|
3711
|
+
this.path = path3;
|
|
3712
|
+
this.name = "DocumentError";
|
|
3713
|
+
}
|
|
3714
|
+
};
|
|
3715
|
+
|
|
3679
3716
|
// ../../packages/core/dist/formats/spec-project.js
|
|
3680
3717
|
var InitError = class extends Error {
|
|
3681
3718
|
code;
|
|
@@ -3740,6 +3777,11 @@ function parseManagedConfig(text4) {
|
|
|
3740
3777
|
throw new InitError("INVALID_CONFIG", t("config.language", { languages: PROJECT_LANGUAGES.join(", ") }));
|
|
3741
3778
|
config2.language = value.language;
|
|
3742
3779
|
}
|
|
3780
|
+
if ("requirementStyle" in value) {
|
|
3781
|
+
if (!requirementStyles.includes(value.requirementStyle))
|
|
3782
|
+
throw new InitError("INVALID_CONFIG", t("config.requirementStyle", { styles: requirementStyles.join(", ") }));
|
|
3783
|
+
config2.requirementStyle = value.requirementStyle;
|
|
3784
|
+
}
|
|
3743
3785
|
return config2;
|
|
3744
3786
|
}
|
|
3745
3787
|
function formatManagedConfig(config2, previous) {
|
|
@@ -3747,7 +3789,7 @@ function formatManagedConfig(config2, previous) {
|
|
|
3747
3789
|
if (previous !== void 0) {
|
|
3748
3790
|
const value = JSON.parse(previous);
|
|
3749
3791
|
if (object(value)) {
|
|
3750
|
-
const { schemaVersion: _s, baseline: _b, cli: _c, language: _l, ...rest } = value;
|
|
3792
|
+
const { schemaVersion: _s, baseline: _b, cli: _c, language: _l, requirementStyle: _r, ...rest } = value;
|
|
3751
3793
|
unknown2 = rest;
|
|
3752
3794
|
}
|
|
3753
3795
|
}
|
|
@@ -3755,7 +3797,8 @@ function formatManagedConfig(config2, previous) {
|
|
|
3755
3797
|
schemaVersion: config2.schemaVersion,
|
|
3756
3798
|
baseline: config2.baseline,
|
|
3757
3799
|
...config2.cli === void 0 ? {} : { cli: config2.cli },
|
|
3758
|
-
...config2.language === void 0 ? {} : { language: config2.language }
|
|
3800
|
+
...config2.language === void 0 ? {} : { language: config2.language },
|
|
3801
|
+
...config2.requirementStyle === void 0 ? {} : { requirementStyle: config2.requirementStyle }
|
|
3759
3802
|
};
|
|
3760
3803
|
return JSON.stringify({ ...known, ...unknown2 }, null, 2) + "\n";
|
|
3761
3804
|
}
|
|
@@ -3828,7 +3871,7 @@ var WIKI_DIR = ".gitifact/wiki";
|
|
|
3828
3871
|
var WIKI_HISTORY_PATH = WIKI_DIR + "/history.jsonl";
|
|
3829
3872
|
var WIKI_ENTRY = "README.md";
|
|
3830
3873
|
var WIKI_ENTRY_PATH = WIKI_DIR + "/" + WIKI_ENTRY;
|
|
3831
|
-
var
|
|
3874
|
+
var token2 = "[a-z2-7]{10}";
|
|
3832
3875
|
var STORE_DIR = ".gitifact";
|
|
3833
3876
|
var marker = "gitifact";
|
|
3834
3877
|
var recordPathPattern = /^(?:\.gitifact\/spec\/[^/]+\/(?:requirements\.md|design\.md|history\.jsonl)|\.gitifact\/wiki\/(?:(?:[^/]+\/)*[^/]+\.md|history\.jsonl))$/;
|
|
@@ -3847,7 +3890,7 @@ function validateDocumentRelativePath(relative) {
|
|
|
3847
3890
|
if (!nameToken.test(part) || part.length > 80)
|
|
3848
3891
|
fail(t("document.folderName", { path: relative }));
|
|
3849
3892
|
}
|
|
3850
|
-
var reqId = new RegExp(`^R-${
|
|
3893
|
+
var reqId = new RegExp(`^R-${token2}$`);
|
|
3851
3894
|
var fail = (message) => {
|
|
3852
3895
|
throw new StoreError(message);
|
|
3853
3896
|
};
|
|
@@ -3860,20 +3903,20 @@ var scalar = (value) => {
|
|
|
3860
3903
|
fail(t("frontmatter.scalar", { value }));
|
|
3861
3904
|
return value;
|
|
3862
3905
|
};
|
|
3863
|
-
function parseFrontmatter(
|
|
3864
|
-
const legacy = new RegExp(`^<!-- ${marker}-(?:${kind2 === "wiki" ? "product|guide" : kind2}): (${legacyIds}-${
|
|
3906
|
+
function parseFrontmatter(lines2, kind2, legacyIds) {
|
|
3907
|
+
const legacy = new RegExp(`^<!-- ${marker}-(?:${kind2 === "wiki" ? "product|guide" : kind2}): (${legacyIds}-${token2}) -->$`).exec(lines2[0] ?? "");
|
|
3865
3908
|
if (legacy) {
|
|
3866
|
-
|
|
3909
|
+
lines2.shift();
|
|
3867
3910
|
return { id: legacy[1] };
|
|
3868
3911
|
}
|
|
3869
|
-
if (
|
|
3912
|
+
if (lines2[0] !== "---")
|
|
3870
3913
|
fail(t("frontmatter.required"));
|
|
3871
|
-
|
|
3872
|
-
const end =
|
|
3914
|
+
lines2.shift();
|
|
3915
|
+
const end = lines2.indexOf("---");
|
|
3873
3916
|
if (end === -1)
|
|
3874
3917
|
fail(t("frontmatter.unclosed"));
|
|
3875
|
-
const block =
|
|
3876
|
-
|
|
3918
|
+
const block = lines2.splice(0, end);
|
|
3919
|
+
lines2.shift();
|
|
3877
3920
|
const fields2 = /* @__PURE__ */ new Map();
|
|
3878
3921
|
for (let i = 0; i < block.length; i++) {
|
|
3879
3922
|
const line2 = block[i];
|
|
@@ -3909,7 +3952,7 @@ function parseFrontmatter(lines, kind2, legacyIds) {
|
|
|
3909
3952
|
fields2.set("sources", sources3);
|
|
3910
3953
|
}
|
|
3911
3954
|
const id = fields2.get("id");
|
|
3912
|
-
if (typeof id !== "string" || !new RegExp(`^(?:${legacyIds})-${
|
|
3955
|
+
if (typeof id !== "string" || !new RegExp(`^(?:${legacyIds})-${token2}$`).test(id))
|
|
3913
3956
|
fail(t("frontmatter.id", { kind: kind2 }));
|
|
3914
3957
|
for (const key of fields2.keys())
|
|
3915
3958
|
if (key !== "id" && !(key === "sources" && kind2 === "design"))
|
|
@@ -3938,17 +3981,17 @@ function validateSource(value) {
|
|
|
3938
3981
|
function parseDesign(source2, specId) {
|
|
3939
3982
|
if (source2.includes("\0") || /\r(?!\n)/.test(source2))
|
|
3940
3983
|
fail(t("design.invalidCharacters"));
|
|
3941
|
-
const
|
|
3942
|
-
const front = parseFrontmatter(
|
|
3984
|
+
const lines2 = normalized(source2).split("\n");
|
|
3985
|
+
const front = parseFrontmatter(lines2, "design", "S");
|
|
3943
3986
|
if (front.id !== specId)
|
|
3944
3987
|
fail(t("design.idMismatch"));
|
|
3945
|
-
while (
|
|
3946
|
-
|
|
3947
|
-
const heading =
|
|
3988
|
+
while (lines2[0] === "")
|
|
3989
|
+
lines2.shift();
|
|
3990
|
+
const heading = lines2.shift();
|
|
3948
3991
|
if (!heading?.startsWith("# ") || !heading.slice(2).trim())
|
|
3949
3992
|
fail(t("design.titleRequired"));
|
|
3950
3993
|
const title = heading.slice(2).trim();
|
|
3951
|
-
const raw = normalized(
|
|
3994
|
+
const raw = normalized(lines2.join("\n"));
|
|
3952
3995
|
if (!raw)
|
|
3953
3996
|
fail(t("design.bodyRequired"));
|
|
3954
3997
|
const references = /* @__PURE__ */ new Set();
|
|
@@ -3986,15 +4029,15 @@ function parseDocument(path3, source2) {
|
|
|
3986
4029
|
validateDocumentRelativePath(match[1]);
|
|
3987
4030
|
if (source2.includes("\0") || /\r(?!\n)/.test(source2))
|
|
3988
4031
|
fail(t("document.invalidCharacters", { path: path3 }));
|
|
3989
|
-
const
|
|
3990
|
-
const { id } = parseFrontmatter(
|
|
3991
|
-
while (
|
|
3992
|
-
|
|
3993
|
-
const heading =
|
|
4032
|
+
const lines2 = normalized(source2).split("\n");
|
|
4033
|
+
const { id } = parseFrontmatter(lines2, "wiki", "W");
|
|
4034
|
+
while (lines2[0] === "")
|
|
4035
|
+
lines2.shift();
|
|
4036
|
+
const heading = lines2.shift();
|
|
3994
4037
|
if (!heading?.startsWith("# ") || !heading.slice(2).trim())
|
|
3995
4038
|
fail(t("document.titleRequired", { path: path3 }));
|
|
3996
4039
|
const title = heading.slice(2).trim();
|
|
3997
|
-
const body2 = normalized(
|
|
4040
|
+
const body2 = normalized(lines2.join("\n"));
|
|
3998
4041
|
if (!body2)
|
|
3999
4042
|
fail(t("document.bodyRequired", { path: path3 }));
|
|
4000
4043
|
let fence;
|
|
@@ -4081,8 +4124,8 @@ function parseSpec(path3, source2, history = "", designSource) {
|
|
|
4081
4124
|
fail(t("spec.unsupportedPath", { path: path3 }));
|
|
4082
4125
|
if (source2.includes("\0") || source2.includes("\r") && /\r(?!\n)/.test(source2))
|
|
4083
4126
|
fail(t("spec.invalidCharacters", { path: path3 }));
|
|
4084
|
-
const
|
|
4085
|
-
const specId = parseFrontmatter(
|
|
4127
|
+
const lines2 = normalized(source2).split("\n");
|
|
4128
|
+
const specId = parseFrontmatter(lines2, "spec", "S").id;
|
|
4086
4129
|
let title = "";
|
|
4087
4130
|
let description = "";
|
|
4088
4131
|
let current2;
|
|
@@ -4095,10 +4138,10 @@ function parseSpec(path3, source2, history = "", designSource) {
|
|
|
4095
4138
|
else
|
|
4096
4139
|
description += line2 + "\n";
|
|
4097
4140
|
};
|
|
4098
|
-
for (let i = 0; i <
|
|
4099
|
-
const line2 =
|
|
4141
|
+
for (let i = 0; i < lines2.length; i++) {
|
|
4142
|
+
const line2 = lines2[i];
|
|
4100
4143
|
if (waitingId) {
|
|
4101
|
-
const match = new RegExp(`^<!-- ${marker}-req: (R-${
|
|
4144
|
+
const match = new RegExp(`^<!-- ${marker}-req: (R-${token2}) -->$`).exec(line2);
|
|
4102
4145
|
if (!match || !current2)
|
|
4103
4146
|
fail(t("spec.requirementIdRequired", { path: path3 }));
|
|
4104
4147
|
current2.id = match[1];
|
|
@@ -4170,7 +4213,7 @@ function parseHistory(source2, scope = "spec") {
|
|
|
4170
4213
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
4171
4214
|
fail(t("history.invalidRecord"));
|
|
4172
4215
|
const r = value;
|
|
4173
|
-
if (!shapes.includes(Object.keys(r).sort().join(",")) || typeof r.id !== "string" || !new RegExp(`^H-${
|
|
4216
|
+
if (!shapes.includes(Object.keys(r).sort().join(",")) || typeof r.id !== "string" || !new RegExp(`^H-${token2}$`).test(r.id) || ids.has(r.id) || typeof r.reason !== "string" || !r.reason.trim() || !Array.isArray(r.requirements) || !r.requirements.length && !Array.isArray(r.designs) && !Array.isArray(r.documents) || r.documents !== void 0 && (r.requirements.length || !Array.isArray(r.documents) || !r.documents.length || r.documents.some((id) => typeof id !== "string" || !/^W-[a-z2-7]{10}$/.test(id)) || new Set(r.documents).size !== r.documents.length) || r.designs !== void 0 && (!Array.isArray(r.designs) || !r.designs.length || r.designs.some((id) => typeof id !== "string" || !/^S-[a-z2-7]{10}$/.test(id)) || new Set(r.designs).size !== r.designs.length) || r.requirements.some((id) => typeof id !== "string" || !reqId.test(id)) || new Set(r.requirements).size !== r.requirements.length)
|
|
4174
4217
|
fail(t("history.invalidFields"));
|
|
4175
4218
|
ids.add(r.id);
|
|
4176
4219
|
records2.push({ id: r.id, requirements: r.requirements, ...r.designs === void 0 ? {} : { designs: r.designs }, ...r.documents === void 0 ? {} : { documents: r.documents }, reason: r.reason });
|
|
@@ -4289,28 +4332,6 @@ function compareStoreBundles(a, b) {
|
|
|
4289
4332
|
return { specChanges: specs2.specChanges, changes: [...specs2.changes, ...compareWikis(a.wiki, b.wiki)] };
|
|
4290
4333
|
}
|
|
4291
4334
|
|
|
4292
|
-
// ../../packages/core/dist/domain/document.js
|
|
4293
|
-
var DOC_ID_PREFIX = { feature: "S", requirement: "R", design: "D", wiki: "W", instruction: "I" };
|
|
4294
|
-
var RECORD_ID_PREFIX = "DR";
|
|
4295
|
-
var token2 = "[a-z2-7]{10}";
|
|
4296
|
-
var docIdPattern = new RegExp(`^[SRDWI]-${token2}$`);
|
|
4297
|
-
var recordIdPattern = new RegExp(`^DR-${token2}$`);
|
|
4298
|
-
var reasonIdPattern = new RegExp(`^H-${token2}$`);
|
|
4299
|
-
var idPatternOf = (kind2) => new RegExp(`^${DOC_ID_PREFIX[kind2]}-${token2}$`);
|
|
4300
|
-
var kindOfId = (id) => Object.entries(DOC_ID_PREFIX).find(([, prefix]) => id.startsWith(prefix + "-"))?.[0];
|
|
4301
|
-
var docWarning = (code, path3, values = {}) => ({ code, path: path3, message: t(`warn.${code}`, { path: path3, ...values }) });
|
|
4302
|
-
var docProblem = (code, path3, values = {}) => ({ code, path: path3, message: t(`doc.${code}`, { path: path3, ...values }) });
|
|
4303
|
-
var DocumentError = class extends Error {
|
|
4304
|
-
code;
|
|
4305
|
-
path;
|
|
4306
|
-
constructor(code, path3, message) {
|
|
4307
|
-
super(message);
|
|
4308
|
-
this.code = code;
|
|
4309
|
-
this.path = path3;
|
|
4310
|
-
this.name = "DocumentError";
|
|
4311
|
-
}
|
|
4312
|
-
};
|
|
4313
|
-
|
|
4314
4335
|
// ../../packages/core/dist/domain/record.js
|
|
4315
4336
|
var recordSectionKeys = ["context", "decision", "alternatives"];
|
|
4316
4337
|
var RECORD_REQUIRED_SECTIONS = ["context", "decision"];
|
|
@@ -4336,13 +4357,13 @@ function quoteScalar(value) {
|
|
|
4336
4357
|
return plain2 ? value : '"' + value.replace(/[\\"]/g, "\\$&") + '"';
|
|
4337
4358
|
}
|
|
4338
4359
|
function parseFrontmatterBlock(source2, path3) {
|
|
4339
|
-
const
|
|
4340
|
-
if (
|
|
4360
|
+
const lines2 = source2.split("\n");
|
|
4361
|
+
if (lines2[0] !== "---")
|
|
4341
4362
|
throw new DocumentError("FRONTMATTER_REQUIRED", path3, t("doc.FRONTMATTER_REQUIRED", { path: path3 }));
|
|
4342
|
-
const end =
|
|
4363
|
+
const end = lines2.indexOf("---", 1);
|
|
4343
4364
|
if (end === -1)
|
|
4344
4365
|
throw new DocumentError("FRONTMATTER_UNCLOSED", path3, t("doc.FRONTMATTER_UNCLOSED", { path: path3 }));
|
|
4345
|
-
const block =
|
|
4366
|
+
const block = lines2.slice(1, end);
|
|
4346
4367
|
const fields2 = /* @__PURE__ */ new Map();
|
|
4347
4368
|
const bad = (line2) => new DocumentError("FRONTMATTER_LINE", path3, t("doc.FRONTMATTER_LINE", { path: path3, line: line2 }));
|
|
4348
4369
|
for (let i = 0; i < block.length; i++) {
|
|
@@ -4385,7 +4406,7 @@ function parseFrontmatterBlock(source2, path3) {
|
|
|
4385
4406
|
throw bad(line2);
|
|
4386
4407
|
fields2.set(key, scalars.length ? { type: "list", items: scalars } : { type: "maps", items: maps });
|
|
4387
4408
|
}
|
|
4388
|
-
return { fields: fields2, body:
|
|
4409
|
+
return { fields: fields2, body: lines2.slice(end + 1).join("\n") };
|
|
4389
4410
|
}
|
|
4390
4411
|
function renderFrontmatterBlock(fields2) {
|
|
4391
4412
|
const out = ["---"];
|
|
@@ -4577,7 +4598,7 @@ function classifyDocPath(path3) {
|
|
|
4577
4598
|
}
|
|
4578
4599
|
var KEYS2 = {
|
|
4579
4600
|
feature: ["id", "title", "description", "draft"],
|
|
4580
|
-
requirement: ["id", "title", "description", "order", "draft"],
|
|
4601
|
+
requirement: ["id", "title", "description", "order", "style", "draft"],
|
|
4581
4602
|
design: ["id", "title", "description", "order", "requirements", "sources", "draft"],
|
|
4582
4603
|
wiki: ["id", "title", "description", "draft"],
|
|
4583
4604
|
instruction: ["id", "title", "description", "draft"]
|
|
@@ -4683,8 +4704,12 @@ function parseDocumentFile(path3, source2) {
|
|
|
4683
4704
|
return { kind: "wiki", ...common };
|
|
4684
4705
|
if (where.kind === "instruction")
|
|
4685
4706
|
return { kind: "instruction", name: where.name, ...common };
|
|
4686
|
-
if (where.kind === "requirement")
|
|
4687
|
-
|
|
4707
|
+
if (where.kind === "requirement") {
|
|
4708
|
+
const style2 = fields2.get("style");
|
|
4709
|
+
if (style2 && (style2.type !== "scalar" || !requirementStyles.includes(style2.value)))
|
|
4710
|
+
throw new DocumentError("FRONTMATTER_VALUE", path3, t("doc.FRONTMATTER_VALUE", { path: path3, value: "style" }));
|
|
4711
|
+
return { kind: "requirement", feature: where.feature, order: order(), ...style2 ? { style: style2.value } : {}, ...common };
|
|
4712
|
+
}
|
|
4688
4713
|
const refs = fields2.get("requirements");
|
|
4689
4714
|
if (refs && (refs.type !== "list" || refs.items.some((r) => !idPatternOf("requirement").test(r)) || new Set(refs.items).size !== refs.items.length)) {
|
|
4690
4715
|
throw new DocumentError("FRONTMATTER_VALUE", path3, t("doc.FRONTMATTER_VALUE", { path: path3, value: "requirements" }));
|
|
@@ -4710,6 +4735,7 @@ function renderDocumentFile(doc) {
|
|
|
4710
4735
|
["title", doc.title],
|
|
4711
4736
|
["description", doc.description],
|
|
4712
4737
|
["order", doc.kind === "requirement" || doc.kind === "design" ? doc.order : void 0],
|
|
4738
|
+
["style", doc.kind === "requirement" ? doc.style : void 0],
|
|
4713
4739
|
["requirements", doc.kind === "design" ? doc.requirements : void 0],
|
|
4714
4740
|
["sources", doc.kind === "design" ? doc.sources.map((s) => ({ ...s })) : void 0],
|
|
4715
4741
|
["draft", doc.draft ? true : void 0]
|
|
@@ -4929,6 +4955,7 @@ function compareDocumentSets(before, after) {
|
|
|
4929
4955
|
}
|
|
4930
4956
|
|
|
4931
4957
|
// ../../packages/core/dist/use-cases/document-warnings.js
|
|
4958
|
+
var OVERVIEW_SECTION_LIMIT = 7;
|
|
4932
4959
|
function documentBodyLinks(documents) {
|
|
4933
4960
|
return documents.flatMap((doc) => extractLinks(doc.body).flatMap((link3) => {
|
|
4934
4961
|
const target = resolveLink(doc.path, link3);
|
|
@@ -4963,6 +4990,79 @@ function documentWarnings(documents, assets, existing) {
|
|
|
4963
4990
|
}
|
|
4964
4991
|
if (total > ASSETS_TOTAL_LIMIT)
|
|
4965
4992
|
warnings.push(docWarning("ASSETS_TOTAL_SIZE", ASSETS_DIR, { bytes: total }));
|
|
4993
|
+
for (const doc of documents) {
|
|
4994
|
+
if (doc.kind !== "design" || !doc.path.endsWith("/design/overview.md"))
|
|
4995
|
+
continue;
|
|
4996
|
+
const sections2 = lines(doc.body).filter((line2) => /^##\s/.test(line2)).length;
|
|
4997
|
+
if (sections2 >= OVERVIEW_SECTION_LIMIT)
|
|
4998
|
+
warnings.push(docWarning("DESIGN_OVERVIEW_LARGE", doc.path, { sections: sections2 }));
|
|
4999
|
+
}
|
|
5000
|
+
return warnings;
|
|
5001
|
+
}
|
|
5002
|
+
var lines = (body2) => body2.replace(/\r\n/g, "\n").split("\n");
|
|
5003
|
+
var scopeHeading = /^###\s+(?:범위와 제약|scope and constraints)\s*$/i;
|
|
5004
|
+
var acceptanceHeading = /^###\s+(?:수용 조건|acceptance criteria)\s*$/i;
|
|
5005
|
+
var useCaseSections = [
|
|
5006
|
+
["scope", scopeHeading],
|
|
5007
|
+
["preconditions", /^###\s+(?:사전 조건|preconditions)\s*$/i],
|
|
5008
|
+
["basic", /^###\s+(?:기본 흐름|basic flow)\s*$/i],
|
|
5009
|
+
["alternatives", /^###\s+(?:대체 흐름|alternative flows?)\s*$/i],
|
|
5010
|
+
["postconditions", /^###\s+(?:사후 조건|postconditions)\s*$/i],
|
|
5011
|
+
["acceptance", acceptanceHeading]
|
|
5012
|
+
];
|
|
5013
|
+
var pathLine = /^\s*(?:경로|path)\s*:\s*(.*)$/i;
|
|
5014
|
+
var basicFlowName = /^(?:기본 흐름|basic flow)$/i;
|
|
5015
|
+
var alternativeId = /^-\s+(?:\*\*)?(A\d+)\b/;
|
|
5016
|
+
function requirementFormatWarnings(doc, projectStyle) {
|
|
5017
|
+
if (doc.kind !== "requirement")
|
|
5018
|
+
return [];
|
|
5019
|
+
const missing2 = projectStyle === "usecase" && !doc.style ? [docWarning("REQUIREMENT_STYLE_MISSING", doc.path)] : [];
|
|
5020
|
+
const body2 = lines(doc.body);
|
|
5021
|
+
const scope = body2.findIndex((line2) => scopeHeading.test(line2.trim()));
|
|
5022
|
+
const acceptance = body2.findIndex((line2) => acceptanceHeading.test(line2.trim()));
|
|
5023
|
+
const sectionOf = (start) => {
|
|
5024
|
+
const rest = body2.slice(start + 1);
|
|
5025
|
+
const end = rest.findIndex((line2) => /^#{1,3}\s/.test(line2));
|
|
5026
|
+
return end < 0 ? rest : rest.slice(0, end);
|
|
5027
|
+
};
|
|
5028
|
+
const outside = (section2, item) => section2.some((line2) => line2.trim() !== "" && !item.test(line2) && !/^\s+\S/.test(line2));
|
|
5029
|
+
const warnings = [];
|
|
5030
|
+
if (scope >= 0 && (acceptance >= 0 && scope > acceptance || outside(sectionOf(scope), /^- /)))
|
|
5031
|
+
warnings.push(docWarning("REQUIREMENT_SCOPE_FORMAT", doc.path));
|
|
5032
|
+
if (acceptance >= 0 && (outside(sectionOf(acceptance), /^\d+\.\s/) || body2.slice(acceptance + 1).some((line2) => /^#{1,3}\s/.test(line2) && !scopeHeading.test(line2.trim()))))
|
|
5033
|
+
warnings.push(docWarning("REQUIREMENT_CRITERIA_FORMAT", doc.path));
|
|
5034
|
+
if (doc.style === "usecase")
|
|
5035
|
+
warnings.push(...useCaseWarnings(doc.path, body2, sectionOf, acceptance));
|
|
5036
|
+
return [...missing2, ...warnings];
|
|
5037
|
+
}
|
|
5038
|
+
function useCaseWarnings(path3, body2, sectionOf, acceptance) {
|
|
5039
|
+
const warnings = [];
|
|
5040
|
+
const found = useCaseSections.map(([key, heading]) => ({ key, at: body2.findIndex((line2) => heading.test(line2.trim())) })).filter((s) => s.at >= 0);
|
|
5041
|
+
const ordered = found.every((s, i) => i === 0 || s.at > found[i - 1].at);
|
|
5042
|
+
if (!found.some((s) => s.key === "basic") || !ordered)
|
|
5043
|
+
warnings.push(docWarning("REQUIREMENT_FLOW_FORMAT", path3));
|
|
5044
|
+
if (acceptance < 0)
|
|
5045
|
+
return warnings;
|
|
5046
|
+
const alternatives = found.find((s) => s.key === "alternatives");
|
|
5047
|
+
const defined = new Set(alternatives ? sectionOf(alternatives.at).flatMap((line2) => {
|
|
5048
|
+
const m = alternativeId.exec(line2);
|
|
5049
|
+
return m ? [m[1]] : [];
|
|
5050
|
+
}) : []);
|
|
5051
|
+
const items2 = [];
|
|
5052
|
+
for (const line2 of sectionOf(acceptance)) {
|
|
5053
|
+
if (/^\d+\.\s/.test(line2))
|
|
5054
|
+
items2.push([line2.replace(/^\d+\.\s+/, "")]);
|
|
5055
|
+
else if (items2.length && /^\s+\S/.test(line2))
|
|
5056
|
+
items2[items2.length - 1].push(line2);
|
|
5057
|
+
}
|
|
5058
|
+
const named = (flow) => basicFlowName.test(flow) || defined.has(flow);
|
|
5059
|
+
const unpathed = items2.some((item) => {
|
|
5060
|
+
const match = item.map((line2) => pathLine.exec(line2)).find(Boolean);
|
|
5061
|
+
const flows = match ? match[1].split(/[,,、]/).map((f) => f.trim()).filter(Boolean) : [];
|
|
5062
|
+
return !flows.length || !flows.every(named);
|
|
5063
|
+
});
|
|
5064
|
+
if (unpathed)
|
|
5065
|
+
warnings.push(docWarning("REQUIREMENT_PATH_FORMAT", path3));
|
|
4966
5066
|
return warnings;
|
|
4967
5067
|
}
|
|
4968
5068
|
|
|
@@ -4981,12 +5081,12 @@ function parseChangelog(text4) {
|
|
|
4981
5081
|
let entry2;
|
|
4982
5082
|
let section2;
|
|
4983
5083
|
const fail4 = (line2, key, values = {}) => new InitError("INVALID_CHANGELOG", t("changelog.atLine", { line: line2, reason: t(key, values) }));
|
|
4984
|
-
const
|
|
5084
|
+
const lines2 = text4.replace(/\r\n/g, "\n").split("\n");
|
|
4985
5085
|
const close = (line2) => {
|
|
4986
5086
|
if (entry2 && changelogSections.every((name2) => entry2[name2].length === 0))
|
|
4987
5087
|
throw fail4(line2, "changelog.emptyVersion", { version: entry2.version });
|
|
4988
5088
|
};
|
|
4989
|
-
|
|
5089
|
+
lines2.forEach((raw, index) => {
|
|
4990
5090
|
const line2 = index + 1;
|
|
4991
5091
|
if (raw.trim() === "")
|
|
4992
5092
|
return;
|
|
@@ -5024,7 +5124,7 @@ function parseChangelog(text4) {
|
|
|
5024
5124
|
}
|
|
5025
5125
|
throw fail4(line2, "changelog.unknownLine", { text: raw });
|
|
5026
5126
|
});
|
|
5027
|
-
close(
|
|
5127
|
+
close(lines2.length);
|
|
5028
5128
|
if (entries.length === 0)
|
|
5029
5129
|
throw fail4(1, "changelog.noVersions");
|
|
5030
5130
|
return entries;
|
|
@@ -6997,14 +7097,14 @@ function toDotPath(_path) {
|
|
|
6997
7097
|
return segs.join("");
|
|
6998
7098
|
}
|
|
6999
7099
|
function prettifyError(error62) {
|
|
7000
|
-
const
|
|
7100
|
+
const lines2 = [];
|
|
7001
7101
|
const issues = [...error62.issues].sort((a, b) => (a.path ?? []).length - (b.path ?? []).length);
|
|
7002
7102
|
for (const issue2 of issues) {
|
|
7003
|
-
|
|
7103
|
+
lines2.push(`\u2716 ${issue2.message}`);
|
|
7004
7104
|
if (issue2.path?.length)
|
|
7005
|
-
|
|
7105
|
+
lines2.push(` \u2192 at ${toDotPath(issue2.path)}`);
|
|
7006
7106
|
}
|
|
7007
|
-
return
|
|
7107
|
+
return lines2.join("\n");
|
|
7008
7108
|
}
|
|
7009
7109
|
|
|
7010
7110
|
// ../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/parse.js
|
|
@@ -7839,9 +7939,9 @@ var Doc = class {
|
|
|
7839
7939
|
return;
|
|
7840
7940
|
}
|
|
7841
7941
|
const content = arg;
|
|
7842
|
-
const
|
|
7843
|
-
const minIndent = Math.min(...
|
|
7844
|
-
const dedented =
|
|
7942
|
+
const lines2 = content.split("\n").filter((x) => x);
|
|
7943
|
+
const minIndent = Math.min(...lines2.map((x) => x.length - x.trimStart().length));
|
|
7944
|
+
const dedented = lines2.map((x) => x.slice(minIndent)).map((x) => " ".repeat(this.indent * 2) + x);
|
|
7845
7945
|
for (const line2 of dedented) {
|
|
7846
7946
|
this.content.push(line2);
|
|
7847
7947
|
}
|
|
@@ -25056,7 +25156,8 @@ var state = external_exports.enum(["committed", "added", "modified", "deleted"])
|
|
|
25056
25156
|
var standing = { state, previousPath: external_exports.string().optional() };
|
|
25057
25157
|
var contributor = external_exports.strictObject({ email: external_exports.string(), name: external_exports.string(), commits: external_exports.number().int().nonnegative(), latest: external_exports.string() });
|
|
25058
25158
|
var source = external_exports.strictObject({ id: external_exports.string().optional(), title: external_exports.string().optional(), path: external_exports.string().optional(), url: external_exports.string().optional(), note: external_exports.string().optional() });
|
|
25059
|
-
var
|
|
25159
|
+
var style = external_exports.enum(["default", "usecase"]);
|
|
25160
|
+
var requirement = external_exports.strictObject({ id: external_exports.string(), path: external_exports.string(), title: external_exports.string(), description: external_exports.string(), order: external_exports.number().int().nonnegative(), style: style.optional(), body: external_exports.string(), ...standing });
|
|
25060
25161
|
var design = external_exports.strictObject({
|
|
25061
25162
|
id: external_exports.string(),
|
|
25062
25163
|
path: external_exports.string(),
|
|
@@ -25143,7 +25244,7 @@ var browserFeaturesV1 = external_exports.strictObject({
|
|
|
25143
25244
|
next: external_exports.string().nullable(),
|
|
25144
25245
|
features: external_exports.array(featureRow)
|
|
25145
25246
|
});
|
|
25146
|
-
var
|
|
25247
|
+
var browserFeatureV2 = external_exports.strictObject({ contract: external_exports.literal("browser-feature"), version: external_exports.literal(2), sessionId: external_exports.string(), feature });
|
|
25147
25248
|
var browserInstructionsV1 = external_exports.strictObject({
|
|
25148
25249
|
contract: external_exports.literal("browser-instructions"),
|
|
25149
25250
|
version: external_exports.literal(1),
|
|
@@ -25177,6 +25278,7 @@ var snapshot = external_exports.strictObject({
|
|
|
25177
25278
|
specId: external_exports.string(),
|
|
25178
25279
|
path: external_exports.string(),
|
|
25179
25280
|
order: external_exports.number().int().optional(),
|
|
25281
|
+
style: style.optional(),
|
|
25180
25282
|
requirements: external_exports.array(external_exports.string()).optional(),
|
|
25181
25283
|
sources: external_exports.array(source).optional()
|
|
25182
25284
|
}).nullable();
|
|
@@ -25198,16 +25300,25 @@ var event = external_exports.strictObject({
|
|
|
25198
25300
|
after: reference,
|
|
25199
25301
|
records: external_exports.array(record2)
|
|
25200
25302
|
});
|
|
25201
|
-
var
|
|
25303
|
+
var browserHistoryV7 = external_exports.strictObject({
|
|
25202
25304
|
contract: external_exports.literal("browser-history"),
|
|
25203
|
-
version: external_exports.literal(
|
|
25305
|
+
version: external_exports.literal(7),
|
|
25204
25306
|
sessionId: external_exports.string(),
|
|
25205
25307
|
head: oid2,
|
|
25206
25308
|
// Matching changes and the commits that hold them in all of history, not in this page.
|
|
25207
25309
|
total: external_exports.number().int().nonnegative(),
|
|
25208
25310
|
commits: external_exports.number().int().nonnegative(),
|
|
25209
25311
|
next: oid2.nullable(),
|
|
25210
|
-
events: external_exports.array(event)
|
|
25312
|
+
events: external_exports.array(event),
|
|
25313
|
+
// Every document and those no record explains, and each record with how many documents it explains, in commit order.
|
|
25314
|
+
whole: external_exports.array(external_exports.strictObject({
|
|
25315
|
+
commit: oid2,
|
|
25316
|
+
documents: external_exports.number().int().nonnegative(),
|
|
25317
|
+
unrecorded: external_exports.number().int().nonnegative(),
|
|
25318
|
+
records: external_exports.array(external_exports.strictObject({ id: external_exports.string(), documents: external_exports.number().int().positive() }))
|
|
25319
|
+
})),
|
|
25320
|
+
// The kinds of document the history holds at all, so the filter offers a kind only when it can find something.
|
|
25321
|
+
kinds: external_exports.array(kind)
|
|
25211
25322
|
});
|
|
25212
25323
|
var browserHistorySummaryV5 = external_exports.strictObject({
|
|
25213
25324
|
contract: external_exports.literal("browser-history-summary"),
|
|
@@ -25243,13 +25354,14 @@ var browserSearchV3 = external_exports.strictObject({
|
|
|
25243
25354
|
});
|
|
25244
25355
|
var headQuery = oid2;
|
|
25245
25356
|
var count = (max) => external_exports.string().regex(/^(0|[1-9]\d{0,6})$/).transform(Number).pipe(external_exports.number().int().min(0).max(max));
|
|
25246
|
-
var
|
|
25357
|
+
var browserHistoryQueryV5 = external_exports.strictObject({
|
|
25247
25358
|
head: headQuery,
|
|
25248
25359
|
after: oid2.optional(),
|
|
25249
25360
|
limit: count(50).pipe(external_exports.number().min(1)).optional(),
|
|
25250
|
-
|
|
25361
|
+
// A feature or an instruction; `record=missing` keeps the changes no record explains.
|
|
25362
|
+
target: external_exports.string().regex(/^[SI]-[a-z2-7]{10}$/).optional(),
|
|
25251
25363
|
document: kind.optional(),
|
|
25252
|
-
|
|
25364
|
+
record: external_exports.literal("missing").optional(),
|
|
25253
25365
|
author: external_exports.string().min(1).max(320).optional(),
|
|
25254
25366
|
q: external_exports.string().max(200).optional()
|
|
25255
25367
|
});
|
|
@@ -25324,9 +25436,9 @@ var browserCommitV4 = external_exports.strictObject({
|
|
|
25324
25436
|
});
|
|
25325
25437
|
var recordId = external_exports.string().regex(/^(?:DR|H)-[A-Za-z0-9_-]{1,64}$/);
|
|
25326
25438
|
var browserCommitQueryV3 = external_exports.strictObject({ commit: oid2, after: external_exports.string().min(1).max(200).optional(), limit: count(100).pipe(external_exports.number().min(1)).optional(), record: recordId.optional() });
|
|
25327
|
-
var
|
|
25439
|
+
var browserCommitChangeV2 = external_exports.strictObject({
|
|
25328
25440
|
contract: external_exports.literal("browser-commit-change"),
|
|
25329
|
-
version: external_exports.literal(
|
|
25441
|
+
version: external_exports.literal(2),
|
|
25330
25442
|
sessionId: external_exports.string(),
|
|
25331
25443
|
commit: oid2,
|
|
25332
25444
|
event,
|
|
@@ -25345,6 +25457,24 @@ var browserRecordV2 = external_exports.strictObject({
|
|
|
25345
25457
|
others: external_exports.number().int().nonnegative()
|
|
25346
25458
|
});
|
|
25347
25459
|
var browserRecordQueryV1 = external_exports.strictObject({ head: oid2, id: recordId });
|
|
25460
|
+
var browserDocumentHistoryV1 = external_exports.strictObject({
|
|
25461
|
+
contract: external_exports.literal("browser-document-history"),
|
|
25462
|
+
version: external_exports.literal(1),
|
|
25463
|
+
sessionId: external_exports.string(),
|
|
25464
|
+
head: oid2,
|
|
25465
|
+
doc: external_exports.strictObject({ id: external_exports.string(), title: external_exports.string().nullable(), kind: kind.nullable(), path: external_exports.string().nullable() }),
|
|
25466
|
+
total: external_exports.number().int().nonnegative(),
|
|
25467
|
+
recorded: external_exports.number().int().nonnegative(),
|
|
25468
|
+
withoutRecord: external_exports.number().int().nonnegative(),
|
|
25469
|
+
next: oid2.nullable(),
|
|
25470
|
+
events: external_exports.array(event)
|
|
25471
|
+
});
|
|
25472
|
+
var browserDocumentHistoryQueryV1 = external_exports.strictObject({
|
|
25473
|
+
head: oid2,
|
|
25474
|
+
id: external_exports.string().regex(/^[SRDWI]-[a-z2-7]{10}$/),
|
|
25475
|
+
after: oid2.optional(),
|
|
25476
|
+
limit: count(50).pipe(external_exports.number().min(1)).optional()
|
|
25477
|
+
});
|
|
25348
25478
|
var browserInstructionFileV1 = external_exports.strictObject({
|
|
25349
25479
|
contract: external_exports.literal("browser-instruction-file"),
|
|
25350
25480
|
version: external_exports.literal(1),
|
|
@@ -25367,9 +25497,9 @@ var browserWorkingV1 = external_exports.strictObject({
|
|
|
25367
25497
|
changes: external_exports.array(workingChange),
|
|
25368
25498
|
withoutRecord: external_exports.array(external_exports.string())
|
|
25369
25499
|
});
|
|
25370
|
-
var
|
|
25500
|
+
var browserWorkingChangeV2 = external_exports.strictObject({
|
|
25371
25501
|
contract: external_exports.literal("browser-working-change"),
|
|
25372
|
-
version: external_exports.literal(
|
|
25502
|
+
version: external_exports.literal(2),
|
|
25373
25503
|
sessionId: external_exports.string(),
|
|
25374
25504
|
change: workingChange,
|
|
25375
25505
|
before: snapshot,
|
|
@@ -25635,6 +25765,7 @@ var messages_default3 = {
|
|
|
25635
25765
|
"server.cursorNotFound": "\uC774\uC5B4 \uC77D\uC744 \uC704\uCE58\uB97C \uBAA9\uB85D\uC5D0\uC11C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uCC98\uC74C\uBD80\uD130 \uB2E4\uC2DC \uBD88\uB7EC\uC624\uC138\uC694.",
|
|
25636
25766
|
"server.workingChangeNotFound": "\uCEE4\uBC0B \uC804 \uBCC0\uACBD\uC5D0 \uADF8 \uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25637
25767
|
"server.recordNotFound": "\uC774 \uC774\uB825\uC5D0 \uADF8 \uACB0\uC815\uAE30\uB85D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25768
|
+
"server.documentNotFound": "\uC774 \uC774\uB825\uACFC \uC791\uC5C5 \uD3F4\uB354\uC5D0 \uADF8 \uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25638
25769
|
"server.commitFileNotFound": "\uADF8 \uCEE4\uBC0B\uC774 \uBC14\uAFBC \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
25639
25770
|
"server.instructionFileNotFound": "\uC9C0\uCE68 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
25640
25771
|
"server.specsUnreadable": "\uBA85\uC138\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
@@ -25769,7 +25900,8 @@ var messages_default3 = {
|
|
|
25769
25900
|
"docs.pathExample.design": "payment/api (.gitifact/spec/payment/design/api.md)",
|
|
25770
25901
|
"docs.pathExample.instruction": "cli-architecture (.gitifact/instructions/cli-architecture/index.md)",
|
|
25771
25902
|
"docs.skeleton.feature": "(\uC774 \uAE30\uB2A5\uC774 \uBB34\uC5C7\uC774\uACE0 \uC5B4\uB514\uAE4C\uC9C0\uC778\uC9C0)",
|
|
25772
|
-
"docs.skeleton.requirement": "(\uC0AC\uC6A9\uC790)\uB85C\uC11C, (\uBAA9\uC801)\uC744 \uC704\uD574 (\uB3D9\uC791)\uC744 \uD558\uACE0 \uC2F6\uB2E4.\n\n### \uC218\uC6A9 \uC870\uAC74\n\n1. \uC870\uAC74: (\uC0C1\uD669)\n \uAE30\uB300 \uB3D9\uC791: (\uACB0\uACFC)",
|
|
25903
|
+
"docs.skeleton.requirement": "(\uC0AC\uC6A9\uC790)\uB85C\uC11C, (\uBAA9\uC801)\uC744 \uC704\uD574 (\uB3D9\uC791)\uC744 \uD558\uACE0 \uC2F6\uB2E4.\n\n### \uBC94\uC704\uC640 \uC81C\uC57D\n\n- (\uCC38\xB7\uAC70\uC9D3\uC744 \uAC00\uB9B4 \uC218 \uC788\uB294 \uADDC\uCE59 \uD55C \uBB38\uC7A5. \uC5C6\uC73C\uBA74 \uC774 \uC808\uC744 \uC9C0\uC6B4\uB2E4)\n\n### \uC218\uC6A9 \uC870\uAC74\n\n1. \uC870\uAC74: (\uC0C1\uD669)\n \uAE30\uB300 \uB3D9\uC791: (\uACB0\uACFC)",
|
|
25904
|
+
"docs.skeleton.requirementUsecase": "(\uC0AC\uC6A9\uC790)\uB85C\uC11C, (\uBAA9\uC801)\uC744 \uC704\uD574 (\uB3D9\uC791)\uC744 \uD558\uACE0 \uC2F6\uB2E4.\n\n### \uBC94\uC704\uC640 \uC81C\uC57D\n\n- (\uCC38\xB7\uAC70\uC9D3\uC744 \uAC00\uB9B4 \uC218 \uC788\uB294 \uADDC\uCE59 \uD55C \uBB38\uC7A5. \uC5C6\uC73C\uBA74 \uC774 \uC808\uC744 \uC9C0\uC6B4\uB2E4)\n\n### \uC0AC\uC804 \uC870\uAC74\n\n- (\uC2DC\uC791 \uC804\uC5D0 \uCC38\uC774\uC5B4\uC57C \uD558\uB294 \uAC83. \uC5C6\uC73C\uBA74 \uC774 \uC808\uC744 \uC9C0\uC6B4\uB2E4)\n\n### \uAE30\uBCF8 \uD750\uB984\n\n1. (\uD589\uC704\uC790)\uAC00 (\uB3D9\uC791)\uD55C\uB2E4.\n2. (\uC2DC\uC2A4\uD15C)\uC774 (\uACB0\uACFC)\uB97C \uBCF4\uC778\uB2E4.\n\n### \uB300\uCCB4 \uD750\uB984\n\n- **A1. (\uAC08\uB77C\uC9C0\uB294 \uC0C1\uD669)** (1\uB2E8\uACC4\uC5D0\uC11C)\n 1. (\uADF8\uB54C\uC758 \uB3D9\uC791)\n\n### \uC0AC\uD6C4 \uC870\uAC74\n\n- (\uB05D\uB09C \uB4A4 \uCC38\uC778 \uAC83. \uC5C6\uC73C\uBA74 \uC774 \uC808\uC744 \uC9C0\uC6B4\uB2E4)\n\n### \uC218\uC6A9 \uC870\uAC74\n\n1. \uACBD\uB85C: \uAE30\uBCF8 \uD750\uB984\n \uC870\uAC74: (\uC0C1\uD669)\n \uAE30\uB300 \uB3D9\uC791: (\uACB0\uACFC)\n2. \uACBD\uB85C: \uAE30\uBCF8 \uD750\uB984, A1\n \uC870\uAC74: (\uC0C1\uD669)\n \uAE30\uB300 \uB3D9\uC791: (\uACB0\uACFC)",
|
|
25773
25905
|
"docs.skeleton.design": "(\uC774 \uC124\uACC4\uAC00 \uB2E4\uB8E8\uB294 \uAD6C\uC870\uC640 \uCC98\uB9AC \uBC29\uC2DD)",
|
|
25774
25906
|
"docs.skeleton.instruction": "(\uC774 \uC791\uC5C5\uC744 \uD560 \uB54C \uC9C0\uD0AC \uADDC\uCE59\uACFC \uC808\uCC28. \uC790\uC138\uD55C \uB0B4\uC6A9\uC740 references/ \uC544\uB798 \uD30C\uC77C\uB85C \uB098\uB204\uACE0 \uC5EC\uAE30\uC11C \uB9C1\uD06C\uD55C\uB2E4)",
|
|
25775
25907
|
"docs.exists": "\uC774\uBBF8 \uC788\uB294 \uD30C\uC77C\uC785\uB2C8\uB2E4: {path}",
|
|
@@ -25792,8 +25924,10 @@ var messages_default3 = {
|
|
|
25792
25924
|
"commit.checkFailed": "\uBB38\uC11C \uAC80\uC0AC\uC5D0\uC11C \uBB38\uC81C {count}\uAC1C\uAC00 \uB098\uC640 \uCEE4\uBC0B\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.",
|
|
25793
25925
|
"commit.unknownDocument": "\uACB0\uC815\uAE30\uB85D\uC774 \uAC00\uB9AC\uD0A4\uB294 \uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4: {ids}",
|
|
25794
25926
|
"docs.singleLine": "{field}\uC740 \uD55C \uC904\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
25927
|
+
"docs.styleRequirementOnly": "--style\uC740 \uC694\uAD6C\uC0AC\uD56D(requirement)\uC744 \uB9CC\uB4E4 \uB54C\uB9CC \uC501\uB2C8\uB2E4.",
|
|
25795
25928
|
"changes.problems": "\uBB38\uC11C \uAC80\uC0AC: \uBB38\uC81C {count}\uAC1C (check\uB85C \uD655\uC778)",
|
|
25796
25929
|
"changes.warnings": "\uBB38\uC11C \uACBD\uACE0: {count}\uAC1C (check\uB85C \uD655\uC778, \uCEE4\uBC0B\uC740 \uB9C9\uC9C0 \uC54A\uC74C)",
|
|
25930
|
+
"changes.formatWarnings": "\uD615\uC2DD \uACBD\uACE0 {count}\uAC1C (\uC774\uBC88\uC5D0 \uBC14\uB010 \uC694\uAD6C\uC0AC\uD56D, \uCEE4\uBC0B\uC740 \uB9C9\uC9C0 \uC54A\uC74C)",
|
|
25797
25931
|
"changes.clean": "\uBB38\uC11C \uAC80\uC0AC: \uBB38\uC81C \uC5C6\uC74C",
|
|
25798
25932
|
"changes.pendingRecords": "\uCEE4\uBC0B\uD558\uC9C0 \uC54A\uC740 \uACB0\uC815\uAE30\uB85D {count}\uAC1C (*\uB294 \uC774\uBC88\uC5D0 \uBC14\uB00C\uC9C0 \uC54A\uC740 \uBB38\uC11C)",
|
|
25799
25933
|
"changes.withoutRecord": "\uACB0\uC815\uAE30\uB85D\uC774 \uC5C6\uB294 \uC218\uC815\xB7\uC774\uB3D9\xB7\uC0AD\uC81C: {ids}",
|
|
@@ -25830,6 +25964,7 @@ var messages_default3 = {
|
|
|
25830
25964
|
"help.specsNew": "ID\uB97C \uBC1C\uAE09\uD558\uACE0 \uD504\uB860\uD2B8\uB9E4\uD130\uC640 \uBCF8\uBB38 \uBF08\uB300\uB97C \uCC44\uC6B4 \uC0C8 \uBA85\uC138 \uD30C\uC77C \uC0DD\uC131 (draft: true \uD45C\uC2DC)",
|
|
25831
25965
|
"help.specsNewKind": "feature, requirement, design \uC911 \uD558\uB098",
|
|
25832
25966
|
"help.specsNewPath": "\uAE30\uB2A5 \uC774\uB984 \uB610\uB294 \uAE30\uB2A5/slug (\uC608: payment, payment/cancel)",
|
|
25967
|
+
"help.specsNewStyle": "\uC694\uAD6C\uC0AC\uD56D \uD615\uC2DD(usecase, default). \uC5C6\uC73C\uBA74 \uC124\uC815\uC758 requirementStyle\uC744 \uB530\uB978\uB2E4",
|
|
25833
25968
|
"help.newTitle": "\uBB38\uC11C \uC81C\uBAA9",
|
|
25834
25969
|
"help.newDescription": "\uD55C \uC904 \uC124\uBA85",
|
|
25835
25970
|
"help.instructions": "\uD504\uB85C\uC81D\uD2B8 \uC9C0\uCE68\uC758 \uBAA9\uB85D\xB7\uC6D0\uBB38\xB7\uC0DD\uC131",
|
|
@@ -25949,6 +26084,7 @@ var messages_default4 = {
|
|
|
25949
26084
|
"server.cursorNotFound": "The place to read on from is no longer in the list. Load it again from the start.",
|
|
25950
26085
|
"server.workingChangeNotFound": "No uncommitted change of that document.",
|
|
25951
26086
|
"server.recordNotFound": "This history has no such decision record.",
|
|
26087
|
+
"server.documentNotFound": "Neither this history nor the working tree has that document.",
|
|
25952
26088
|
"server.commitFileNotFound": "That commit did not change this file.",
|
|
25953
26089
|
"server.instructionFileNotFound": "The instruction file was not found.",
|
|
25954
26090
|
"server.specsUnreadable": "Could not read specifications.",
|
|
@@ -26083,7 +26219,8 @@ var messages_default4 = {
|
|
|
26083
26219
|
"docs.pathExample.design": "payment/api (.gitifact/spec/payment/design/api.md)",
|
|
26084
26220
|
"docs.pathExample.instruction": "cli-architecture (.gitifact/instructions/cli-architecture/index.md)",
|
|
26085
26221
|
"docs.skeleton.feature": "(What this feature is and where it ends)",
|
|
26086
|
-
"docs.skeleton.requirement": "As (a user), I want to (act) so that (purpose).\n\n### Acceptance criteria\n\n1. Condition: (situation)\n Expected: (result)",
|
|
26222
|
+
"docs.skeleton.requirement": "As (a user), I want to (act) so that (purpose).\n\n### Scope and constraints\n\n- (One rule that is either true or false. Remove this section if there is none)\n\n### Acceptance criteria\n\n1. Condition: (situation)\n Expected: (result)",
|
|
26223
|
+
"docs.skeleton.requirementUsecase": "As (a user), I want to (act) so that (purpose).\n\n### Scope and constraints\n\n- (One rule that is either true or false. Remove this section if there is none)\n\n### Preconditions\n\n- (What holds before it starts. Remove this section if there is none)\n\n### Basic flow\n\n1. (The actor) (acts).\n2. (The system) shows (the result).\n\n### Alternative flows\n\n- **A1. (Where it branches)** (at step 1)\n 1. (What happens then)\n\n### Postconditions\n\n- (What holds when it ends. Remove this section if there is none)\n\n### Acceptance criteria\n\n1. Path: Basic flow\n Condition: (situation)\n Expected: (result)\n2. Path: Basic flow, A1\n Condition: (situation)\n Expected: (result)",
|
|
26087
26224
|
"docs.skeleton.design": "(The structure and processing this design covers)",
|
|
26088
26225
|
"docs.skeleton.instruction": "(Rules and steps to follow for this kind of work. Put details in files under references/ and link them from here)",
|
|
26089
26226
|
"docs.exists": "The file already exists: {path}",
|
|
@@ -26106,8 +26243,10 @@ var messages_default4 = {
|
|
|
26106
26243
|
"commit.checkFailed": "The document check found {count} problems; nothing was committed.",
|
|
26107
26244
|
"commit.unknownDocument": "A record names documents that do not exist: {ids}",
|
|
26108
26245
|
"docs.singleLine": "The {field} must be a single line.",
|
|
26246
|
+
"docs.styleRequirementOnly": "--style applies only when creating a requirement.",
|
|
26109
26247
|
"changes.problems": "Document check: {count} problems (see check)",
|
|
26110
26248
|
"changes.warnings": "Document warnings: {count} (see check; they do not block a commit)",
|
|
26249
|
+
"changes.formatWarnings": "Format warnings: {count} (requirements changed here; they do not block a commit)",
|
|
26111
26250
|
"changes.clean": "Document check: no problems",
|
|
26112
26251
|
"changes.pendingRecords": "{count} uncommitted record(s) (* marks a document this change does not touch)",
|
|
26113
26252
|
"changes.withoutRecord": "Changed, moved or deleted without a record: {ids}",
|
|
@@ -26144,6 +26283,7 @@ var messages_default4 = {
|
|
|
26144
26283
|
"help.specsNew": "Create a spec file with an issued ID, frontmatter and a body skeleton (marked draft: true)",
|
|
26145
26284
|
"help.specsNewKind": "One of feature, requirement, design",
|
|
26146
26285
|
"help.specsNewPath": "Feature name or feature/slug (e.g. payment, payment/cancel)",
|
|
26286
|
+
"help.specsNewStyle": "Requirement shape (usecase, default). Defaults to the config requirementStyle",
|
|
26147
26287
|
"help.newTitle": "Document title",
|
|
26148
26288
|
"help.newDescription": "One-line description",
|
|
26149
26289
|
"help.instructions": "List, read and create project instructions",
|
|
@@ -26559,7 +26699,7 @@ function storeReader(cwd) {
|
|
|
26559
26699
|
import { DatabaseSync } from "node:sqlite";
|
|
26560
26700
|
import { lstat, mkdir, rm, writeFile } from "node:fs/promises";
|
|
26561
26701
|
import { join as join2 } from "node:path";
|
|
26562
|
-
var CACHE_FORMAT =
|
|
26702
|
+
var CACHE_FORMAT = 12;
|
|
26563
26703
|
var CACHE_DIR = ".gitifact/cache";
|
|
26564
26704
|
var SCHEMA = `
|
|
26565
26705
|
-- Working-tree files already read: the modification time and size decide whether a file is read again.
|
|
@@ -26711,6 +26851,10 @@ function snippet(text4, query) {
|
|
|
26711
26851
|
return (from > 0 ? "\u2026" : "") + text4.slice(from, at + query.length + 70).trim() + (at + query.length + 70 < text4.length ? "\u2026" : "");
|
|
26712
26852
|
}
|
|
26713
26853
|
var containing = (query) => "%" + query.replace(/[\\%_]/g, (c) => "\\" + c) + "%";
|
|
26854
|
+
function hashPrefix(query) {
|
|
26855
|
+
const wanted = query?.trim().toLowerCase();
|
|
26856
|
+
return wanted && /^[0-9a-f]{7,64}$/.test(wanted) ? wanted : void 0;
|
|
26857
|
+
}
|
|
26714
26858
|
|
|
26715
26859
|
// src/adapters/cache/documents.ts
|
|
26716
26860
|
var FILE_LIMIT = 1024 * 1024;
|
|
@@ -27003,7 +27147,7 @@ var recordKind = (path3) => {
|
|
|
27003
27147
|
var folderOf = (path3) => path3.startsWith(SPEC_ROOT + "/") ? path3.split("/").slice(0, 3).join("/") : null;
|
|
27004
27148
|
function snapshot3(doc, specId) {
|
|
27005
27149
|
const base = { id: doc.id, kind: doc.kind, title: doc.title, description: doc.description, body: doc.body, specId, path: doc.path };
|
|
27006
|
-
if (doc.kind === "requirement") return { ...base, order: doc.order };
|
|
27150
|
+
if (doc.kind === "requirement") return { ...base, order: doc.order, ...doc.style ? { style: doc.style } : {} };
|
|
27007
27151
|
if (doc.kind === "design") return { ...base, order: doc.order, requirements: doc.requirements, sources: doc.sources };
|
|
27008
27152
|
return base;
|
|
27009
27153
|
}
|
|
@@ -27026,7 +27170,7 @@ function sideOf2(files) {
|
|
|
27026
27170
|
}
|
|
27027
27171
|
return { docs: new Map(docs.map((d) => [d.id, snapshot3(d, d.kind === "wiki" || d.kind === "instruction" ? d.kind : specIds.get(folderOf(d.path)) ?? "")])), reasons };
|
|
27028
27172
|
}
|
|
27029
|
-
var same = (a, b) => a.title === b.title && a.description === b.description && a.body === b.body && a.order === b.order && JSON.stringify(a.requirements) === JSON.stringify(b.requirements) && JSON.stringify(a.sources) === JSON.stringify(b.sources);
|
|
27173
|
+
var same = (a, b) => a.title === b.title && a.description === b.description && a.body === b.body && a.order === b.order && a.style === b.style && JSON.stringify(a.requirements) === JSON.stringify(b.requirements) && JSON.stringify(a.sources) === JSON.stringify(b.sources);
|
|
27030
27174
|
function compare(before, after) {
|
|
27031
27175
|
const out = [];
|
|
27032
27176
|
for (const id of [.../* @__PURE__ */ new Set([...before.docs.keys(), ...after.docs.keys()])].sort()) {
|
|
@@ -27103,10 +27247,10 @@ function createCommitChanges(git) {
|
|
|
27103
27247
|
}
|
|
27104
27248
|
};
|
|
27105
27249
|
for (const chunk of patch.split("").filter(Boolean)) {
|
|
27106
|
-
const
|
|
27107
|
-
const commit =
|
|
27108
|
-
const removed = new Set(
|
|
27109
|
-
found.set(commit,
|
|
27250
|
+
const lines2 = chunk.split("\n");
|
|
27251
|
+
const commit = lines2[0].trim();
|
|
27252
|
+
const removed = new Set(lines2.filter((l) => l.startsWith("-") && !l.startsWith("---")).flatMap((l) => read(l.slice(1))).map((r) => r.id));
|
|
27253
|
+
found.set(commit, lines2.filter((l) => l.startsWith("+") && !l.startsWith("+++")).flatMap((l) => read(l.slice(1))).filter((r) => !removed.has(r.id)).map((r) => reasonRecord(r.id, r.docs, r.reason)));
|
|
27110
27254
|
}
|
|
27111
27255
|
return found;
|
|
27112
27256
|
}
|
|
@@ -27415,25 +27559,30 @@ function createHistory(database, git, originals) {
|
|
|
27415
27559
|
function where(filter) {
|
|
27416
27560
|
const clauses = [];
|
|
27417
27561
|
const params = [];
|
|
27418
|
-
if (filter.
|
|
27419
|
-
clauses.push("
|
|
27420
|
-
params.push(
|
|
27562
|
+
if (filter.target?.startsWith("I-")) {
|
|
27563
|
+
clauses.push("c.id = ?");
|
|
27564
|
+
params.push(filter.target);
|
|
27565
|
+
} else if (filter.target) {
|
|
27566
|
+
clauses.push("(c.before_spec = ? OR c.after_spec = ?)");
|
|
27567
|
+
params.push(filter.target, filter.target);
|
|
27421
27568
|
}
|
|
27422
27569
|
if (filter.document) {
|
|
27423
27570
|
clauses.push("c.kind = ?");
|
|
27424
27571
|
params.push(filter.document);
|
|
27425
27572
|
}
|
|
27426
|
-
if (filter.
|
|
27427
|
-
clauses.push("(c.before_spec = ? OR c.after_spec = ?)");
|
|
27428
|
-
params.push(filter.feature, filter.feature);
|
|
27429
|
-
}
|
|
27573
|
+
if (filter.unrecorded) clauses.push("json_array_length(c.row, '$.records') = 0");
|
|
27430
27574
|
if (filter.author) {
|
|
27431
27575
|
clauses.push("c.email = ?");
|
|
27432
27576
|
params.push(filter.author);
|
|
27433
27577
|
}
|
|
27434
|
-
|
|
27435
|
-
|
|
27436
|
-
|
|
27578
|
+
const q = filter.q?.trim().toLowerCase();
|
|
27579
|
+
if (q) {
|
|
27580
|
+
const record4 = `EXISTS (SELECT 1 FROM json_each(c.row, '$.records') j JOIN records r ON r.oid = c.oid AND r.id = j.value
|
|
27581
|
+
WHERE instr(lower(r.title), ?) > 0 OR instr(lower(r.id), ?) > 0
|
|
27582
|
+
OR instr(lower((SELECT group_concat(json_extract(s.value, '$.body'), ' ') FROM json_each(r.sections) s)), ?) > 0)`;
|
|
27583
|
+
const hash3 = hashPrefix(q) ? " OR substr(c.oid, 1, length(?)) = ?" : "";
|
|
27584
|
+
clauses.push(`(instr(c.needle, ?) > 0 OR ${record4}${hash3})`);
|
|
27585
|
+
params.push(q, q, q, q, ...hash3 ? [q, q] : []);
|
|
27437
27586
|
}
|
|
27438
27587
|
return { sql: clauses.map((c) => " AND " + c).join(""), params };
|
|
27439
27588
|
}
|
|
@@ -27461,11 +27610,28 @@ function createHistory(database, git, originals) {
|
|
|
27461
27610
|
const commits = db.prepare(`SELECT l.pos AS pos, l.oid AS oid ${from} AND l.pos > ? GROUP BY l.pos, l.oid ORDER BY l.pos LIMIT ?`).all(head, ...params, start, limit + 1);
|
|
27462
27611
|
const shown = commits.slice(0, limit);
|
|
27463
27612
|
const rows = !shown.length ? [] : db.prepare(`SELECT c.row ${from} AND l.pos >= ? AND l.pos <= ? ORDER BY l.pos, c.ord`).all(head, ...params, shown[0].pos, shown[shown.length - 1].pos);
|
|
27613
|
+
const oids = JSON.stringify(shown.map((c) => c.oid));
|
|
27614
|
+
const sizes = db.prepare(`SELECT oid, count(*) AS documents, sum(json_array_length(row, '$.records') = 0) AS unrecorded
|
|
27615
|
+
FROM changes WHERE oid IN (SELECT value FROM json_each(?)) GROUP BY oid`).all(oids);
|
|
27616
|
+
const explained = db.prepare(`SELECT c.oid AS oid, j.value AS id, count(*) AS documents FROM changes c, json_each(c.row, '$.records') j
|
|
27617
|
+
WHERE c.oid IN (SELECT value FROM json_each(?)) GROUP BY c.oid, j.value ORDER BY c.oid, min(c.ord)`).all(oids);
|
|
27618
|
+
const whole = shown.map(({ oid: oid3 }) => {
|
|
27619
|
+
const size = sizes.find((s) => s.oid === oid3);
|
|
27620
|
+
return {
|
|
27621
|
+
commit: oid3,
|
|
27622
|
+
documents: Number(size?.documents ?? 0),
|
|
27623
|
+
unrecorded: Number(size?.unrecorded ?? 0),
|
|
27624
|
+
records: explained.filter((r) => r.oid === oid3).map((r) => ({ id: r.id, documents: Number(r.documents) }))
|
|
27625
|
+
};
|
|
27626
|
+
});
|
|
27627
|
+
const kinds = db.prepare("SELECT DISTINCT c.kind AS kind FROM lineage l JOIN changes c ON c.oid = l.oid WHERE l.head = ?").all(head).map((k) => k.kind);
|
|
27464
27628
|
return {
|
|
27465
27629
|
total: Number(counted.n),
|
|
27466
27630
|
commits: Number(counted.commits),
|
|
27467
27631
|
next: commits.length > limit ? shown[shown.length - 1].oid : null,
|
|
27468
|
-
events: hydrate(db, rows.map((r) => r.row))
|
|
27632
|
+
events: hydrate(db, rows.map((r) => r.row)),
|
|
27633
|
+
whole,
|
|
27634
|
+
kinds
|
|
27469
27635
|
};
|
|
27470
27636
|
});
|
|
27471
27637
|
},
|
|
@@ -27515,9 +27681,11 @@ function createHistory(database, git, originals) {
|
|
|
27515
27681
|
clauses.push("(lower(json_extract(row, '$.author')) = ? OR lower(json_extract(row, '$.email')) = ?)");
|
|
27516
27682
|
params.push(filter.author.toLowerCase(), filter.author.toLowerCase());
|
|
27517
27683
|
}
|
|
27518
|
-
|
|
27519
|
-
|
|
27520
|
-
|
|
27684
|
+
const q = filter.q?.trim().toLowerCase();
|
|
27685
|
+
const hash3 = hashPrefix(q);
|
|
27686
|
+
if (q) {
|
|
27687
|
+
clauses.push(`(instr(lower(title || ' ' || id || ' ' || coalesce(body, '')), ?) > 0${hash3 ? " OR substr(oid, 1, length(?)) = ?" : ""})`);
|
|
27688
|
+
params.push(q, ...hash3 ? [hash3, hash3] : []);
|
|
27521
27689
|
}
|
|
27522
27690
|
if (filter.from !== void 0) {
|
|
27523
27691
|
clauses.push("unixepoch(json_extract(row, '$.date')) * 1000 >= ?");
|
|
@@ -27725,8 +27893,8 @@ function createCommitLog(database, git, root) {
|
|
|
27725
27893
|
* prints it. Anything shorter or not a hash names none. Newest first, a page after the commit `after`.
|
|
27726
27894
|
*/
|
|
27727
27895
|
async commitsNamed(head, raw, after, limit) {
|
|
27728
|
-
const prefix = raw
|
|
27729
|
-
if (
|
|
27896
|
+
const prefix = hashPrefix(raw);
|
|
27897
|
+
if (!prefix) return { total: 0, next: null, hits: [] };
|
|
27730
27898
|
await ensure(head);
|
|
27731
27899
|
return database.with((db) => {
|
|
27732
27900
|
const rows = db.prepare("SELECT oid, name, date, subject FROM log WHERE reach = 1 AND substr(oid, 1, length(?)) = ? ORDER BY time DESC, oid").all(prefix, prefix);
|
|
@@ -28077,6 +28245,8 @@ function createStampReader(root, inherited = process.env) {
|
|
|
28077
28245
|
const info5 = await lstat8(join9(root, ...path3.split("/"))).catch(() => void 0);
|
|
28078
28246
|
return path3 + " " + (info5 ? info5.mtimeMs + ":" + info5.size : "-");
|
|
28079
28247
|
}));
|
|
28248
|
+
const mailmap = await lstat8(join9(root, ".mailmap")).catch(() => void 0);
|
|
28249
|
+
seen.push(".mailmap " + (mailmap ? mailmap.mtimeMs + ":" + mailmap.size : "-"));
|
|
28080
28250
|
return createHash2("sha256").update(head.trim() + "\n" + seen.sort().join("\n")).digest("hex").slice(0, 20);
|
|
28081
28251
|
};
|
|
28082
28252
|
}
|
|
@@ -28111,7 +28281,7 @@ function checkoutDocuments(states, authors) {
|
|
|
28111
28281
|
description: index.description,
|
|
28112
28282
|
body: index.body,
|
|
28113
28283
|
...standing2(index.id),
|
|
28114
|
-
requirements: requirements.map((r) => ({ id: r.id, path: r.path, title: r.title, description: r.description, order: r.order, body: r.body, ...standing2(r.id) })),
|
|
28284
|
+
requirements: requirements.map((r) => ({ id: r.id, path: r.path, title: r.title, description: r.description, order: r.order, ...r.style ? { style: r.style } : {}, body: r.body, ...standing2(r.id) })),
|
|
28115
28285
|
designs: designs.map((d) => ({
|
|
28116
28286
|
id: d.id,
|
|
28117
28287
|
path: d.path,
|
|
@@ -28152,23 +28322,23 @@ function createCheckoutReader(root, cache, inherited = process.env) {
|
|
|
28152
28322
|
return head || null;
|
|
28153
28323
|
};
|
|
28154
28324
|
const pending = /* @__PURE__ */ new Map();
|
|
28325
|
+
const last = /* @__PURE__ */ new Map();
|
|
28155
28326
|
const readStamp = createStampReader(root, inherited);
|
|
28156
|
-
async function read() {
|
|
28327
|
+
async function read(stamp) {
|
|
28157
28328
|
const raw = await readConfigFile(root);
|
|
28158
28329
|
if (!raw) throw new StoreError(t2("specReader.schemaRequired"));
|
|
28159
28330
|
parseManagedConfig(raw);
|
|
28160
28331
|
const head = await readHead();
|
|
28161
|
-
const
|
|
28162
|
-
const [current2, dirty, authors, people] = await settled([
|
|
28332
|
+
const [current3, dirty, authors, people] = await settled([
|
|
28163
28333
|
cache.documents.list(),
|
|
28164
28334
|
head ? git(["status", "--porcelain=v1", "--", ".gitifact/spec", INSTRUCTIONS_ROOT]) : Promise.resolve(""),
|
|
28165
28335
|
// Who touched each folder and who committed at all, counted over the commit log in the cache.
|
|
28166
28336
|
head ? cache.log.folders(head) : Promise.resolve(/* @__PURE__ */ new Map()),
|
|
28167
28337
|
head ? cache.log.contributors(head) : Promise.resolve([])
|
|
28168
28338
|
]);
|
|
28169
|
-
const states = await documentStates({ head: async () => head, reader },
|
|
28339
|
+
const states = await documentStates({ head: async () => head, reader }, current3.documents);
|
|
28170
28340
|
const { features, instructions: instructions2, orphans } = checkoutDocuments(states, authors);
|
|
28171
|
-
const problems = [...
|
|
28341
|
+
const problems = [...current3.problems, ...orphans.map((feature2) => docProblem("FEATURE_INDEX_REQUIRED", `.gitifact/spec/${feature2}/index.md`, { feature: feature2 }))];
|
|
28172
28342
|
if (await readHead() !== head) throw new StoreError(t2("specReader.projectChanged"));
|
|
28173
28343
|
return {
|
|
28174
28344
|
head,
|
|
@@ -28182,11 +28352,19 @@ function createCheckoutReader(root, cache, inherited = process.env) {
|
|
|
28182
28352
|
folders: authors
|
|
28183
28353
|
};
|
|
28184
28354
|
}
|
|
28355
|
+
async function current2(language) {
|
|
28356
|
+
const stamp = await readStamp();
|
|
28357
|
+
const known = last.get(language);
|
|
28358
|
+
if (known?.stamp === stamp) return { ...known, observedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
28359
|
+
const fresh = await read(stamp);
|
|
28360
|
+
last.set(language, fresh);
|
|
28361
|
+
return fresh;
|
|
28362
|
+
}
|
|
28185
28363
|
const base = () => {
|
|
28186
28364
|
const language = getLanguage();
|
|
28187
28365
|
let value = pending.get(language);
|
|
28188
28366
|
if (!value) {
|
|
28189
|
-
value =
|
|
28367
|
+
value = current2(language).finally(() => pending.delete(language));
|
|
28190
28368
|
pending.set(language, value);
|
|
28191
28369
|
}
|
|
28192
28370
|
return value;
|
|
@@ -28240,15 +28418,15 @@ function createCommitFiles(git) {
|
|
|
28240
28418
|
const revs = parent ? [parent, commit] : [commit];
|
|
28241
28419
|
const names = (await text4([...base, "--name-status", ...revs, "--"])).split("\0");
|
|
28242
28420
|
const counts = (await text4([...base, "--numstat", ...revs, "--"])).split("\0");
|
|
28243
|
-
const
|
|
28421
|
+
const lines2 = /* @__PURE__ */ new Map();
|
|
28244
28422
|
for (let i = 0; i < counts.length; i++) {
|
|
28245
28423
|
const [added, deleted, path3] = counts[i].split(" ");
|
|
28246
28424
|
if (added === void 0 || deleted === void 0) continue;
|
|
28247
28425
|
const count2 = { additions: added === "-" ? null : Number(added), deletions: deleted === "-" ? null : Number(deleted) };
|
|
28248
28426
|
if (path3 === "") {
|
|
28249
|
-
|
|
28427
|
+
lines2.set(counts[i + 2], count2);
|
|
28250
28428
|
i += 2;
|
|
28251
|
-
} else if (path3 !== void 0)
|
|
28429
|
+
} else if (path3 !== void 0) lines2.set(path3, count2);
|
|
28252
28430
|
}
|
|
28253
28431
|
const files = [];
|
|
28254
28432
|
for (let i = 0; i < names.length - 1; i++) {
|
|
@@ -28258,7 +28436,7 @@ function createCommitFiles(git) {
|
|
|
28258
28436
|
const previousPath = renamed ? names[++i] : void 0;
|
|
28259
28437
|
const path3 = names[++i];
|
|
28260
28438
|
if (!isSource(path3) && (!previousPath || !isSource(previousPath))) continue;
|
|
28261
|
-
files.push({ path: path3, ...renamed && code.startsWith("R") ? { previousPath } : {}, status: statusOf(code), ...
|
|
28439
|
+
files.push({ path: path3, ...renamed && code.startsWith("R") ? { previousPath } : {}, status: statusOf(code), ...lines2.get(path3) ?? { additions: null, deletions: null } });
|
|
28262
28440
|
}
|
|
28263
28441
|
return { commit, parent, total: files.length, files };
|
|
28264
28442
|
}
|
|
@@ -28339,7 +28517,7 @@ function snapshot4(doc, docs) {
|
|
|
28339
28517
|
const folder = doc.path.split("/").slice(0, 3).join("/");
|
|
28340
28518
|
const specId = doc.kind === "wiki" || doc.kind === "instruction" ? doc.kind : docs.find((d) => d.kind === "feature" && d.path === folder + "/index.md")?.id ?? "";
|
|
28341
28519
|
const base = { id: doc.id, kind: doc.kind, title: doc.title, description: doc.description, body: doc.body, specId, path: doc.path };
|
|
28342
|
-
if (doc.kind === "requirement") return { ...base, order: doc.order };
|
|
28520
|
+
if (doc.kind === "requirement") return { ...base, order: doc.order, ...doc.style ? { style: doc.style } : {} };
|
|
28343
28521
|
if (doc.kind === "design") return { ...base, order: doc.order, requirements: doc.requirements, sources: doc.sources };
|
|
28344
28522
|
return base;
|
|
28345
28523
|
}
|
|
@@ -28400,6 +28578,25 @@ async function recent(source2, head) {
|
|
|
28400
28578
|
return { group: "recent", total: hits.length, next: null, hits };
|
|
28401
28579
|
}
|
|
28402
28580
|
|
|
28581
|
+
// src/queries/document-history.ts
|
|
28582
|
+
async function documentHistory(source2, head, id) {
|
|
28583
|
+
const events = head ? await source2.cache.history.ofDocument(head, id) : [];
|
|
28584
|
+
const current2 = (await source2.cache.documents.list()).documents.find((d) => d.id === id);
|
|
28585
|
+
const last = events.map((e) => e.after ?? e.before).find(Boolean);
|
|
28586
|
+
if (!current2 && !events.length) return void 0;
|
|
28587
|
+
const doc = { id, title: current2?.title ?? last?.title ?? null, kind: current2?.kind ?? events[0]?.kind ?? null, path: current2?.path ?? last?.path ?? null };
|
|
28588
|
+
return { doc, events };
|
|
28589
|
+
}
|
|
28590
|
+
async function documentHistoryPage(source2, head, id, request) {
|
|
28591
|
+
const found = await documentHistory(source2, head, id);
|
|
28592
|
+
if (!found) return void 0;
|
|
28593
|
+
const page = pageOf(found.events, (e) => e.commit, request);
|
|
28594
|
+
if (!page) return null;
|
|
28595
|
+
const recorded = found.events.filter((e) => e.records.length).length;
|
|
28596
|
+
const withoutRecord = found.events.filter((e) => !e.records.length && e.types.some((type) => type !== "created")).length;
|
|
28597
|
+
return { doc: found.doc, total: page.total, recorded, withoutRecord, next: page.next, events: page.rows };
|
|
28598
|
+
}
|
|
28599
|
+
|
|
28403
28600
|
// src/queries/checkout.ts
|
|
28404
28601
|
var SHOWN_REQUIREMENTS = 12;
|
|
28405
28602
|
function checkoutIndex(base) {
|
|
@@ -28416,13 +28613,13 @@ function checkoutIndex(base) {
|
|
|
28416
28613
|
people: base.people.map((p) => ({ name: p.name, email: p.email }))
|
|
28417
28614
|
};
|
|
28418
28615
|
}
|
|
28419
|
-
var
|
|
28616
|
+
var acceptanceHeading2 = /^###\s+(?:수용 조건|acceptance criteria)\s*$/i;
|
|
28420
28617
|
function acceptanceCount(body2) {
|
|
28421
|
-
const
|
|
28422
|
-
const start =
|
|
28618
|
+
const lines2 = body2.replace(/\r\n/g, "\n").split("\n");
|
|
28619
|
+
const start = lines2.findIndex((line2) => acceptanceHeading2.test(line2.trim()));
|
|
28423
28620
|
if (start < 0) return null;
|
|
28424
28621
|
let count2 = 0;
|
|
28425
|
-
for (const line2 of
|
|
28622
|
+
for (const line2 of lines2.slice(start + 1)) {
|
|
28426
28623
|
if (/^#{1,6}\s/.test(line2)) break;
|
|
28427
28624
|
if (/^\d+\.\s/.test(line2)) count2++;
|
|
28428
28625
|
}
|
|
@@ -28529,7 +28726,7 @@ function recordRoutes(root, sessionId, env) {
|
|
|
28529
28726
|
route({ method: "GET", path: "/api/v1/feature", session: true, query: browserFeatureQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
|
|
28530
28727
|
const feature2 = featureOf(await checkout.base(), query.id);
|
|
28531
28728
|
if (!feature2) throw new HttpError(404, "NOT_FOUND", t2("server.featureNotFound"));
|
|
28532
|
-
return ok(
|
|
28729
|
+
return ok(browserFeatureV2.parse({ contract: "browser-feature", version: 2, sessionId, feature: feature2 }));
|
|
28533
28730
|
} }),
|
|
28534
28731
|
route({ method: "GET", path: "/api/v1/instructions", session: true, unreadable: unreadable2, handle: async () => ok(browserInstructionsV1.parse({ contract: "browser-instructions", version: 1, sessionId, ...await checkout.instructions() })) }),
|
|
28535
28732
|
route({ method: "GET", path: "/api/v1/contributors", session: true, query: browserContributorsQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
|
|
@@ -28544,10 +28741,16 @@ function recordRoutes(root, sessionId, env) {
|
|
|
28544
28741
|
} }),
|
|
28545
28742
|
// Whether the screen is behind, asked when the reader comes back to the tab; cheap enough to ask every time.
|
|
28546
28743
|
route({ method: "GET", path: "/api/v1/stamp", session: true, unreadable: unreadable2, handle: async () => ok(browserStampV1.parse({ contract: "browser-stamp", version: 1, sessionId, stamp: await readStamp() })) }),
|
|
28547
|
-
route({ method: "GET", path: "/api/v1/history", session: true, query:
|
|
28548
|
-
const page = await cache.history.commits(query.head, {
|
|
28744
|
+
route({ method: "GET", path: "/api/v1/history", session: true, query: browserHistoryQueryV5, unreadable: unreadable2, handle: async ({ query }) => {
|
|
28745
|
+
const page = await cache.history.commits(query.head, {
|
|
28746
|
+
target: query.target,
|
|
28747
|
+
document: query.document,
|
|
28748
|
+
unrecorded: query.record === "missing",
|
|
28749
|
+
author: query.author,
|
|
28750
|
+
q: query.q
|
|
28751
|
+
}, query.after, query.limit ?? PAGE);
|
|
28549
28752
|
if (!page) throw cursorGone2();
|
|
28550
|
-
return ok(
|
|
28753
|
+
return ok(browserHistoryV7.parse({ contract: "browser-history", version: 7, sessionId, head: query.head, ...page }));
|
|
28551
28754
|
} }),
|
|
28552
28755
|
route({ method: "GET", path: "/api/v1/history/summary", session: true, query: browserHistorySummaryQueryV1, unreadable: unreadable2, handle: async ({ query }) => ok(browserHistorySummaryV5.parse({
|
|
28553
28756
|
contract: "browser-history-summary",
|
|
@@ -28584,7 +28787,7 @@ function recordRoutes(root, sessionId, env) {
|
|
|
28584
28787
|
route({ method: "GET", path: "/api/v1/commit/change", session: true, query: browserCommitChangeQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
|
|
28585
28788
|
const change2 = await cache.history.commitChange(query.commit, query.id);
|
|
28586
28789
|
if (!change2) throw new HttpError(404, "NOT_FOUND", t2("server.commitNotFound"));
|
|
28587
|
-
return ok(
|
|
28790
|
+
return ok(browserCommitChangeV2.parse({ contract: "browser-commit-change", version: 2, sessionId, commit: query.commit, event: change2.event, before: change2.before, after: change2.after }));
|
|
28588
28791
|
} }),
|
|
28589
28792
|
// A record's page names the record; which commit added it is read from the history of the HEAD the reader is on.
|
|
28590
28793
|
route({ method: "GET", path: "/api/v1/record", session: true, query: browserRecordQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
|
|
@@ -28592,12 +28795,19 @@ function recordRoutes(root, sessionId, env) {
|
|
|
28592
28795
|
if (!found) throw new HttpError(404, "NOT_FOUND", t2("server.recordNotFound"));
|
|
28593
28796
|
return ok(browserRecordV2.parse({ contract: "browser-record", version: 2, sessionId, head: query.head, id: query.id, ...found }));
|
|
28594
28797
|
} }),
|
|
28798
|
+
// One document's decision flow in the HEAD the reader is on: the commits that changed it, a page of them at a time.
|
|
28799
|
+
route({ method: "GET", path: "/api/v1/document-history", session: true, query: browserDocumentHistoryQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
|
|
28800
|
+
const found = await documentHistoryPage(source2, query.head, query.id, { after: query.after, limit: query.limit ?? PAGE });
|
|
28801
|
+
if (found === void 0) throw new HttpError(404, "NOT_FOUND", t2("server.documentNotFound"));
|
|
28802
|
+
if (found === null) throw cursorGone2();
|
|
28803
|
+
return ok(browserDocumentHistoryV1.parse({ contract: "browser-document-history", version: 1, sessionId, head: query.head, ...found }));
|
|
28804
|
+
} }),
|
|
28595
28805
|
// What is not committed yet, worked out again on every request: the uncommitted entry of the records list.
|
|
28596
28806
|
route({ method: "GET", path: "/api/v1/working", session: true, unreadable: unreadable2, handle: async () => ok(browserWorkingV1.parse({ contract: "browser-working", version: 1, sessionId, ...await workingOverview(working2) })) }),
|
|
28597
28807
|
route({ method: "GET", path: "/api/v1/working/change", session: true, query: browserWorkingChangeQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
|
|
28598
28808
|
const change2 = await workingChange2(working2, query.id);
|
|
28599
28809
|
if (!change2) throw new HttpError(404, "NOT_FOUND", t2("server.workingChangeNotFound"));
|
|
28600
|
-
return ok(
|
|
28810
|
+
return ok(browserWorkingChangeV2.parse({ contract: "browser-working-change", version: 2, sessionId, ...change2 }));
|
|
28601
28811
|
} }),
|
|
28602
28812
|
// The source a commit changed beside its documents, read from Git when the commit or record page asks for it.
|
|
28603
28813
|
route({ method: "GET", path: "/api/v1/commit/files", session: true, query: browserCommitFilesQueryV2, unreadable: unreadable2, handle: async ({ query }) => {
|
|
@@ -28973,11 +29183,11 @@ import { readFile as readFile11 } from "node:fs/promises";
|
|
|
28973
29183
|
// src/commands/output.ts
|
|
28974
29184
|
var formats = ["text", "json"];
|
|
28975
29185
|
var CommandError = class extends Error {
|
|
28976
|
-
constructor(code, message, details = {},
|
|
29186
|
+
constructor(code, message, details = {}, lines2 = []) {
|
|
28977
29187
|
super(message);
|
|
28978
29188
|
this.code = code;
|
|
28979
29189
|
this.details = details;
|
|
28980
|
-
this.lines =
|
|
29190
|
+
this.lines = lines2;
|
|
28981
29191
|
}
|
|
28982
29192
|
code;
|
|
28983
29193
|
details;
|
|
@@ -28994,13 +29204,13 @@ async function runCommand(contract, format2, run) {
|
|
|
28994
29204
|
const code = known ? error62.code : contract.toUpperCase() + "_FAILED";
|
|
28995
29205
|
const message = known ? error62.message : t2("command.failed");
|
|
28996
29206
|
const details = error62 instanceof CommandError ? error62.details : {};
|
|
28997
|
-
const
|
|
28998
|
-
process.stderr.write(format2 === "json" ? JSON.stringify({ ...envelope, ok: false, error: { code, message, ...details } }) + "\n" : [code + ": " + message, ...
|
|
29207
|
+
const lines2 = error62 instanceof CommandError ? error62.lines : [];
|
|
29208
|
+
process.stderr.write(format2 === "json" ? JSON.stringify({ ...envelope, ok: false, error: { code, message, ...details } }) + "\n" : [code + ": " + message, ...lines2].join("\n") + "\n");
|
|
28999
29209
|
process.exitCode = 1;
|
|
29000
29210
|
}
|
|
29001
29211
|
}
|
|
29002
|
-
var section = (label,
|
|
29003
|
-
var text2 = (
|
|
29212
|
+
var section = (label, lines2, indent = " ") => lines2.length ? [label, ...lines2.map((line2) => indent + line2)] : [];
|
|
29213
|
+
var text2 = (lines2) => lines2.join("\n") + "\n";
|
|
29004
29214
|
|
|
29005
29215
|
// src/commands/guide.ts
|
|
29006
29216
|
var guideTopics = ["workflow", "spec", "design", "instructions", "records", "writing", "commit", "migrate"];
|
|
@@ -29071,8 +29281,8 @@ function findBlock(text4) {
|
|
|
29071
29281
|
function isWrapperFile(text4) {
|
|
29072
29282
|
const found = findBlock(text4);
|
|
29073
29283
|
const own2 = found ? text4.slice(0, found.start) + text4.slice(found.end) : text4;
|
|
29074
|
-
const
|
|
29075
|
-
return
|
|
29284
|
+
const lines2 = own2.split(/\r?\n/).map((line2) => line2.trim()).filter(Boolean);
|
|
29285
|
+
return lines2.length > 0 && lines2.every((line2) => /^@(?:\.\/)?[^\s]+$/.test(line2) && candidatePaths.includes(line2.replace(/^@(?:\.\/)?/, "")));
|
|
29076
29286
|
}
|
|
29077
29287
|
var CLAUDE_WRAPPER_PATH = "CLAUDE.md";
|
|
29078
29288
|
function claudeWrapperFor(agents2) {
|
|
@@ -29662,6 +29872,10 @@ async function createDocument(project, kind2, path3, options) {
|
|
|
29662
29872
|
for (const [field, value] of [["title", options.title], ["description", options.description]]) {
|
|
29663
29873
|
if (/[\r\n]/.test(value)) throw new CommandError("INVALID_VALUE", t2("docs.singleLine", { field }));
|
|
29664
29874
|
}
|
|
29875
|
+
if (options.style && kind2 !== "requirement") throw new CommandError("INVALID_VALUE", t2("docs.styleRequirementOnly"));
|
|
29876
|
+
const projectStyle = project.config.requirementStyle;
|
|
29877
|
+
const style2 = kind2 === "requirement" ? options.style ?? projectStyle ?? "default" : void 0;
|
|
29878
|
+
const styleKey = style2 === "usecase" || style2 === "default" && projectStyle === "usecase" ? { style: style2 } : {};
|
|
29665
29879
|
const target = newPath(kind2, path3);
|
|
29666
29880
|
const { documents } = await project.cache.documents.list();
|
|
29667
29881
|
const taken = new Set(documents.map((d) => d.id));
|
|
@@ -29672,9 +29886,10 @@ async function createDocument(project, kind2, path3, options) {
|
|
|
29672
29886
|
const folder = target.slice(0, target.lastIndexOf("/") + 1);
|
|
29673
29887
|
const siblings = documents.filter((d) => (d.kind === "requirement" || d.kind === "design") && d.path.startsWith(folder) && !d.path.slice(folder.length).includes("/"));
|
|
29674
29888
|
const order = Math.min(999999, Math.max(0, ...siblings.map((d) => d.order)) + 10);
|
|
29675
|
-
const
|
|
29889
|
+
const body2 = style2 === "usecase" ? t2("docs.skeleton.requirementUsecase") : skeleton[kind2]();
|
|
29890
|
+
const base = { id, path: target, title: options.title.trim(), description: options.description.trim(), body: body2, draft: true };
|
|
29676
29891
|
const feature2 = target.split("/")[2];
|
|
29677
|
-
const doc = kind2 === "feature" ? { kind: kind2, feature: feature2, ...base } : kind2 === "instruction" ? { kind: kind2, name: path3, ...base } : kind2 === "requirement" ? { kind: kind2, feature: feature2, order, ...base } : { kind: kind2, feature: feature2, order, requirements: [], sources: [], ...base };
|
|
29892
|
+
const doc = kind2 === "feature" ? { kind: kind2, feature: feature2, ...base } : kind2 === "instruction" ? { kind: kind2, name: path3, ...base } : kind2 === "requirement" ? { kind: kind2, feature: feature2, order, ...styleKey, ...base } : { kind: kind2, feature: feature2, order, requirements: [], sources: [], ...base };
|
|
29678
29893
|
const rendered = renderDocumentFile(doc);
|
|
29679
29894
|
parseDocumentFile(target, rendered);
|
|
29680
29895
|
try {
|
|
@@ -29732,13 +29947,14 @@ function cursorGone(options) {
|
|
|
29732
29947
|
throw new CommandError("INVALID_VALUE", t2("list.after", { cursor: options.after ?? "" }));
|
|
29733
29948
|
}
|
|
29734
29949
|
var pageLine = (page, before = 0, unit = t2("list.items")) => page.next === null ? [] : [t2("list.more", { shown: before + page.rows.length, total: page.total, unit, cursor: page.next })];
|
|
29735
|
-
function aside(format2,
|
|
29736
|
-
if (format2 === "text" &&
|
|
29950
|
+
function aside(format2, lines2) {
|
|
29951
|
+
if (format2 === "text" && lines2.length) process.stderr.write(lines2.join("\n") + "\n");
|
|
29737
29952
|
return "";
|
|
29738
29953
|
}
|
|
29739
29954
|
|
|
29740
29955
|
// src/commands/specs.ts
|
|
29741
29956
|
var specKinds = ["feature", "requirement", "design"];
|
|
29957
|
+
var specStyles = requirementStyles;
|
|
29742
29958
|
var specSorts = ["order", "title", "updated"];
|
|
29743
29959
|
var columns = ["id", "kind", "feature", "path", "title", "description", "order", "draft", "state", "previousPath", "requirements", "sources", "designs", "updated", "line"];
|
|
29744
29960
|
var kindLabel = { feature: () => t2("docs.feature"), requirement: () => t2("docs.requirement"), design: () => t2("docs.design") };
|
|
@@ -30136,6 +30352,10 @@ var recordLine = (r, changes2) => {
|
|
|
30136
30352
|
const changed = new Set(changes2.map((c) => c.id));
|
|
30137
30353
|
return `${r.id} ${r.title}${r.draft ? " (" + t2("docs.draft") + ")" : ""} \u2014 ${r.docs.map((d) => changed.has(d) ? d : d + "*").join(", ")}`;
|
|
30138
30354
|
};
|
|
30355
|
+
var formatWarnings = (changes2, documents, project) => {
|
|
30356
|
+
const touched = new Set(changes2.map((c) => c.id));
|
|
30357
|
+
return documents.filter((d) => touched.has(d.id)).flatMap((d) => requirementFormatWarnings(d, project.config.requirementStyle));
|
|
30358
|
+
};
|
|
30139
30359
|
var recordSummary = (r) => ({ id: r.id, title: r.title, docs: r.docs, path: r.path, ...r.draft ? { draft: true } : {} });
|
|
30140
30360
|
var runChangesList = (options, controls = {}) => runCommand("changes", options.format, async () => {
|
|
30141
30361
|
const project = await openProject(process.cwd());
|
|
@@ -30146,7 +30366,8 @@ var runChangesList = (options, controls = {}) => runCommand("changes", options.f
|
|
|
30146
30366
|
const withoutRecord = uncovered(changes2, records2);
|
|
30147
30367
|
const sharedDocuments = shared(changes2, records2);
|
|
30148
30368
|
const problems = [...working2.problems, ...pending.problems, ...checked.problems];
|
|
30149
|
-
const
|
|
30369
|
+
const formats2 = formatWarnings(changes2, checked.documents, project);
|
|
30370
|
+
const warnings = [...await readDocumentWarnings(project.root, checked.documents), ...formats2];
|
|
30150
30371
|
const inputs = await prepareAgentInputs(project.root, controls).catch(() => void 0);
|
|
30151
30372
|
const out = changes2.length ? [t2("changes.changed", { count: changes2.length }), ...changes2.map((c) => " " + changeLine(c))] : [t2("changes.none")];
|
|
30152
30373
|
out.push(...section(t2("changes.pendingRecords", { count: records2.length }), records2.map((r) => recordLine(r, changes2))));
|
|
@@ -30154,7 +30375,8 @@ var runChangesList = (options, controls = {}) => runCommand("changes", options.f
|
|
|
30154
30375
|
if (sharedDocuments.length) out.push(t2("changes.sharedDocuments", { ids: sharedDocuments.join(", ") }));
|
|
30155
30376
|
if (pending.altered.length) out.push(t2("changes.recordAltered", { paths: pending.altered.join(", ") }));
|
|
30156
30377
|
out.push(problems.length ? t2("changes.problems", { count: problems.length }) : t2("changes.clean"));
|
|
30157
|
-
if (warnings.length) out.push(t2("changes.warnings", { count: warnings.length }));
|
|
30378
|
+
if (warnings.length > formats2.length) out.push(t2("changes.warnings", { count: warnings.length - formats2.length }));
|
|
30379
|
+
out.push(...section(t2("changes.formatWarnings", { count: formats2.length }), formats2.map((w) => w.code + " " + w.message)));
|
|
30158
30380
|
if (inputs) out.push(t2("changes.input", { path: inputs.commit }));
|
|
30159
30381
|
return { json: { head, changes: changes2, pendingRecords: records2.map(recordSummary), withoutRecord, sharedDocuments, alteredRecords: pending.altered, problems, warnings, inputs: inputs ?? null }, text: text2(out) };
|
|
30160
30382
|
});
|
|
@@ -30169,6 +30391,7 @@ var runChangesCommit = (options, controls = {}) => runCommand("changes", options
|
|
|
30169
30391
|
...result.changes.map((c) => " " + changeLine(c)),
|
|
30170
30392
|
...result.records.map((r) => " " + r.id + " " + r.title),
|
|
30171
30393
|
...result.withoutRecord.length ? [t2("changes.withoutRecord", { ids: result.withoutRecord.join(", ") })] : [],
|
|
30394
|
+
...section(t2("changes.formatWarnings", { count: result.warnings.length }), result.warnings.map((w) => w.code + " " + w.message)),
|
|
30172
30395
|
...result.trailers
|
|
30173
30396
|
];
|
|
30174
30397
|
return { json: { ...json3, ...inputRemoved === void 0 ? {} : { inputRemoved } }, text: text2(out) };
|
|
@@ -30225,6 +30448,7 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30225
30448
|
const split = changes2.filter((c) => c.previousPath !== void 0 && !(selected2.includes(c.path) && selected2.includes(c.previousPath)));
|
|
30226
30449
|
if (split.length) fail3(t2("commit.selectMove", { ids: split.map((c) => c.id).join(", ") }));
|
|
30227
30450
|
const withoutRecord = uncovered(changes2, records2);
|
|
30451
|
+
const warnings = formatWarnings(changes2, checked.documents, project);
|
|
30228
30452
|
const status = (await git(["status", "--porcelain=v1", "-z", "--untracked-files=all", "--no-renames", "--", ".gitifact"])).toString("utf8").split("\0").filter(Boolean);
|
|
30229
30453
|
const removed = new Set(status.filter((entry2) => entry2.slice(0, 2).includes("D")).map((entry2) => entry2.slice(3)));
|
|
30230
30454
|
checkStoreSelection(selected2.filter((p) => !(underDocuments(p) && removed.has(p))));
|
|
@@ -30241,7 +30465,7 @@ async function commitChanges(cwd, input2, dryRun) {
|
|
|
30241
30465
|
const contextPaths = policyPaths(selected2);
|
|
30242
30466
|
const hashes = async (list) => new Map(await Promise.all(list.map(async (p) => [p, await fingerprint(root, p)])));
|
|
30243
30467
|
const started = await hashes([.../* @__PURE__ */ new Set([...selected2, ...contextPaths])]);
|
|
30244
|
-
const summary = { root, head: base.head, message, paths: selected2, changes: changes2, records: records2.map(recordSummary), withoutRecord, trailers };
|
|
30468
|
+
const summary = { root, head: base.head, message, paths: selected2, changes: changes2, records: records2.map(recordSummary), withoutRecord, warnings, trailers };
|
|
30245
30469
|
if (dryRun) {
|
|
30246
30470
|
if (!same2(base, await project.reader.baseline())) fail3(t2("commit.headChanged"));
|
|
30247
30471
|
return { outcome: "dry-run", committed: false, ...summary, commit: void 0 };
|
|
@@ -30406,12 +30630,13 @@ var runRecordsList = (options) => runCommand("records", options.format, async ()
|
|
|
30406
30630
|
const after = await since(project, options.since, head);
|
|
30407
30631
|
const by = byAuthor(options.author);
|
|
30408
30632
|
const has2 = contains(options.q);
|
|
30633
|
+
const hash3 = hashPrefix(options.q);
|
|
30409
30634
|
const id = options.doc;
|
|
30410
|
-
const
|
|
30411
|
-
|
|
30412
|
-
const
|
|
30413
|
-
|
|
30414
|
-
const page = paginate(events.filter((e) => after(e) && by(e) && has2(
|
|
30635
|
+
const found2 = await documentHistory(project, head, id);
|
|
30636
|
+
if (!found2) throw new CommandError("UNKNOWN_DOCUMENT", t2("docs.unknownDocument", { ids: id }));
|
|
30637
|
+
const { events } = found2;
|
|
30638
|
+
const title = found2.doc.title;
|
|
30639
|
+
const page = paginate(events.filter((e) => after(e) && by(e) && (has2(...e.records.flatMap((r) => [r.title, r.id, ...sectionText(r.sections)])) || !!hash3 && e.commit.startsWith(hash3))).map((e) => ({
|
|
30415
30640
|
commit: e.commit,
|
|
30416
30641
|
date: e.date,
|
|
30417
30642
|
author: e.author,
|
|
@@ -30449,7 +30674,7 @@ var runRecordsList = (options) => runCommand("records", options.format, async ()
|
|
|
30449
30674
|
} catch {
|
|
30450
30675
|
return [];
|
|
30451
30676
|
}
|
|
30452
|
-
}).map((r) => ({ id: r.id, title: r.title, commit: null, date: null, author: null, docs: r.docs, sections: r.sections.map((s) => ({ key: s.key, body: s.body })) }))).filter((r) => has(r.title, ...sectionText(r.sections))).sort((a, b) => a.id < b.id ? -1 : 1);
|
|
30677
|
+
}).map((r) => ({ id: r.id, title: r.title, commit: null, date: null, author: null, docs: r.docs, sections: r.sections.map((s) => ({ key: s.key, body: s.body })) }))).filter((r) => has(r.title, r.id, ...sectionText(r.sections))).sort((a, b) => a.id < b.id ? -1 : 1);
|
|
30453
30678
|
const size = options.all ? void 0 : options.limit ?? PAGE_SIZE;
|
|
30454
30679
|
const inPending = options.after === void 0 ? 0 : pending.findIndex((r) => r.id === options.after) + 1;
|
|
30455
30680
|
const afterCommitted = options.after !== void 0 && !inPending ? options.after : void 0;
|
|
@@ -30759,23 +30984,23 @@ async function runUpdate(options, version2) {
|
|
|
30759
30984
|
process.stdout.write(JSON.stringify(dto) + "\n");
|
|
30760
30985
|
return;
|
|
30761
30986
|
}
|
|
30762
|
-
const
|
|
30763
|
-
|
|
30764
|
-
if (dto.install)
|
|
30765
|
-
|
|
30766
|
-
if (dto.agentDocs.missing.length)
|
|
30767
|
-
if (dto.project.state === "written")
|
|
30768
|
-
if (dto.project.cli && isNewerRelease(dto.project.cli, dto.cliVersion))
|
|
30769
|
-
if (dto.migrationRequired)
|
|
30987
|
+
const lines2 = [t2("update.text.current", { version: dto.cliVersion })];
|
|
30988
|
+
lines2.push(dto.update.status === "available" ? t2("update.text.available", { version: dto.update.latestVersion }) : dto.update.status === "up-to-date" ? t2("update.text.upToDate") : dto.update.status === "disabled" ? t2("update.text.disabled") : t2("update.text.unavailable"));
|
|
30989
|
+
if (dto.install) lines2.push(t2("update.text.install", { command: dto.install.npmGlobal }), t2("update.text.afterInstall"));
|
|
30990
|
+
lines2.push(dto.agentDocs.state === "refreshed" ? t2("update.text.blockRefreshed", { paths: dto.agentDocs.paths.join(", ") }) : dto.agentDocs.state === "current" ? t2("update.text.blockCurrent", { paths: dto.agentDocs.paths.join(", ") }) : dto.agentDocs.state === "kept" ? t2("update.text.blockKept", { paths: dto.agentDocs.paths.join(", ") || "-" }) : dto.agentDocs.state === "no-block" ? t2("update.text.noBlock") : t2("update.text.notInitialized"));
|
|
30991
|
+
if (dto.agentDocs.missing.length) lines2.push(t2("update.text.missing", { paths: dto.agentDocs.missing.join(", ") }));
|
|
30992
|
+
if (dto.project.state === "written") lines2.push(t2("update.text.projectWritten", { path: CONFIG_PATH, version: dto.project.cli ?? dto.cliVersion }));
|
|
30993
|
+
if (dto.project.cli && isNewerRelease(dto.project.cli, dto.cliVersion)) lines2.push(t2("update.text.projectAhead", { project: dto.project.cli, version: dto.cliVersion, command: npmGlobalInstall(dto.project.cli) }));
|
|
30994
|
+
if (dto.migrationRequired) lines2.push(t2("update.text.migrationRequired", { version: dto.cliVersion }));
|
|
30770
30995
|
const { commit } = dto;
|
|
30771
|
-
if (commit.state === "committed")
|
|
30772
|
-
else if (commit.state === "nothing")
|
|
30996
|
+
if (commit.state === "committed") lines2.push(t2("update.text.committed", { commit: commit.commit.slice(0, 12), paths: commit.paths.join(", ") }));
|
|
30997
|
+
else if (commit.state === "nothing") lines2.push(t2("update.text.commitNothing"));
|
|
30773
30998
|
else if (commit.state === "skipped") {
|
|
30774
30999
|
const paths2 = commit.paths.join(", ");
|
|
30775
31000
|
const text4 = commit.reason === "untracked" ? t2("update.text.commitSkipped.untracked", { paths: paths2 }) : commit.reason === "other-changes" ? t2("update.text.commitSkipped.other-changes", { paths: paths2 }) : t2("update.text.commitSkipped.commit-failed", { paths: paths2 });
|
|
30776
|
-
|
|
31001
|
+
lines2.push(text4 + (commit.detail ? " (" + commit.detail + ")" : ""));
|
|
30777
31002
|
}
|
|
30778
|
-
process.stdout.write(
|
|
31003
|
+
process.stdout.write(lines2.join("\n") + "\n");
|
|
30779
31004
|
} catch (error62) {
|
|
30780
31005
|
const known = error62 instanceof InitError || error62 instanceof RepositoryReadError;
|
|
30781
31006
|
const failure2 = { code: known ? error62.code : "UPDATE_FAILED", message: known ? error62.message : t2("update.failed") };
|
|
@@ -30804,12 +31029,12 @@ async function runUpdateCheck(format2, version2) {
|
|
|
30804
31029
|
return;
|
|
30805
31030
|
}
|
|
30806
31031
|
const state2 = dto.update;
|
|
30807
|
-
const
|
|
31032
|
+
const lines2 = [
|
|
30808
31033
|
t2("update.text.current", { version: dto.cliVersion }),
|
|
30809
31034
|
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")
|
|
30810
31035
|
];
|
|
30811
|
-
if (state2.status === "available")
|
|
30812
|
-
process.stdout.write(
|
|
31036
|
+
if (state2.status === "available") lines2.push(t2("update.text.install", { command: npmGlobalInstall(state2.latestVersion) }), t2("update.text.afterInstall"));
|
|
31037
|
+
process.stdout.write(lines2.join("\n") + "\n");
|
|
30813
31038
|
}
|
|
30814
31039
|
|
|
30815
31040
|
// src/commands/version-notice.ts
|
|
@@ -30884,17 +31109,17 @@ for (let i = 0; i < languageArgs.length; i++) {
|
|
|
30884
31109
|
if (value === "ko" || value === "en") selectedLanguage = value;
|
|
30885
31110
|
}
|
|
30886
31111
|
configureLanguage(selectedLanguage ?? environmentLanguage(), selectedLanguage);
|
|
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.
|
|
31112
|
+
var program2 = new Command().name("gitifact").addOption(new Option("--lang <language>", t2("help.lang")).choices(["ko", "en"])).description(t2("help.program")).version("0.8.6").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
|
|
30888
31113
|
program2.hook("preAction", async (_program, action) => {
|
|
30889
31114
|
let top = action;
|
|
30890
31115
|
while (top.parent && top.parent !== program2) top = top.parent;
|
|
30891
|
-
if (top.name() !== REFRESH_COMMAND) await noticeVersion("0.8.
|
|
31116
|
+
if (top.name() !== REFRESH_COMMAND) await noticeVersion("0.8.6", top.name());
|
|
30892
31117
|
});
|
|
30893
|
-
program2.command(REFRESH_COMMAND, { hidden: true }).allowExcessArguments(false).action(() => refreshUpdateCache("0.8.
|
|
31118
|
+
program2.command(REFRESH_COMMAND, { hidden: true }).allowExcessArguments(false).action(() => refreshUpdateCache("0.8.6"));
|
|
30894
31119
|
var format = () => new Option("--format <format>", t2("help.format")).choices(formats).default("text");
|
|
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.
|
|
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.
|
|
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.
|
|
31120
|
+
program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).action((options) => runBrowser(options, "0.8.6"));
|
|
31121
|
+
program2.command("init").description(t2("help.init")).allowExcessArguments(false).option("--dry-run", t2("help.initDryRun")).addOption(new Option("--agent <agent>", t2("help.initAgent")).choices([...agentPresetNames])).addOption(new Option("--remove-agents", t2("help.initRemoveAgents")).conflicts("skipAgents")).option("--skip-agents", t2("help.initSkipAgents")).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runInit(options, "0.8.6"));
|
|
31122
|
+
program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).option("--commit", t2("help.updateCommit")).addOption(new Option("--check", t2("help.updateCheck")).conflicts("commit")).addOption(new Option("--later", t2("help.updateLater")).conflicts(["check", "commit"])).action((options) => options.later ? runUpdateLater(options.format, "0.8.6") : options.check ? runUpdateCheck(options.format, "0.8.6") : runUpdate(options, "0.8.6"));
|
|
30898
31123
|
var listed2 = (command, sorts) => {
|
|
30899
31124
|
command.allowExcessArguments(false).option("--q <words>", t2("help.listQ")).option("--author <name>", t2("help.listAuthor"));
|
|
30900
31125
|
if (sorts) command.addOption(new Option("--sort <key>", t2("help.listSort")).choices([...sorts]).default(sorts[0]));
|
|
@@ -30903,7 +31128,7 @@ var listed2 = (command, sorts) => {
|
|
|
30903
31128
|
var specs = program2.command("specs").description(t2("help.specs"));
|
|
30904
31129
|
listed2(specs.command("list").description(t2("help.specsList")).addOption(new Option("--type <kind>", t2("help.specsListType")).choices([...specKinds])).option("--feature <folder>", t2("help.specsListFeature")).option("--without-design", t2("help.specsListWithoutDesign")).option("--uncovered", t2("help.specsListUncovered")).option("--draft", t2("help.specsListDraft")).option("--changed-since <date|commit>", t2("help.specsListChangedSince")), specSorts).action((o) => runSpecsList(o));
|
|
30905
31130
|
specs.command("show").description(t2("help.specsShow")).argument("<ids...>", t2("help.specsShowIds")).option("--ref <commit>", t2("help.showRef")).addOption(format()).action((ids, o) => runSpecsShow(ids, o));
|
|
30906
|
-
specs.command("new").description(t2("help.specsNew")).allowExcessArguments(false).addArgument(new Argument("<kind>", t2("help.specsNewKind")).choices(specKinds)).argument("<path>", t2("help.specsNewPath")).requiredOption("--title <title>", t2("help.newTitle")).requiredOption("--description <text>", t2("help.newDescription")).addOption(format()).action((kind2, path3, o) => runSpecsNew(kind2, path3, o));
|
|
31131
|
+
specs.command("new").description(t2("help.specsNew")).allowExcessArguments(false).addArgument(new Argument("<kind>", t2("help.specsNewKind")).choices(specKinds)).argument("<path>", t2("help.specsNewPath")).requiredOption("--title <title>", t2("help.newTitle")).requiredOption("--description <text>", t2("help.newDescription")).addOption(new Option("--style <style>", t2("help.specsNewStyle")).choices(specStyles)).addOption(format()).action((kind2, path3, o) => runSpecsNew(kind2, path3, o));
|
|
30907
31132
|
var instructions = program2.command("instructions").description(t2("help.instructions"));
|
|
30908
31133
|
listed2(instructions.command("list").description(t2("help.instructionsList")), instructionSorts).action((o) => runInstructionsList(o));
|
|
30909
31134
|
instructions.command("show").description(t2("help.instructionsShow")).argument("<targets...>", t2("help.instructionsShowTargets")).option("--ref <commit>", t2("help.showRef")).option("--file <path>", t2("help.instructionsShowFile")).addOption(format()).action((targets, o) => runInstructionsShow(targets, o));
|
|
@@ -30916,7 +31141,7 @@ program2.command("check").description(t2("help.check")).allowExcessArguments(fal
|
|
|
30916
31141
|
var changes = program2.command("changes").description(t2("help.changes"));
|
|
30917
31142
|
changes.command("list").description(t2("help.changesList")).allowExcessArguments(false).addOption(format()).action((o) => runChangesList(o));
|
|
30918
31143
|
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));
|
|
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.
|
|
31144
|
+
program2.command("feedback").description(t2("help.feedback")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.feedbackFile")).option("--dry-run", t2("help.feedbackDryRun")).addOption(format()).action((o) => runFeedback(o, "0.8.6"));
|
|
30920
31145
|
var guide = program2.command("guide").description(t2("help.guide"));
|
|
30921
31146
|
guide.command("list").description(t2("help.guideList")).allowExcessArguments(false).addOption(format()).action((o) => runGuideList(o));
|
|
30922
31147
|
guide.command("show").description(t2("help.guideShow")).argument("<topic>", t2("help.guideTopic")).allowExcessArguments(false).addOption(format()).action((topic, o) => runGuideShow(topic, o));
|