gitifact 0.8.5 → 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.
Files changed (54) hide show
  1. package/dist/browser/assets/{HgiRefresh-BSPkIVFZ.js → HgiRefresh-CnBE2KZ8.js} +1 -1
  2. package/dist/browser/assets/{Markdown-B1P3lpA0.js → Markdown-75QVB57V.js} +1 -1
  3. package/dist/browser/assets/{Selector-BG3Gd_OR.js → Selector-E8jyEKNB.js} +1 -1
  4. package/dist/browser/assets/Tab-C-PhLRIZ.js +4 -0
  5. package/dist/browser/assets/{Table-DjTkmoR7.js → Table-Cr2jvka_.js} +1 -1
  6. package/dist/browser/assets/{Token-D337a1e3.js → Token-BBk7tRek.js} +1 -1
  7. package/dist/browser/assets/{about-D06ipt4C.js → about-C3ewDfU2.js} +1 -1
  8. package/dist/browser/assets/{activity-timeline-Bl6a55GR.js → activity-timeline-B3s0viEt.js} +2 -2
  9. package/dist/browser/assets/changelog-DkRd6I8J.js +1 -0
  10. package/dist/browser/assets/commit-BHwKZ7hK.js +4 -0
  11. package/dist/browser/assets/{contributor-D1TZSDq9.js → contributor-CqqvzxLh.js} +1 -1
  12. package/dist/browser/assets/{contributors-lkpVuCXS.js → contributors-CuMPZx6_.js} +1 -1
  13. package/dist/browser/assets/{contributors._email-B7ATmxN1.js → contributors._email-CEcZZfAR.js} +1 -1
  14. package/dist/browser/assets/{contributors.index-Cc0QRJwQ.js → contributors.index-DNMBFxLb.js} +1 -1
  15. package/dist/browser/assets/dashboard.index-nV7KwM5H.js +1 -0
  16. package/dist/browser/assets/{document-7jVYmB_Z.js → document-BnxE7Txb.js} +1 -1
  17. package/dist/browser/assets/{document-kGFspd5u.js → document-odLLdugz.js} +1 -1
  18. package/dist/browser/assets/features-C0YzZiS-.js +2 -0
  19. package/dist/browser/assets/{features._featureId-DGUBnzjL.js → features._featureId-Cmg8-2ku.js} +1 -1
  20. package/dist/browser/assets/{features.index-Dgw4kiMG.js → features.index-CBz7BmRW.js} +1 -1
  21. package/dist/browser/assets/{getting-started-B_LeBSZE.js → getting-started-CaOhGSBe.js} +1 -1
  22. package/dist/browser/assets/git-DwAnKiiN.js +1 -0
  23. package/dist/browser/assets/{index-IML0_BCy.js → index-BljzO9go.js} +4 -4
  24. package/dist/browser/assets/{instructions-Qhbd8_KG.js → instructions-DWS_nwe0.js} +1 -1
  25. package/dist/browser/assets/{instructions._instructionId-CnX6OyFZ.js → instructions._instructionId-l7aWWvfx.js} +1 -1
  26. package/dist/browser/assets/instructions.agents-t7hMe4Pv.js +1 -0
  27. package/dist/browser/assets/instructions.index-CHVCQBSH.js +1 -0
  28. package/dist/browser/assets/{lazyRouteComponent-tJOK5sxC.js → lazyRouteComponent-BZI8yQj_.js} +1 -1
  29. package/dist/browser/assets/{load-more-DVsjzCxE.js → load-more-BVsXjzHC.js} +1 -1
  30. package/dist/browser/assets/page-header-CRcXie4p.js +248 -0
  31. package/dist/browser/assets/{records._recordId-C2qxnLKN.js → records._recordId-DF-NkdBL.js} +1 -1
  32. package/dist/browser/assets/{records.commits._commit-CSa3sQ8C.js → records.commits._commit-BBf_rxHJ.js} +1 -1
  33. package/dist/browser/assets/{records.docs._docId-SIPsGTwH.js → records.docs._docId-Diev5opj.js} +1 -1
  34. package/dist/browser/assets/{records.index-DoE_3GrP.js → records.index-DPWv9blV.js} +1 -1
  35. package/dist/browser/assets/{records.working-Cp5ualrr.js → records.working-D5xv-dTD.js} +1 -1
  36. package/dist/browser/assets/{settings-tVQIx1Uf.js → settings-N1hE7l-i.js} +1 -1
  37. package/dist/browser/assets/{useInfiniteQuery-C0rB-9Ci.js → useInfiniteQuery-CrEm5UW2.js} +1 -1
  38. package/dist/browser/assets/{useKeyboardHint-D5jGavym.js → useKeyboardHint-CGJ2GVT3.js} +1 -1
  39. package/dist/browser/index.html +20 -20
  40. package/dist/i18n/en/changelog.md +11 -0
  41. package/dist/i18n/en/docs/spec.md +79 -3
  42. package/dist/i18n/ko/changelog.md +11 -0
  43. package/dist/i18n/ko/docs/spec.md +79 -3
  44. package/dist/main.js +140 -62
  45. package/package.json +1 -1
  46. package/dist/browser/assets/Tab-RKLZrCiK.js +0 -1
  47. package/dist/browser/assets/changelog-DCvEVceR.js +0 -1
  48. package/dist/browser/assets/commit-Cj7mcn9u.js +0 -4
  49. package/dist/browser/assets/dashboard.index-BNTyn3_V.js +0 -1
  50. package/dist/browser/assets/features-CBeEOrok.js +0 -2
  51. package/dist/browser/assets/git-DW-pzDOm.js +0 -1
  52. package/dist/browser/assets/instructions.agents-0tKcPahQ.js +0 -1
  53. package/dist/browser/assets/instructions.index-B3v6vtEg.js +0 -1
  54. package/dist/browser/assets/page-header-AS8jZ1ve.js +0 -248
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}",
@@ -3520,6 +3521,9 @@ var messages_default = {
3520
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}",
3521
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}",
3522
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}",
3523
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."
3524
3528
  };
3525
3529
 
@@ -3531,6 +3535,7 @@ var messages_default2 = {
3531
3535
  "config.schemaFields": "Check the schemaVersion and baseline fields.",
3532
3536
  "config.cliVersion": "The config field cli must be a release version such as 0.8.3.",
3533
3537
  "config.language": "The config field language must be one of {languages}.",
3538
+ "config.requirementStyle": "The config field requirementStyle must be one of {styles}.",
3534
3539
  "document.pathTooLong": "Wiki page path exceeds the depth or length limit: {path}",
3535
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}",
3536
3541
  "document.folderName": "Wiki folder names must use lowercase letters, digits and hyphens: {path}",
@@ -3642,6 +3647,9 @@ var messages_default2 = {
3642
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}",
3643
3648
  "warn.REQUIREMENT_SCOPE_FORMAT": "Scope and constraints come before the acceptance criteria, as - items only (guide show spec): {path}",
3644
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}",
3645
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."
3646
3654
  };
3647
3655
 
@@ -3682,6 +3690,29 @@ async function readRepositoryStatus(reader, services) {
3682
3690
  };
3683
3691
  }
3684
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
+
3685
3716
  // ../../packages/core/dist/formats/spec-project.js
3686
3717
  var InitError = class extends Error {
3687
3718
  code;
@@ -3746,6 +3777,11 @@ function parseManagedConfig(text4) {
3746
3777
  throw new InitError("INVALID_CONFIG", t("config.language", { languages: PROJECT_LANGUAGES.join(", ") }));
3747
3778
  config2.language = value.language;
3748
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
+ }
3749
3785
  return config2;
3750
3786
  }
3751
3787
  function formatManagedConfig(config2, previous) {
@@ -3753,7 +3789,7 @@ function formatManagedConfig(config2, previous) {
3753
3789
  if (previous !== void 0) {
3754
3790
  const value = JSON.parse(previous);
3755
3791
  if (object(value)) {
3756
- 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;
3757
3793
  unknown2 = rest;
3758
3794
  }
3759
3795
  }
@@ -3761,7 +3797,8 @@ function formatManagedConfig(config2, previous) {
3761
3797
  schemaVersion: config2.schemaVersion,
3762
3798
  baseline: config2.baseline,
3763
3799
  ...config2.cli === void 0 ? {} : { cli: config2.cli },
3764
- ...config2.language === void 0 ? {} : { language: config2.language }
3800
+ ...config2.language === void 0 ? {} : { language: config2.language },
3801
+ ...config2.requirementStyle === void 0 ? {} : { requirementStyle: config2.requirementStyle }
3765
3802
  };
3766
3803
  return JSON.stringify({ ...known, ...unknown2 }, null, 2) + "\n";
3767
3804
  }
@@ -3834,7 +3871,7 @@ var WIKI_DIR = ".gitifact/wiki";
3834
3871
  var WIKI_HISTORY_PATH = WIKI_DIR + "/history.jsonl";
3835
3872
  var WIKI_ENTRY = "README.md";
3836
3873
  var WIKI_ENTRY_PATH = WIKI_DIR + "/" + WIKI_ENTRY;
3837
- var token = "[a-z2-7]{10}";
3874
+ var token2 = "[a-z2-7]{10}";
3838
3875
  var STORE_DIR = ".gitifact";
3839
3876
  var marker = "gitifact";
3840
3877
  var recordPathPattern = /^(?:\.gitifact\/spec\/[^/]+\/(?:requirements\.md|design\.md|history\.jsonl)|\.gitifact\/wiki\/(?:(?:[^/]+\/)*[^/]+\.md|history\.jsonl))$/;
@@ -3853,7 +3890,7 @@ function validateDocumentRelativePath(relative) {
3853
3890
  if (!nameToken.test(part) || part.length > 80)
3854
3891
  fail(t("document.folderName", { path: relative }));
3855
3892
  }
3856
- var reqId = new RegExp(`^R-${token}$`);
3893
+ var reqId = new RegExp(`^R-${token2}$`);
3857
3894
  var fail = (message) => {
3858
3895
  throw new StoreError(message);
3859
3896
  };
@@ -3867,7 +3904,7 @@ var scalar = (value) => {
3867
3904
  return value;
3868
3905
  };
3869
3906
  function parseFrontmatter(lines2, kind2, legacyIds) {
3870
- const legacy = new RegExp(`^<!-- ${marker}-(?:${kind2 === "wiki" ? "product|guide" : kind2}): (${legacyIds}-${token}) -->$`).exec(lines2[0] ?? "");
3907
+ const legacy = new RegExp(`^<!-- ${marker}-(?:${kind2 === "wiki" ? "product|guide" : kind2}): (${legacyIds}-${token2}) -->$`).exec(lines2[0] ?? "");
3871
3908
  if (legacy) {
3872
3909
  lines2.shift();
3873
3910
  return { id: legacy[1] };
@@ -3915,7 +3952,7 @@ function parseFrontmatter(lines2, kind2, legacyIds) {
3915
3952
  fields2.set("sources", sources3);
3916
3953
  }
3917
3954
  const id = fields2.get("id");
3918
- if (typeof id !== "string" || !new RegExp(`^(?:${legacyIds})-${token}$`).test(id))
3955
+ if (typeof id !== "string" || !new RegExp(`^(?:${legacyIds})-${token2}$`).test(id))
3919
3956
  fail(t("frontmatter.id", { kind: kind2 }));
3920
3957
  for (const key of fields2.keys())
3921
3958
  if (key !== "id" && !(key === "sources" && kind2 === "design"))
@@ -4104,7 +4141,7 @@ function parseSpec(path3, source2, history = "", designSource) {
4104
4141
  for (let i = 0; i < lines2.length; i++) {
4105
4142
  const line2 = lines2[i];
4106
4143
  if (waitingId) {
4107
- const match = new RegExp(`^<!-- ${marker}-req: (R-${token}) -->$`).exec(line2);
4144
+ const match = new RegExp(`^<!-- ${marker}-req: (R-${token2}) -->$`).exec(line2);
4108
4145
  if (!match || !current2)
4109
4146
  fail(t("spec.requirementIdRequired", { path: path3 }));
4110
4147
  current2.id = match[1];
@@ -4176,7 +4213,7 @@ function parseHistory(source2, scope = "spec") {
4176
4213
  if (!value || typeof value !== "object" || Array.isArray(value))
4177
4214
  fail(t("history.invalidRecord"));
4178
4215
  const r = value;
4179
- if (!shapes.includes(Object.keys(r).sort().join(",")) || typeof r.id !== "string" || !new RegExp(`^H-${token}$`).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)
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)
4180
4217
  fail(t("history.invalidFields"));
4181
4218
  ids.add(r.id);
4182
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 });
@@ -4295,28 +4332,6 @@ function compareStoreBundles(a, b) {
4295
4332
  return { specChanges: specs2.specChanges, changes: [...specs2.changes, ...compareWikis(a.wiki, b.wiki)] };
4296
4333
  }
4297
4334
 
4298
- // ../../packages/core/dist/domain/document.js
4299
- var DOC_ID_PREFIX = { feature: "S", requirement: "R", design: "D", wiki: "W", instruction: "I" };
4300
- var RECORD_ID_PREFIX = "DR";
4301
- var token2 = "[a-z2-7]{10}";
4302
- var docIdPattern = new RegExp(`^[SRDWI]-${token2}$`);
4303
- var recordIdPattern = new RegExp(`^DR-${token2}$`);
4304
- var reasonIdPattern = new RegExp(`^H-${token2}$`);
4305
- var idPatternOf = (kind2) => new RegExp(`^${DOC_ID_PREFIX[kind2]}-${token2}$`);
4306
- var kindOfId = (id) => Object.entries(DOC_ID_PREFIX).find(([, prefix]) => id.startsWith(prefix + "-"))?.[0];
4307
- var docWarning = (code, path3, values = {}) => ({ code, path: path3, message: t(`warn.${code}`, { path: path3, ...values }) });
4308
- var docProblem = (code, path3, values = {}) => ({ code, path: path3, message: t(`doc.${code}`, { path: path3, ...values }) });
4309
- var DocumentError = class extends Error {
4310
- code;
4311
- path;
4312
- constructor(code, path3, message) {
4313
- super(message);
4314
- this.code = code;
4315
- this.path = path3;
4316
- this.name = "DocumentError";
4317
- }
4318
- };
4319
-
4320
4335
  // ../../packages/core/dist/domain/record.js
4321
4336
  var recordSectionKeys = ["context", "decision", "alternatives"];
4322
4337
  var RECORD_REQUIRED_SECTIONS = ["context", "decision"];
@@ -4583,7 +4598,7 @@ function classifyDocPath(path3) {
4583
4598
  }
4584
4599
  var KEYS2 = {
4585
4600
  feature: ["id", "title", "description", "draft"],
4586
- requirement: ["id", "title", "description", "order", "draft"],
4601
+ requirement: ["id", "title", "description", "order", "style", "draft"],
4587
4602
  design: ["id", "title", "description", "order", "requirements", "sources", "draft"],
4588
4603
  wiki: ["id", "title", "description", "draft"],
4589
4604
  instruction: ["id", "title", "description", "draft"]
@@ -4689,8 +4704,12 @@ function parseDocumentFile(path3, source2) {
4689
4704
  return { kind: "wiki", ...common };
4690
4705
  if (where.kind === "instruction")
4691
4706
  return { kind: "instruction", name: where.name, ...common };
4692
- if (where.kind === "requirement")
4693
- return { kind: "requirement", feature: where.feature, order: order(), ...common };
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
+ }
4694
4713
  const refs = fields2.get("requirements");
4695
4714
  if (refs && (refs.type !== "list" || refs.items.some((r) => !idPatternOf("requirement").test(r)) || new Set(refs.items).size !== refs.items.length)) {
4696
4715
  throw new DocumentError("FRONTMATTER_VALUE", path3, t("doc.FRONTMATTER_VALUE", { path: path3, value: "requirements" }));
@@ -4716,6 +4735,7 @@ function renderDocumentFile(doc) {
4716
4735
  ["title", doc.title],
4717
4736
  ["description", doc.description],
4718
4737
  ["order", doc.kind === "requirement" || doc.kind === "design" ? doc.order : void 0],
4738
+ ["style", doc.kind === "requirement" ? doc.style : void 0],
4719
4739
  ["requirements", doc.kind === "design" ? doc.requirements : void 0],
4720
4740
  ["sources", doc.kind === "design" ? doc.sources.map((s) => ({ ...s })) : void 0],
4721
4741
  ["draft", doc.draft ? true : void 0]
@@ -4982,9 +5002,21 @@ function documentWarnings(documents, assets, existing) {
4982
5002
  var lines = (body2) => body2.replace(/\r\n/g, "\n").split("\n");
4983
5003
  var scopeHeading = /^###\s+(?:범위와 제약|scope and constraints)\s*$/i;
4984
5004
  var acceptanceHeading = /^###\s+(?:수용 조건|acceptance criteria)\s*$/i;
4985
- function requirementFormatWarnings(doc) {
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) {
4986
5017
  if (doc.kind !== "requirement")
4987
5018
  return [];
5019
+ const missing2 = projectStyle === "usecase" && !doc.style ? [docWarning("REQUIREMENT_STYLE_MISSING", doc.path)] : [];
4988
5020
  const body2 = lines(doc.body);
4989
5021
  const scope = body2.findIndex((line2) => scopeHeading.test(line2.trim()));
4990
5022
  const acceptance = body2.findIndex((line2) => acceptanceHeading.test(line2.trim()));
@@ -4999,6 +5031,38 @@ function requirementFormatWarnings(doc) {
4999
5031
  warnings.push(docWarning("REQUIREMENT_SCOPE_FORMAT", doc.path));
5000
5032
  if (acceptance >= 0 && (outside(sectionOf(acceptance), /^\d+\.\s/) || body2.slice(acceptance + 1).some((line2) => /^#{1,3}\s/.test(line2) && !scopeHeading.test(line2.trim()))))
5001
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));
5002
5066
  return warnings;
5003
5067
  }
5004
5068
 
@@ -25092,7 +25156,8 @@ var state = external_exports.enum(["committed", "added", "modified", "deleted"])
25092
25156
  var standing = { state, previousPath: external_exports.string().optional() };
25093
25157
  var contributor = external_exports.strictObject({ email: external_exports.string(), name: external_exports.string(), commits: external_exports.number().int().nonnegative(), latest: external_exports.string() });
25094
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() });
25095
- 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(), body: external_exports.string(), ...standing });
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 });
25096
25161
  var design = external_exports.strictObject({
25097
25162
  id: external_exports.string(),
25098
25163
  path: external_exports.string(),
@@ -25179,7 +25244,7 @@ var browserFeaturesV1 = external_exports.strictObject({
25179
25244
  next: external_exports.string().nullable(),
25180
25245
  features: external_exports.array(featureRow)
25181
25246
  });
25182
- var browserFeatureV1 = external_exports.strictObject({ contract: external_exports.literal("browser-feature"), version: external_exports.literal(1), sessionId: external_exports.string(), feature });
25247
+ var browserFeatureV2 = external_exports.strictObject({ contract: external_exports.literal("browser-feature"), version: external_exports.literal(2), sessionId: external_exports.string(), feature });
25183
25248
  var browserInstructionsV1 = external_exports.strictObject({
25184
25249
  contract: external_exports.literal("browser-instructions"),
25185
25250
  version: external_exports.literal(1),
@@ -25213,6 +25278,7 @@ var snapshot = external_exports.strictObject({
25213
25278
  specId: external_exports.string(),
25214
25279
  path: external_exports.string(),
25215
25280
  order: external_exports.number().int().optional(),
25281
+ style: style.optional(),
25216
25282
  requirements: external_exports.array(external_exports.string()).optional(),
25217
25283
  sources: external_exports.array(source).optional()
25218
25284
  }).nullable();
@@ -25370,9 +25436,9 @@ var browserCommitV4 = external_exports.strictObject({
25370
25436
  });
25371
25437
  var recordId = external_exports.string().regex(/^(?:DR|H)-[A-Za-z0-9_-]{1,64}$/);
25372
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() });
25373
- var browserCommitChangeV1 = external_exports.strictObject({
25439
+ var browserCommitChangeV2 = external_exports.strictObject({
25374
25440
  contract: external_exports.literal("browser-commit-change"),
25375
- version: external_exports.literal(1),
25441
+ version: external_exports.literal(2),
25376
25442
  sessionId: external_exports.string(),
25377
25443
  commit: oid2,
25378
25444
  event,
@@ -25431,9 +25497,9 @@ var browserWorkingV1 = external_exports.strictObject({
25431
25497
  changes: external_exports.array(workingChange),
25432
25498
  withoutRecord: external_exports.array(external_exports.string())
25433
25499
  });
25434
- var browserWorkingChangeV1 = external_exports.strictObject({
25500
+ var browserWorkingChangeV2 = external_exports.strictObject({
25435
25501
  contract: external_exports.literal("browser-working-change"),
25436
- version: external_exports.literal(1),
25502
+ version: external_exports.literal(2),
25437
25503
  sessionId: external_exports.string(),
25438
25504
  change: workingChange,
25439
25505
  before: snapshot,
@@ -25835,6 +25901,7 @@ var messages_default3 = {
25835
25901
  "docs.pathExample.instruction": "cli-architecture (.gitifact/instructions/cli-architecture/index.md)",
25836
25902
  "docs.skeleton.feature": "(\uC774 \uAE30\uB2A5\uC774 \uBB34\uC5C7\uC774\uACE0 \uC5B4\uB514\uAE4C\uC9C0\uC778\uC9C0)",
25837
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)",
25838
25905
  "docs.skeleton.design": "(\uC774 \uC124\uACC4\uAC00 \uB2E4\uB8E8\uB294 \uAD6C\uC870\uC640 \uCC98\uB9AC \uBC29\uC2DD)",
25839
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)",
25840
25907
  "docs.exists": "\uC774\uBBF8 \uC788\uB294 \uD30C\uC77C\uC785\uB2C8\uB2E4: {path}",
@@ -25857,6 +25924,7 @@ var messages_default3 = {
25857
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.",
25858
25925
  "commit.unknownDocument": "\uACB0\uC815\uAE30\uB85D\uC774 \uAC00\uB9AC\uD0A4\uB294 \uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4: {ids}",
25859
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.",
25860
25928
  "changes.problems": "\uBB38\uC11C \uAC80\uC0AC: \uBB38\uC81C {count}\uAC1C (check\uB85C \uD655\uC778)",
25861
25929
  "changes.warnings": "\uBB38\uC11C \uACBD\uACE0: {count}\uAC1C (check\uB85C \uD655\uC778, \uCEE4\uBC0B\uC740 \uB9C9\uC9C0 \uC54A\uC74C)",
25862
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)",
@@ -25896,6 +25964,7 @@ var messages_default3 = {
25896
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)",
25897
25965
  "help.specsNewKind": "feature, requirement, design \uC911 \uD558\uB098",
25898
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",
25899
25968
  "help.newTitle": "\uBB38\uC11C \uC81C\uBAA9",
25900
25969
  "help.newDescription": "\uD55C \uC904 \uC124\uBA85",
25901
25970
  "help.instructions": "\uD504\uB85C\uC81D\uD2B8 \uC9C0\uCE68\uC758 \uBAA9\uB85D\xB7\uC6D0\uBB38\xB7\uC0DD\uC131",
@@ -26151,6 +26220,7 @@ var messages_default4 = {
26151
26220
  "docs.pathExample.instruction": "cli-architecture (.gitifact/instructions/cli-architecture/index.md)",
26152
26221
  "docs.skeleton.feature": "(What this feature is and where it ends)",
26153
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)",
26154
26224
  "docs.skeleton.design": "(The structure and processing this design covers)",
26155
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)",
26156
26226
  "docs.exists": "The file already exists: {path}",
@@ -26173,6 +26243,7 @@ var messages_default4 = {
26173
26243
  "commit.checkFailed": "The document check found {count} problems; nothing was committed.",
26174
26244
  "commit.unknownDocument": "A record names documents that do not exist: {ids}",
26175
26245
  "docs.singleLine": "The {field} must be a single line.",
26246
+ "docs.styleRequirementOnly": "--style applies only when creating a requirement.",
26176
26247
  "changes.problems": "Document check: {count} problems (see check)",
26177
26248
  "changes.warnings": "Document warnings: {count} (see check; they do not block a commit)",
26178
26249
  "changes.formatWarnings": "Format warnings: {count} (requirements changed here; they do not block a commit)",
@@ -26212,6 +26283,7 @@ var messages_default4 = {
26212
26283
  "help.specsNew": "Create a spec file with an issued ID, frontmatter and a body skeleton (marked draft: true)",
26213
26284
  "help.specsNewKind": "One of feature, requirement, design",
26214
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",
26215
26287
  "help.newTitle": "Document title",
26216
26288
  "help.newDescription": "One-line description",
26217
26289
  "help.instructions": "List, read and create project instructions",
@@ -26627,7 +26699,7 @@ function storeReader(cwd) {
26627
26699
  import { DatabaseSync } from "node:sqlite";
26628
26700
  import { lstat, mkdir, rm, writeFile } from "node:fs/promises";
26629
26701
  import { join as join2 } from "node:path";
26630
- var CACHE_FORMAT = 11;
26702
+ var CACHE_FORMAT = 12;
26631
26703
  var CACHE_DIR = ".gitifact/cache";
26632
26704
  var SCHEMA = `
26633
26705
  -- Working-tree files already read: the modification time and size decide whether a file is read again.
@@ -27075,7 +27147,7 @@ var recordKind = (path3) => {
27075
27147
  var folderOf = (path3) => path3.startsWith(SPEC_ROOT + "/") ? path3.split("/").slice(0, 3).join("/") : null;
27076
27148
  function snapshot3(doc, specId) {
27077
27149
  const base = { id: doc.id, kind: doc.kind, title: doc.title, description: doc.description, body: doc.body, specId, path: doc.path };
27078
- if (doc.kind === "requirement") return { ...base, order: doc.order };
27150
+ if (doc.kind === "requirement") return { ...base, order: doc.order, ...doc.style ? { style: doc.style } : {} };
27079
27151
  if (doc.kind === "design") return { ...base, order: doc.order, requirements: doc.requirements, sources: doc.sources };
27080
27152
  return base;
27081
27153
  }
@@ -27098,7 +27170,7 @@ function sideOf2(files) {
27098
27170
  }
27099
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 };
27100
27172
  }
27101
- 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);
27102
27174
  function compare(before, after) {
27103
27175
  const out = [];
27104
27176
  for (const id of [.../* @__PURE__ */ new Set([...before.docs.keys(), ...after.docs.keys()])].sort()) {
@@ -28209,7 +28281,7 @@ function checkoutDocuments(states, authors) {
28209
28281
  description: index.description,
28210
28282
  body: index.body,
28211
28283
  ...standing2(index.id),
28212
- 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) })),
28213
28285
  designs: designs.map((d) => ({
28214
28286
  id: d.id,
28215
28287
  path: d.path,
@@ -28445,7 +28517,7 @@ function snapshot4(doc, docs) {
28445
28517
  const folder = doc.path.split("/").slice(0, 3).join("/");
28446
28518
  const specId = doc.kind === "wiki" || doc.kind === "instruction" ? doc.kind : docs.find((d) => d.kind === "feature" && d.path === folder + "/index.md")?.id ?? "";
28447
28519
  const base = { id: doc.id, kind: doc.kind, title: doc.title, description: doc.description, body: doc.body, specId, path: doc.path };
28448
- if (doc.kind === "requirement") return { ...base, order: doc.order };
28520
+ if (doc.kind === "requirement") return { ...base, order: doc.order, ...doc.style ? { style: doc.style } : {} };
28449
28521
  if (doc.kind === "design") return { ...base, order: doc.order, requirements: doc.requirements, sources: doc.sources };
28450
28522
  return base;
28451
28523
  }
@@ -28654,7 +28726,7 @@ function recordRoutes(root, sessionId, env) {
28654
28726
  route({ method: "GET", path: "/api/v1/feature", session: true, query: browserFeatureQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
28655
28727
  const feature2 = featureOf(await checkout.base(), query.id);
28656
28728
  if (!feature2) throw new HttpError(404, "NOT_FOUND", t2("server.featureNotFound"));
28657
- return ok(browserFeatureV1.parse({ contract: "browser-feature", version: 1, sessionId, feature: feature2 }));
28729
+ return ok(browserFeatureV2.parse({ contract: "browser-feature", version: 2, sessionId, feature: feature2 }));
28658
28730
  } }),
28659
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() })) }),
28660
28732
  route({ method: "GET", path: "/api/v1/contributors", session: true, query: browserContributorsQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
@@ -28715,7 +28787,7 @@ function recordRoutes(root, sessionId, env) {
28715
28787
  route({ method: "GET", path: "/api/v1/commit/change", session: true, query: browserCommitChangeQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
28716
28788
  const change2 = await cache.history.commitChange(query.commit, query.id);
28717
28789
  if (!change2) throw new HttpError(404, "NOT_FOUND", t2("server.commitNotFound"));
28718
- return ok(browserCommitChangeV1.parse({ contract: "browser-commit-change", version: 1, sessionId, commit: query.commit, event: change2.event, before: change2.before, after: change2.after }));
28790
+ return ok(browserCommitChangeV2.parse({ contract: "browser-commit-change", version: 2, sessionId, commit: query.commit, event: change2.event, before: change2.before, after: change2.after }));
28719
28791
  } }),
28720
28792
  // A record's page names the record; which commit added it is read from the history of the HEAD the reader is on.
28721
28793
  route({ method: "GET", path: "/api/v1/record", session: true, query: browserRecordQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
@@ -28735,7 +28807,7 @@ function recordRoutes(root, sessionId, env) {
28735
28807
  route({ method: "GET", path: "/api/v1/working/change", session: true, query: browserWorkingChangeQueryV1, unreadable: unreadable2, handle: async ({ query }) => {
28736
28808
  const change2 = await workingChange2(working2, query.id);
28737
28809
  if (!change2) throw new HttpError(404, "NOT_FOUND", t2("server.workingChangeNotFound"));
28738
- return ok(browserWorkingChangeV1.parse({ contract: "browser-working-change", version: 1, sessionId, ...change2 }));
28810
+ return ok(browserWorkingChangeV2.parse({ contract: "browser-working-change", version: 2, sessionId, ...change2 }));
28739
28811
  } }),
28740
28812
  // The source a commit changed beside its documents, read from Git when the commit or record page asks for it.
28741
28813
  route({ method: "GET", path: "/api/v1/commit/files", session: true, query: browserCommitFilesQueryV2, unreadable: unreadable2, handle: async ({ query }) => {
@@ -29800,6 +29872,10 @@ async function createDocument(project, kind2, path3, options) {
29800
29872
  for (const [field, value] of [["title", options.title], ["description", options.description]]) {
29801
29873
  if (/[\r\n]/.test(value)) throw new CommandError("INVALID_VALUE", t2("docs.singleLine", { field }));
29802
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 } : {};
29803
29879
  const target = newPath(kind2, path3);
29804
29880
  const { documents } = await project.cache.documents.list();
29805
29881
  const taken = new Set(documents.map((d) => d.id));
@@ -29810,9 +29886,10 @@ async function createDocument(project, kind2, path3, options) {
29810
29886
  const folder = target.slice(0, target.lastIndexOf("/") + 1);
29811
29887
  const siblings = documents.filter((d) => (d.kind === "requirement" || d.kind === "design") && d.path.startsWith(folder) && !d.path.slice(folder.length).includes("/"));
29812
29888
  const order = Math.min(999999, Math.max(0, ...siblings.map((d) => d.order)) + 10);
29813
- const base = { id, path: target, title: options.title.trim(), description: options.description.trim(), body: skeleton[kind2](), draft: true };
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 };
29814
29891
  const feature2 = target.split("/")[2];
29815
- 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 };
29816
29893
  const rendered = renderDocumentFile(doc);
29817
29894
  parseDocumentFile(target, rendered);
29818
29895
  try {
@@ -29877,6 +29954,7 @@ function aside(format2, lines2) {
29877
29954
 
29878
29955
  // src/commands/specs.ts
29879
29956
  var specKinds = ["feature", "requirement", "design"];
29957
+ var specStyles = requirementStyles;
29880
29958
  var specSorts = ["order", "title", "updated"];
29881
29959
  var columns = ["id", "kind", "feature", "path", "title", "description", "order", "draft", "state", "previousPath", "requirements", "sources", "designs", "updated", "line"];
29882
29960
  var kindLabel = { feature: () => t2("docs.feature"), requirement: () => t2("docs.requirement"), design: () => t2("docs.design") };
@@ -30274,9 +30352,9 @@ var recordLine = (r, changes2) => {
30274
30352
  const changed = new Set(changes2.map((c) => c.id));
30275
30353
  return `${r.id} ${r.title}${r.draft ? " (" + t2("docs.draft") + ")" : ""} \u2014 ${r.docs.map((d) => changed.has(d) ? d : d + "*").join(", ")}`;
30276
30354
  };
30277
- var formatWarnings = (changes2, documents) => {
30355
+ var formatWarnings = (changes2, documents, project) => {
30278
30356
  const touched = new Set(changes2.map((c) => c.id));
30279
- return documents.filter((d) => touched.has(d.id)).flatMap(requirementFormatWarnings);
30357
+ return documents.filter((d) => touched.has(d.id)).flatMap((d) => requirementFormatWarnings(d, project.config.requirementStyle));
30280
30358
  };
30281
30359
  var recordSummary = (r) => ({ id: r.id, title: r.title, docs: r.docs, path: r.path, ...r.draft ? { draft: true } : {} });
30282
30360
  var runChangesList = (options, controls = {}) => runCommand("changes", options.format, async () => {
@@ -30288,7 +30366,7 @@ var runChangesList = (options, controls = {}) => runCommand("changes", options.f
30288
30366
  const withoutRecord = uncovered(changes2, records2);
30289
30367
  const sharedDocuments = shared(changes2, records2);
30290
30368
  const problems = [...working2.problems, ...pending.problems, ...checked.problems];
30291
- const formats2 = formatWarnings(changes2, checked.documents);
30369
+ const formats2 = formatWarnings(changes2, checked.documents, project);
30292
30370
  const warnings = [...await readDocumentWarnings(project.root, checked.documents), ...formats2];
30293
30371
  const inputs = await prepareAgentInputs(project.root, controls).catch(() => void 0);
30294
30372
  const out = changes2.length ? [t2("changes.changed", { count: changes2.length }), ...changes2.map((c) => " " + changeLine(c))] : [t2("changes.none")];
@@ -30370,7 +30448,7 @@ async function commitChanges(cwd, input2, dryRun) {
30370
30448
  const split = changes2.filter((c) => c.previousPath !== void 0 && !(selected2.includes(c.path) && selected2.includes(c.previousPath)));
30371
30449
  if (split.length) fail3(t2("commit.selectMove", { ids: split.map((c) => c.id).join(", ") }));
30372
30450
  const withoutRecord = uncovered(changes2, records2);
30373
- const warnings = formatWarnings(changes2, checked.documents);
30451
+ const warnings = formatWarnings(changes2, checked.documents, project);
30374
30452
  const status = (await git(["status", "--porcelain=v1", "-z", "--untracked-files=all", "--no-renames", "--", ".gitifact"])).toString("utf8").split("\0").filter(Boolean);
30375
30453
  const removed = new Set(status.filter((entry2) => entry2.slice(0, 2).includes("D")).map((entry2) => entry2.slice(3)));
30376
30454
  checkStoreSelection(selected2.filter((p) => !(underDocuments(p) && removed.has(p))));
@@ -31031,17 +31109,17 @@ for (let i = 0; i < languageArgs.length; i++) {
31031
31109
  if (value === "ko" || value === "en") selectedLanguage = value;
31032
31110
  }
31033
31111
  configureLanguage(selectedLanguage ?? environmentLanguage(), selectedLanguage);
31034
- var program2 = new Command().name("gitifact").addOption(new Option("--lang <language>", t2("help.lang")).choices(["ko", "en"])).description(t2("help.program")).version("0.8.5").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
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());
31035
31113
  program2.hook("preAction", async (_program, action) => {
31036
31114
  let top = action;
31037
31115
  while (top.parent && top.parent !== program2) top = top.parent;
31038
- if (top.name() !== REFRESH_COMMAND) await noticeVersion("0.8.5", top.name());
31116
+ if (top.name() !== REFRESH_COMMAND) await noticeVersion("0.8.6", top.name());
31039
31117
  });
31040
- program2.command(REFRESH_COMMAND, { hidden: true }).allowExcessArguments(false).action(() => refreshUpdateCache("0.8.5"));
31118
+ program2.command(REFRESH_COMMAND, { hidden: true }).allowExcessArguments(false).action(() => refreshUpdateCache("0.8.6"));
31041
31119
  var format = () => new Option("--format <format>", t2("help.format")).choices(formats).default("text");
31042
- 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.5"));
31043
- 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.5"));
31044
- 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.5") : options.check ? runUpdateCheck(options.format, "0.8.5") : runUpdate(options, "0.8.5"));
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"));
31045
31123
  var listed2 = (command, sorts) => {
31046
31124
  command.allowExcessArguments(false).option("--q <words>", t2("help.listQ")).option("--author <name>", t2("help.listAuthor"));
31047
31125
  if (sorts) command.addOption(new Option("--sort <key>", t2("help.listSort")).choices([...sorts]).default(sorts[0]));
@@ -31050,7 +31128,7 @@ var listed2 = (command, sorts) => {
31050
31128
  var specs = program2.command("specs").description(t2("help.specs"));
31051
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));
31052
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));
31053
- 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));
31054
31132
  var instructions = program2.command("instructions").description(t2("help.instructions"));
31055
31133
  listed2(instructions.command("list").description(t2("help.instructionsList")), instructionSorts).action((o) => runInstructionsList(o));
31056
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));
@@ -31063,7 +31141,7 @@ program2.command("check").description(t2("help.check")).allowExcessArguments(fal
31063
31141
  var changes = program2.command("changes").description(t2("help.changes"));
31064
31142
  changes.command("list").description(t2("help.changesList")).allowExcessArguments(false).addOption(format()).action((o) => runChangesList(o));
31065
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));
31066
- 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.5"));
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"));
31067
31145
  var guide = program2.command("guide").description(t2("help.guide"));
31068
31146
  guide.command("list").description(t2("help.guideList")).allowExcessArguments(false).addOption(format()).action((o) => runGuideList(o));
31069
31147
  guide.command("show").description(t2("help.guideShow")).argument("<topic>", t2("help.guideTopic")).allowExcessArguments(false).addOption(format()).action((topic, o) => runGuideShow(topic, o));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitifact",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "description": "Git-backed requirements and change history for coding agents.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{F as t,K as n,V as r,l as i,n as a,q as o}from"./themeProps-CkLe5zXY.js";import{bt as s,xt as c}from"./page-header-AS8jZ1ve.js";import{x as l}from"./Table-DjTkmoR7.js";import{a as u}from"./useMediaQuery-twbHF0pO.js";import{E as d,J as f,S as ee,W as p,_ as te,t as m}from"./Icon-DPaLmsmh.js";import{a as h,r as ne}from"./IconButton-Br-4XhQr.js";import{t as g}from"./useDevWarning-Dudfg3qF.js";import{t as _}from"./useKeyboardHint-D5jGavym.js";var v=e(o(),1);function y(){let e=(0,v.useRef)(null),t=(0,v.useRef)(null),[n,r]=(0,v.useState)({overflowStart:!1,overflowEnd:!1,hasOverflow:!1}),i=(0,v.useCallback)(()=>{let t=e.current;if(!t)return;let{scrollLeft:n,scrollWidth:i,clientWidth:a}=t,o=i-a,s=Math.abs(n)>1,c=Math.abs(n)<o-1,l=i>a+1;r(e=>e.overflowStart===s&&e.overflowEnd===c&&e.hasOverflow===l?e:{overflowStart:s,overflowEnd:c,hasOverflow:l})},[]),a=(0,v.useCallback)(n=>{e.current&&(t.current?.(),t.current=null,e.current.removeEventListener(`scroll`,i)),e.current=n,n&&(n.addEventListener(`scroll`,i,{passive:!0}),t.current=f(n,i))},[i]);return(0,v.useEffect)(()=>()=>{e.current&&(t.current?.(),t.current=null,e.current.removeEventListener(`scroll`,i))},[i]),{scrollRef:a,...n}}var b=(0,v.createContext)(null);b.displayName=`TabListContext`;function x(){let e=(0,v.use)(b);if(e==null)throw Error(`useTabListContext must be used within TabList. Wrap your Tab/TabMenu in <TabList>.`);return e}var S=i(),C=`[data-tab-value],[data-tab-menu]`;function w(e){e.preventDefault()}var re=.8;`${t[`--focus-outline-width`]}${t[`--focus-outline-offset`]}`;var T=`var(--_tab-strip-bleed)`,E=r[`--spacing-3`];`${E}`,`${E}`,`${T}`;var D=`calc(${T} + ${r[`--spacing-8`]})`;`${T}${D}`,`${T}${D}`;var O={nav:{k1xSpc:`x78zum5`,kGNEyG:`x1qjc9v5`,kOIVth:`x1lsbc85`,ks0D6T:`x193iq5w`,k7Eaqz:`xeuugli`,kVAEAm:`x1n2onr6`,$$css:!0},fill:{kzqmXN:`xh8yej3`,$$css:!0},divider:{kt9PQ7:`x92x3c3`,kfdmCh:`x1q0q8m5`,kL6WhQ:`xw8gpjh`,kGO01o:`xy143xn`,"--_tab-indicator-bottom":`xficto1`,$$css:!0},strip:{k1xSpc:`x78zum5`,kGNEyG:`x1qjc9v5`,kOIVth:`x14kbac9`,kzQI83:`x1iyjqo2`,kmuXW:`xs83m0k`,k7Eaqz:`xeuugli`,kSGwAc:`xqcrz7y`,$$css:!0},stripScroll:{kXHlph:`xw2csxc`,kORKVm:`x10wlt62`,kvh3hx:`x7p5m3t`,katHQp:`x1xif8ns`,k5wCbM:`x1rohswg`,khEr5k:`xkcv6ua xg83hb1`,"--_tab-strip-bleed":`x78b515 x158n88w`,kLKAdn:`xlr2r7p`,keoZOQ:`xmqyaqf`,kGO01o:`xwhchk8`,k1K539:`xlgak1e`,kg3NbH:`x1kpkw9v`,kUOVxO:`xi5l473`,kX1K2I:`xw4ya9i`,k1ekBW:`x157bb6t`,kIyJzY:`x80gvsz x12w9bfk`,kAMwcw:`xlr8y92`,$$css:!0},fullBleedStrip:{kZCmMZ:`xwb75os`,kwRFfy:`xtvv6yu`,$$css:!0},fadeStart:{kX1K2I:`x1hua2o0 x1nwey30`,$$css:!0},fadeEnd:{kX1K2I:`xoj6v2h x1rxa4r8`,$$css:!0},fadeBoth:{kX1K2I:`xq05pg6`,$$css:!0},arrow:{kVAEAm:`x10l6tqk`,k87sOh:`x13vifvy`,k1xSpc:`x1s85apg xqwu39o`,kGNEyG:`x6s0dn4`,kjj79g:`xl56j7k`,kmVPX3:`x1717udv`,kMzoRj:`xc342km`,ksu8eU:`xng3xce`,kaIpWk:`xjspbzw`,kWkggS:`x1prclbq`,kGVxlE:`x1i5ehqx`,kMwMTN:`xv1l7n4 x9o1np9`,kkrTdU:`x1ypdohk x16khyan`,$$css:!0},arrowStart:{kLqNvP:`x1o0tod`,$$css:!0},arrowEnd:{kt4wiu:`xtijo5x`,$$css:!0},fullBleed:{keTefX:`xojxgvx`,k71WvV:`x1fcf3bl`,ks0D6T:`x1x1rfll`,kzqmXN:`xx6qvi6`,$$css:!0}},k={sm:{kzqmXN:`x1fvqzum`,kZKoxP:`x6k0iem`,$$css:!0},md:{kzqmXN:`x805d0l`,kZKoxP:`x1ueg155`,$$css:!0},lg:{kzqmXN:`x1m747yf`,kZKoxP:`xssyfek`,$$css:!0}};function A({ref:e,value:t,onChange:r,size:i,layout:o=`hug`,hasDivider:ne=!1,isFullBleed:g=!1,role:x,overflow:T=`auto`,xstyle:E,className:D,style:A,children:j,onKeyDown:M,onFocus:N,onBlur:P,"aria-label":ie,"aria-labelledby":F,"aria-orientation":I,[h]:ae,...L}){let R=te(),z=ie??R(`@astryx.tabList.label`),B=ee(i,`md`),V=T!==`visible`,H=(0,v.useRef)(null),U=x===`tablist`,{listRef:W,handleKeyDown:G,handleFocus:K}=s({itemSelector:C,orientation:U?`horizontal`:`both`,hasRovingTabIndex:!0}),{hintElement:oe,onKeyDown:q,onFocus:se,onBlur:ce}=_(),{scrollRef:le,overflowStart:J,overflowEnd:Y}=y(),ue=(0,v.useCallback)(e=>{H.current=e,le(V?e:null)},[V,le]),X=(0,v.useCallback)(e=>{let t=H.current;if(!V||!t||!e)return;let n=t.getBoundingClientRect(),r=e.getBoundingClientRect(),i=parseFloat(getComputedStyle(t).scrollPaddingLeft)||0,a=r.right-(n.right-i),o=r.left-(n.left+i),s=r.width>n.width-2*i?c(t)?a:o:a>0?a:o<0?o:0;s!==0&&t.scrollBy({left:s,behavior:`instant`})},[V]),Z=(0,v.useCallback)(()=>{let e=H.current;e&&X(Array.from(e.querySelectorAll(`[data-tab-value]`)).find(e=>e.dataset.tabValue===t)??null)},[X,t]),Q=(0,v.useRef)(Z);(0,v.useEffect)(()=>{Q.current=Z},[Z]);let de=(0,v.useRef)(null);(0,v.useEffect)(()=>{de.current!==t&&(de.current=t,Q.current())},[t]),(0,v.useEffect)(()=>{let e=W.current;return!V||!e?void 0:f(e,()=>Q.current())},[V,W]);let $=(0,v.useCallback)(e=>{let t=H.current;if(!t)return;let n=c(t)?-1:1;t.scrollBy({left:n*e*t.clientWidth*re})},[]),fe=(0,v.useCallback)(()=>$(-1),[$]),pe=(0,v.useCallback)(()=>$(1),[$]),me=(0,v.useMemo)(()=>({value:t,onChange:r,size:B,layout:o,pattern:U?`tabs`:`nav`}),[t,r,B,o,U]),he=(0,v.useCallback)(e=>{M?.(e),!e.defaultPrevented&&(q(e),G(e))},[M,q,G]),ge=(0,v.useCallback)(e=>{N?.(e),!e.defaultPrevented&&(se(e),K(e),X(e.target.closest(C)))},[N,se,K,X]),_e=(0,v.useCallback)(e=>{P?.(e),!e.defaultPrevented&&ce(e)},[P,ce]);(0,v.useRef)(!1),(0,v.useEffect)(()=>{H.current});let ve=V?J&&Y?O.fadeBoth:J?O.fadeStart:Y?O.fadeEnd:null:null;return(0,S.jsx)(b,{value:me,children:(0,S.jsxs)(U?`div`:`nav`,{ref:d(e,W),...L,role:U?void 0:x,"aria-label":U?void 0:z,"aria-labelledby":U?void 0:F,onKeyDown:he,onFocus:ge,onBlur:_e,[h]:``,...u(a(`tab-list`,{size:B}),n(O.nav,o===`fill`&&O.fill,ne&&O.divider,g&&O.fullBleed,E),D,A),children:[(0,S.jsx)(`div`,{ref:ue,role:U?`tablist`:void 0,"aria-label":U?z:void 0,"aria-labelledby":U?F:void 0,...u(a(`tab-strip`),n(O.strip,V&&O.stripScroll,g&&O.fullBleedStrip,ve)),children:j}),V&&J&&(0,S.jsx)(`button`,{type:`button`,"aria-hidden":`true`,tabIndex:-1,onMouseDown:w,onClick:fe,...u(a(`tab-scroll-button`),p.focusVisible(O.arrow,O.arrowStart,k[B])),children:(0,S.jsx)(m,{icon:`chevronLeft`,size:`sm`,color:`inherit`,xstyle:l.mirror})}),V&&Y&&(0,S.jsx)(`button`,{type:`button`,"aria-hidden":`true`,tabIndex:-1,onMouseDown:w,onClick:pe,...u(a(`tab-scroll-button`),p.focusVisible(O.arrow,O.arrowEnd,k[B])),children:(0,S.jsx)(m,{icon:`chevronRight`,size:`sm`,color:`inherit`,xstyle:l.mirror})}),oe]})})}A.displayName=`TabList`;var j={x1u3b27q:`x1u3b27q`,$$css:!0},M={base:{kVAEAm:`x1n2onr6`,k1xSpc:`x3nfvp2`,kGNEyG:`x6s0dn4`,kjj79g:`xl56j7k`,kOIVth:`xzye2dw`,kg3NbH:`xrrkdod`,kWkggS:`xjbqb8w`,kMzoRj:`xc342km`,ksu8eU:`xng3xce`,kaIpWk:`xh6dtrn`,kMv6JI:`xjb2p0i`,kGuDYH:`xcr08ib`,kLWn49:`x1kq96og`,k63SB2:`x1sodnla`,kMwMTN:`xv1l7n4`,kkrTdU:`x1ypdohk x16khyan`,kybGjl:`x1hl2dhg`,khDVqt:`xuxw1ft`,k1ekBW:`xt3l3uh`,kIyJzY:`xuedmi6`,kAMwcw:`xlr8y92`,$$css:!0},hoverBg:{kVAEAm:`x10l6tqk`,kpwlN0:`x10a8y8t`,kogj98:`x1bpp3o7`,kzqmXN:`xh8yej3`,kaIpWk:`xh6dtrn`,kfzvcC:`x47corl`,kWkggS:`xjbqb8w x1a1zr74`,k1ekBW:`x15406qy`,kIyJzY:`xuedmi6`,kAMwcw:`xlr8y92`,$$css:!0},selected:{kMwMTN:`x1tgivj0`,k63SB2:`x2mo6ok`,$$css:!0},icon:{k1xSpc:`x3nfvp2`,kGNEyG:`x6s0dn4`,kjj79g:`xl56j7k`,kmuXW:`x2lah0s`,$$css:!0}},N={sm:{kZKoxP:`x6k0iem`,$$css:!0},md:{kZKoxP:`x1ueg155`,$$css:!0},lg:{kZKoxP:`xssyfek`,$$css:!0}},P={sm:{kZKoxP:`x6k0iem`,$$css:!0},md:{kZKoxP:`x1ueg155`,$$css:!0},lg:{kZKoxP:`xssyfek`,$$css:!0}},ie={fill:{kUk6DE:`x98rzlu`,kjj79g:`xl56j7k`,$$css:!0}},F={sm:{kzqmXN:`x6jxa94`,kZKoxP:`x1v9usgg`,$$css:!0},md:{kzqmXN:`x1kky2od`,kZKoxP:`xlup9mm`,$$css:!0},lg:{kzqmXN:`x1xp8n7a`,kZKoxP:`xmix8c7`,$$css:!0}};function I({as:e,ref:t,value:r,label:i,isLabelHidden:o=!1,href:s,panelId:c,icon:l,selectedIcon:d,endContent:f,xstyle:ee,className:te,style:m,..._}){let y=x(),b=ne(e),C=y.value===r,w=y.size,re=y.layout===`fill`,T=y.pattern===`tabs`,E=s!=null&&!T,D=T&&!E,O=C&&d?d:l,k=!o&&i!==``,A=(0,v.useCallback)(()=>{y.onChange(r)},[y,r]);g(`Tab`,`href is ignored in a role="tablist" TabList — a tab swaps a panel in place rather than navigating. Drop the href, or drop the role for the navigation pattern.`,D&&s!=null);let I=c??_[`aria-controls`];g(`Tab`,`a tab in a role="tablist" TabList controls nothing: pass panelId with the id of the panel it opens, so assistive technology can associate the two.`,D&&I==null),g(`Tab`,`panelId does nothing outside a role="tablist" TabList — the navigation pattern has no panel to associate. Give the TabList role="tablist", or drop the panelId.`,!T&&c!=null);let ae=O?(0,S.jsx)(`span`,{...n(M.icon,F[w]),children:O}):null,L={..._,...o?{"aria-label":i}:{},[h]:``,"data-tab-value":r,...D?{role:`tab`,"aria-selected":C,"aria-controls":I}:{"aria-current":C?`true`:void 0},tabIndex:C?0:-1,...u(a(`tab`,{selected:C?`selected`:null}),p.focusVisible(M.base,N[w],C&&M.selected,re&&ie.fill,j,ee),te,m)},R=(0,S.jsx)(`span`,{"aria-hidden":`true`,...n(M.hoverBg,P[w])}),z=(0,S.jsx)(`span`,{...u(a(`tab-indicator`,{selected:C?`selected`:null}),{0:{className:`x10l6tqk xyi47jn x1ybfrjj x1mcfs9z x36qwtl xjspbzw x47corl xnpjden xuedmi6 xlr8y92 xjbqb8w xg01cxk`},1:{className:`x10l6tqk xyi47jn x1ybfrjj x1mcfs9z x36qwtl xjspbzw x47corl xnpjden xuedmi6 xlr8y92 x1ewilqj x1hc1fzr`}}[!!C<<0])}),B=k?(0,S.jsxs)(`span`,{className:`xwz0xwf`,children:[(0,S.jsx)(`span`,{className:`x1agbcgv xcrlgei`,children:i}),(0,S.jsx)(`span`,{"aria-hidden":`true`,className:`x1agbcgv xcrlgei xlshs6z x47corl x2mo6ok`,children:i})]}):null,V=f?(0,S.jsx)(`span`,{className:`x3nfvp2 x6s0dn4 x2lah0s`,children:f}):null;return E?(0,S.jsxs)(b,{ref:t,href:s,onClick:A,...L,children:[R,ae,B,V,z]}):(0,S.jsxs)(`button`,{ref:t,type:`button`,onClick:A,...L,children:[R,ae,B,V,z]})}I.displayName=`Tab`;export{A as n,I as t};
@@ -1 +0,0 @@
1
- import{h as e}from"./index-IML0_BCy.js";var t=e;export{t as component};