gitifact 0.3.1 → 0.4.0
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 +9 -4
- package/dist/browser/assets/Markdown-BG_9T3yA.js +68 -0
- package/dist/browser/assets/MetadataListItem-BJjmYUP-.js +1 -0
- package/dist/browser/assets/about-C5lrF_v9.js +3 -0
- package/dist/browser/assets/about-Df__2EC8.css +1 -0
- package/dist/browser/assets/changelog-CxmMo2wk.css +1 -0
- package/dist/browser/assets/changelog-hNvOtw70.js +2 -0
- package/dist/browser/assets/{contributors._email-BedFTFKd.js → contributors._email-CwG6z4oO.js} +1 -1
- package/dist/browser/assets/{contributors.index-Bnzf41H5.js → contributors.index-B9l1YPjl.js} +1 -1
- package/dist/browser/assets/{features._featureId-DcMHCk6D.js → features._featureId-uB5QcPIl.js} +1 -1
- package/dist/browser/assets/{requirements-Dwwz8esQ.js → features.index-DzLFYkRG.js} +1 -1
- package/dist/browser/assets/git-DJKAcbnl.js +1 -0
- package/dist/browser/assets/gitifact-logo-DPewkDQ4.svg +5 -0
- package/dist/browser/assets/{guides._documentId-DCT-3idQ.js → guides._documentId-DHM6effA.js} +1 -1
- package/dist/browser/assets/{guides.index-D1kTKyw-.js → guides.index-BfJqdqJd.js} +1 -1
- package/dist/browser/assets/index-jaVGAf81.js +56 -0
- package/dist/browser/assets/{page-header-BL8BYIMW.js → page-header-DI5eoQC1.js} +75 -5
- package/dist/browser/assets/product-YuwMeOC0.js +8 -0
- package/dist/browser/assets/{product.index-DByH6f_H.js → product.index-RgfLdFqG.js} +1 -1
- package/dist/browser/assets/request-state-DpUKcy6G.js +1 -0
- package/dist/browser/assets/{features.index-De9qZC-A.js → requirements-BMLc9Fpl.js} +1 -1
- package/dist/browser/assets/{routes-3pD4uVSj.js → routes-XUldGkLf.js} +1 -1
- package/dist/browser/index.html +6 -5
- package/dist/i18n/ko/block.md +31 -0
- package/dist/i18n/ko/changelog.md +53 -0
- package/dist/{docs → i18n/ko/docs}/workflow.md +1 -1
- package/dist/main.js +1142 -551
- package/package.json +3 -3
- package/dist/browser/assets/Markdown-Br4lZgRm.js +0 -68
- package/dist/browser/assets/about-BEuntqm_.js +0 -52
- package/dist/browser/assets/about-yX6os7bt.css +0 -1
- package/dist/browser/assets/git-D7ZvYMaq.js +0 -1
- package/dist/browser/assets/index-Dv_ANS5w.js +0 -56
- package/dist/browser/assets/product-mRpyGR_g.js +0 -8
- package/dist/browser/assets/request-state-CcdtplxL.js +0 -1
- /package/dist/{docs → i18n/ko/docs}/commit.md +0 -0
- /package/dist/{docs → i18n/ko/docs}/design.md +0 -0
- /package/dist/{docs → i18n/ko/docs}/product.md +0 -0
- /package/dist/{docs → i18n/ko/docs}/spec.md +0 -0
package/dist/main.js
CHANGED
|
@@ -488,9 +488,9 @@ var Help = class {
|
|
|
488
488
|
* @param {Help} helper
|
|
489
489
|
* @returns string[]
|
|
490
490
|
*/
|
|
491
|
-
formatItemList(heading,
|
|
492
|
-
if (
|
|
493
|
-
return [helper.styleTitle(heading), ...
|
|
491
|
+
formatItemList(heading, items2, helper) {
|
|
492
|
+
if (items2.length === 0) return [];
|
|
493
|
+
return [helper.styleTitle(heading), ...items2, ""];
|
|
494
494
|
}
|
|
495
495
|
/**
|
|
496
496
|
* Group items by their help group heading.
|
|
@@ -3398,23 +3398,129 @@ function summarizeChanges(changes) {
|
|
|
3398
3398
|
return result;
|
|
3399
3399
|
}
|
|
3400
3400
|
|
|
3401
|
-
// ../../packages/core/dist/
|
|
3402
|
-
var
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3401
|
+
// ../../packages/core/dist/shared/i18n/ko/messages.json
|
|
3402
|
+
var messages_default = {
|
|
3403
|
+
"config.jsonUnreadable": "\uC124\uC815 JSON\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC6D0\uBB38\uC744 \uBCF4\uC874\uD558\uC138\uC694.",
|
|
3404
|
+
"config.unsupportedFormat": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD504\uB85C\uC81D\uD2B8 \uD615\uC2DD\uC785\uB2C8\uB2E4. \uD638\uD658 CLI\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
3405
|
+
"config.invalidFields": "\uD504\uB85C\uC81D\uD2B8 \uC124\uC815\uC758 \uD544\uB4DC\uB098 \uAC12\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
3406
|
+
"config.jsonUnreadableShort": "\uC124\uC815 JSON\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
3407
|
+
"config.schemaFields": "schemaVersion\uACFC baseline \uC124\uC815 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
3408
|
+
"document.pathTooLong": "\uBB38\uC11C \uACBD\uB85C \uAE4A\uC774 \uB610\uB294 \uAE38\uC774 \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4: {path}",
|
|
3409
|
+
"document.fileName": "\uBB38\uC11C \uD30C\uC77C \uC774\uB984\uC740 \uC18C\uBB38\uC790\xB7\uC22B\uC790\xB7\uD558\uC774\uD508\uACFC .md\uC5EC\uC57C \uD569\uB2C8\uB2E4: {path}",
|
|
3410
|
+
"document.folderName": "\uBB38\uC11C \uD3F4\uB354 \uC774\uB984\uC740 \uC18C\uBB38\uC790\xB7\uC22B\uC790\xB7\uD558\uC774\uD508\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: {path}",
|
|
3411
|
+
"design.invalidCharacters": "\uC798\uBABB\uB41C \uC124\uACC4 \uBB38\uC790\uC785\uB2C8\uB2E4.",
|
|
3412
|
+
"design.idMismatch": "\uC124\uACC4\uC758 gitifact-design ID\uB294 \uAC19\uC740 \uAE30\uB2A5\uC758 S-ID\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
3413
|
+
"design.titleRequired": "\uC124\uACC4 \uC81C\uBAA9\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
3414
|
+
"design.bodyRequired": "\uC124\uACC4 \uBCF8\uBB38\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
3415
|
+
"design.singleTopHeading": "\uC124\uACC4 \uCD5C\uC0C1\uC704 \uC81C\uBAA9\uC740 \uD558\uB098\uB9CC \uC501\uB2C8\uB2E4.",
|
|
3416
|
+
"design.referenceFormat": "\uC124\uACC4\uC758 \uCC38\uC870 \uC8FC\uC11D \uD615\uC2DD\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
3417
|
+
"design.unclosedFence": "\uC124\uACC4 \uCF54\uB4DC \uBE14\uB85D\uC774 \uB2EB\uD788\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.",
|
|
3418
|
+
"document.unsupportedPath": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uBB38\uC11C \uACBD\uB85C: {path}",
|
|
3419
|
+
"document.productOnly": "\uC81C\uD488 \uD3F4\uB354\uC5D0\uB294 PRODUCT.md \uD558\uB098\uB9CC \uB461\uB2C8\uB2E4: {path}",
|
|
3420
|
+
"document.invalidCharacters": "\uC798\uBABB\uB41C \uBB38\uC11C \uBB38\uC790: {path}",
|
|
3421
|
+
"document.idRequired": "\uCCAB \uC904\uC5D0 \uC720\uD6A8\uD55C gitifact-{kind} \uC8FC\uC11D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4: {path}",
|
|
3422
|
+
"document.titleRequired": "\uBB38\uC11C \uC81C\uBAA9\uC774 \uD544\uC694\uD569\uB2C8\uB2E4: {path}",
|
|
3423
|
+
"document.bodyRequired": "\uBB38\uC11C \uBCF8\uBB38\uC774 \uD544\uC694\uD569\uB2C8\uB2E4: {path}",
|
|
3424
|
+
"document.singleTopHeading": "\uBB38\uC11C \uCD5C\uC0C1\uC704 \uC81C\uBAA9\uC740 \uD558\uB098\uB9CC \uC501\uB2C8\uB2E4: {path}",
|
|
3425
|
+
"document.noMarkerInBody": "\uBB38\uC11C \uBCF8\uBB38\uC5D0\uB294 gitifact \uC8FC\uC11D\uC744 \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: {path}",
|
|
3426
|
+
"document.unclosedFence": "\uBB38\uC11C \uCF54\uB4DC \uBE14\uB85D\uC774 \uB2EB\uD788\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4: {path}",
|
|
3427
|
+
"document.kindSet": "\uBB38\uC11C \uC885\uB958 \uC9D1\uD569\uC774 \uC798\uBABB\uB410\uC2B5\uB2C8\uB2E4.",
|
|
3428
|
+
"document.kindMismatch": "\uBB38\uC11C \uC885\uB958\uAC00 \uD3F4\uB354\uC640 \uB2E4\uB985\uB2C8\uB2E4: {path}",
|
|
3429
|
+
"document.duplicateId": "\uC800\uC7A5\uC18C \uB0B4 \uC911\uBCF5 \uBB38\uC11C ID: {id}",
|
|
3430
|
+
"document.caseOnlyPath": "\uB300\uC18C\uBB38\uC790\uB9CC \uB2E4\uB978 \uBB38\uC11C \uACBD\uB85C: {path}",
|
|
3431
|
+
"history.duplicateId": "\uC800\uC7A5\uC18C \uB0B4 \uC911\uBCF5 \uBCF4\uC870 \uAE30\uB85D ID: {id}",
|
|
3432
|
+
"spec.orphanFile": "\uC694\uAD6C\uC0AC\uD56D \uBB38\uC11C \uC5C6\uB294 \uC124\uACC4 \uB610\uB294 \uC774\uC720 \uD30C\uC77C: {path}",
|
|
3433
|
+
"spec.unsupportedPath": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uBA85\uC138 \uACBD\uB85C: {path}",
|
|
3434
|
+
"spec.invalidCharacters": "\uC798\uBABB\uB41C \uBA85\uC138 \uBB38\uC790: {path}",
|
|
3435
|
+
"spec.idRequired": "\uCCAB \uC904\uC5D0 \uC720\uD6A8\uD55C gitifact-spec \uC8FC\uC11D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4: {path}",
|
|
3436
|
+
"spec.requirementIdRequired": "\uC694\uAD6C\uC0AC\uD56D \uC81C\uBAA9 \uBC14\uB85C \uC544\uB798\uC5D0 \uC720\uD6A8\uD55C ID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4: {path}",
|
|
3437
|
+
"spec.invalidFence": "\uC798\uBABB\uB41C \uCF54\uB4DC \uBE14\uB85D\uC785\uB2C8\uB2E4.",
|
|
3438
|
+
"spec.titleOnce": "\uBB38\uC11C \uC81C\uBAA9\uC740 \uCC98\uC74C\uC5D0 \uD55C \uBC88\uB9CC \uC501\uB2C8\uB2E4: {path}",
|
|
3439
|
+
"spec.emptyTitle": "\uBE48 \uBB38\uC11C \uC81C\uBAA9\uC785\uB2C8\uB2E4.",
|
|
3440
|
+
"spec.titleMissing": "\uBB38\uC11C \uC81C\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4: {path}",
|
|
3441
|
+
"spec.emptyRequirementTitle": "\uBE48 \uC694\uAD6C\uC0AC\uD56D \uC81C\uBAA9\uC785\uB2C8\uB2E4.",
|
|
3442
|
+
"spec.commentPosition": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 HTML \uC8FC\uC11D \uC704\uCE58: {path}",
|
|
3443
|
+
"spec.atxOnly": "\uAC80\uD1A0 \uBB38\uBC95\uC740 \uC5F4 1\uC758 ATX \uC81C\uBAA9\uB9CC \uC9C0\uC6D0\uD569\uB2C8\uB2E4: {path}",
|
|
3444
|
+
"spec.incomplete": "\uBBF8\uC644\uC131 \uBA85\uC138\uC785\uB2C8\uB2E4: {path}",
|
|
3445
|
+
"spec.emptyOrDuplicateRequirement": "\uBE48 \uBCF8\uBB38 \uB610\uB294 \uC911\uBCF5 \uC694\uAD6C\uC0AC\uD56D ID: {id}",
|
|
3446
|
+
"history.invalidJsonl": "\uBCF4\uC870 \uAE30\uB85D JSONL\uC744 \uD574\uC11D\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
3447
|
+
"history.invalidRecord": "\uC798\uBABB\uB41C \uBCF4\uC870 \uAE30\uB85D\uC785\uB2C8\uB2E4.",
|
|
3448
|
+
"history.invalidFields": "\uBCF4\uC870 \uAE30\uB85D\uC758 \uD544\uB4DC\xB7ID\xB7\uB300\uC0C1\uC774 \uC798\uBABB\uB410\uC2B5\uB2C8\uB2E4.",
|
|
3449
|
+
"spec.duplicateId": "\uC911\uBCF5 \uBA85\uC138 ID: {id}",
|
|
3450
|
+
"spec.duplicateRequirementId": "\uC800\uC7A5\uC18C \uB0B4 \uC911\uBCF5 \uC694\uAD6C\uC0AC\uD56D ID: {id}",
|
|
3451
|
+
"history.changed": "\uAE30\uC874 \uBCF4\uC870 \uAE30\uB85D\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4: {id}",
|
|
3452
|
+
"history.unlinkedRequirement": "\uC0C8 \uBCF4\uC870 \uAE30\uB85D\uC774 \uC774\uBC88 \uC694\uAD6C\uC0AC\uD56D \uBCC0\uACBD\uACFC \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: {id}",
|
|
3453
|
+
"history.unlinkedDocument": "\uC0C8 \uBCF4\uC870 \uAE30\uB85D\uC774 \uC774\uBC88 \uBB38\uC11C \uBCC0\uACBD\uACFC \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: {id}",
|
|
3454
|
+
"edit.invalidFeatureName": "\uC798\uBABB\uB41C \uAE30\uB2A5 \uD3F4\uB354 \uC774\uB984\uC785\uB2C8\uB2E4.",
|
|
3455
|
+
"edit.operationCount": "operations\uB294 1~100\uAC1C\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
3456
|
+
"edit.idGenerated": "ID \uC0DD\uC131 \uACB0\uACFC\uAC00 \uC798\uBABB\uB410\uC2B5\uB2C8\uB2E4.",
|
|
3457
|
+
"edit.idUnavailable": "\uACE0\uC720 ID\uB97C \uBC1C\uAE09\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
3458
|
+
"edit.invalidOperation": "\uC798\uBABB\uB41C \uD3B8\uC9D1 \uC785\uB825\uC785\uB2C8\uB2E4.",
|
|
3459
|
+
"edit.unsupportedField": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD3B8\uC9D1 \uD544\uB4DC\uC785\uB2C8\uB2E4.",
|
|
3460
|
+
"edit.emptyField": "\uBE48 \uD3B8\uC9D1 \uD544\uB4DC: {field}",
|
|
3461
|
+
"edit.invalidCharacters": "\uC798\uBABB\uB41C \uD3B8\uC9D1 \uBB38\uC790: {field}",
|
|
3462
|
+
"edit.specNotFound": "\uB300\uC0C1 \uBA85\uC138\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4: {path}",
|
|
3463
|
+
"edit.noProductToDelete": "\uC0AD\uC81C\uD560 \uC81C\uD488 \uBB38\uC11C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
3464
|
+
"edit.samePath": "\uC774\uBBF8 \uAC19\uC740 \uACBD\uB85C\uC785\uB2C8\uB2E4.",
|
|
3465
|
+
"edit.documentPathExists": "\uC774\uBBF8 \uC874\uC7AC\uD558\uB294 \uBB38\uC11C \uACBD\uB85C\uC785\uB2C8\uB2E4: {path}",
|
|
3466
|
+
"edit.guideIdNotFound": "\uC9C0\uCE68 \uBB38\uC11C ID\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4: {id}",
|
|
3467
|
+
"edit.featureExists": "\uC774\uBBF8 \uC874\uC7AC\uD558\uB294 \uAE30\uB2A5\uC785\uB2C8\uB2E4.",
|
|
3468
|
+
"edit.noDesignToDelete": "\uC0AD\uC81C\uD560 \uC124\uACC4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
3469
|
+
"edit.specIdNotFound": "\uBA85\uC138 ID\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
3470
|
+
"edit.requirementIdNotFound": "\uC694\uAD6C\uC0AC\uD56D ID\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
3471
|
+
"edit.sameSpec": "\uC774\uBBF8 \uAC19\uC740 \uBA85\uC138\uC5D0 \uC18D\uD569\uB2C8\uB2E4.",
|
|
3472
|
+
"edit.bodyChangesSpecStructure": "\uBCF8\uBB38\uC774 \uBA85\uC138 \uAD6C\uC870\uB97C \uBCC0\uACBD\uD569\uB2C8\uB2E4.",
|
|
3473
|
+
"edit.bodyChangesDocumentStructure": "\uBCF8\uBB38\uC774 \uBB38\uC11C \uAD6C\uC870\uB97C \uBCC0\uACBD\uD569\uB2C8\uB2E4: {path}",
|
|
3474
|
+
"reason.keepEmptySpec": "\uAE30\uC874 \uC774\uC720\uB97C \uBCF4\uC874\uD560 \uBE48 \uBA85\uC138\uB97C \uB0A8\uACA8\uC8FC\uC138\uC694: {id}",
|
|
3475
|
+
"reason.committedImmutable": "\uCEE4\uBC0B\uB41C \uC774\uC720\uC758 \uC218\uC815\xB7\uC0AD\uC81C\xB7\uC7AC\uBC30\uCE58\uB294 \uD5C8\uC6A9\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: {id}",
|
|
3476
|
+
"reason.committedDocumentImmutable": "\uCEE4\uBC0B\uB41C \uBB38\uC11C \uC774\uC720\uC758 \uC218\uC815\xB7\uC0AD\uC81C\xB7\uC7AC\uBC30\uCE58\uB294 \uD5C8\uC6A9\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: {kind}",
|
|
3477
|
+
"reason.count": "reasons\uB294 \uCD5C\uB300 100\uAC1C\uC758 \uBC30\uC5F4\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
3478
|
+
"reason.idGenerated": "\uC798\uBABB\uB41C \uC774\uC720 ID \uC0DD\uC131 \uACB0\uACFC\uC785\uB2C8\uB2E4.",
|
|
3479
|
+
"reason.idUnavailable": "\uACE0\uC720 \uC774\uC720 ID\uB97C \uBC1C\uAE09\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
3480
|
+
"reason.invalidInput": "\uC798\uBABB\uB41C \uC774\uC720 \uC785\uB825\uC785\uB2C8\uB2E4.",
|
|
3481
|
+
"reason.targetsRequired": "\uC774\uC720\uC640 \uB300\uC0C1 \uC694\uAD6C\uC0AC\uD56D\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
3482
|
+
"reason.documentWithRequirements": "\uBB38\uC11C \uC774\uC720\uC5D0\uB294 \uC694\uAD6C\uC0AC\uD56D\uC744 \uD568\uAED8 \uC9C0\uC815\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
3483
|
+
"reason.documentTargetInvalid": "\uBB38\uC11C \uC774\uC720 \uB300\uC0C1\uC774 \uC798\uBABB\uB410\uAC70\uB098 \uC911\uBCF5\uB429\uB2C8\uB2E4.",
|
|
3484
|
+
"reason.documentUnchanged": "\uCD5C\uC885 \uBCC0\uACBD\uC774 \uC5C6\uB294 \uBB38\uC11C\uC5D0 \uC774\uC720\uB97C \uBD99\uC77C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: {id}",
|
|
3485
|
+
"reason.singleDocumentKind": "\uD55C \uC774\uC720\uB294 \uD55C \uC885\uB958\uC758 \uBB38\uC11C\uB9CC \uB300\uC0C1\uC73C\uB85C \uD569\uB2C8\uB2E4.",
|
|
3486
|
+
"reason.invalidTarget": "\uC798\uBABB\uB41C \uC774\uC720 \uB300\uC0C1\uC785\uB2C8\uB2E4.",
|
|
3487
|
+
"reason.targetKind": "\uC774\uC720 \uB300\uC0C1 \uC885\uB958\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
3488
|
+
"reason.targetInvalid": "\uC774\uC720 \uB300\uC0C1\uC774 \uC798\uBABB\uB410\uAC70\uB098 \uC911\uBCF5\uB429\uB2C8\uB2E4.",
|
|
3489
|
+
"reason.requirementUnchanged": "\uCD5C\uC885 \uBCC0\uACBD\uC774 \uC5C6\uB294 \uC694\uAD6C\uC0AC\uD56D\uC5D0 \uC774\uC720\uB97C \uBD99\uC77C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: {id}",
|
|
3490
|
+
"reason.keepDeletedSpec": "\uC0AD\uC81C \uC774\uC720\uB97C \uAE30\uB85D\uD560 \uC6D0\uB798 \uBA85\uC138\uB97C \uB0A8\uACA8\uC8FC\uC138\uC694.",
|
|
3491
|
+
"readError.GIT_NOT_FOUND": "Git \uC2E4\uD589 \uD30C\uC77C\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
3492
|
+
"readError.GIT_CONTEXT_OVERRIDE": "\uD604\uC7AC checkout\uACFC \uB2E4\uB978 Git \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uC9C0\uC815\uD558\uB294 \uD658\uACBD\uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
3493
|
+
"readError.NOT_A_REPOSITORY": "\uD604\uC7AC \uC704\uCE58\uAC00 Git \uC791\uC5C5 \uD3F4\uB354\uC5D0 \uC18D\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
3494
|
+
"readError.UNSUPPORTED_REPOSITORY": "bare \uC800\uC7A5\uC18C \uB610\uB294 Git \uAD00\uB9AC \uB514\uB809\uD130\uB9AC\uC5D0\uC11C\uB294 \uC870\uD68C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
3495
|
+
"readError.GIT_UNSUPPORTED": "\uD544\uC694\uD55C Git \uC635\uC158 \uB610\uB294 object format\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
3496
|
+
"readError.GIT_FAILED": "Git \uC870\uD68C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uC800\uC7A5\uC18C \uC811\uADFC \uAD8C\uD55C\uACFC Git \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
3497
|
+
"readError.INVALID_GIT_OUTPUT": "Git \uC0C1\uD0DC \uCD9C\uB825\uC774 \uC9C0\uC6D0\uD558\uB294 \uD615\uC2DD\uACFC \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
3498
|
+
"readError.UNSUPPORTED_PATH_ENCODING": "Git \uACBD\uB85C\uB97C UTF-8\uB85C \uC190\uC2E4 \uC5C6\uC774 \uD45C\uD604\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
3499
|
+
"readError.REPOSITORY_CHANGED": "\uC870\uD68C \uC911 \uC800\uC7A5\uC18C \uC0C1\uD0DC\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC870\uD68C\uD558\uC138\uC694.",
|
|
3500
|
+
"readError.READ_LIMIT_EXCEEDED": "Git \uC870\uD68C\uC758 \uC2DC\uAC04 \uB610\uB294 \uCD9C\uB825 \uD06C\uAE30 \uC81C\uD55C\uC744 \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
|
|
3501
|
+
"changelog.atLine": "\uD328\uCE58\uB178\uD2B8 {line}\uD589: {reason}",
|
|
3502
|
+
"changelog.emptyVersion": "{version} \uBC84\uC804\uC5D0 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
3503
|
+
"changelog.invalidDate": "\uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uB0A0\uC9DC\uC785\uB2C8\uB2E4: {text}",
|
|
3504
|
+
"changelog.order": "\uBC84\uC804\uC740 \uCD5C\uC2E0\uC774 \uC55E\uC5D0 \uC624\uB3C4\uB85D \uB0B4\uB9BC\uCC28\uC21C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: {version}",
|
|
3505
|
+
"changelog.sectionBeforeVersion": "\uBC84\uC804 \uC81C\uBAA9\uBCF4\uB2E4 \uC808 \uC81C\uBAA9\uC774 \uBA3C\uC800 \uB098\uC654\uC2B5\uB2C8\uB2E4.",
|
|
3506
|
+
"changelog.duplicateSection": "\uAC19\uC740 \uBC84\uC804\uC5D0 {section} \uC808\uC774 \uB450 \uBC88 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
3507
|
+
"changelog.itemOutsideSection": "\uC808 \uC81C\uBAA9(### Added|Changed|Removed|Fixed) \uC544\uB798\uC5D0\uB9CC \uD56D\uBAA9\uC744 \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
3508
|
+
"changelog.unknownLine": '\uC778\uC2DD\uD560 \uC218 \uC5C6\uB294 \uC904\uC785\uB2C8\uB2E4. \uBC84\uC804\uC740 "## X.Y.Z - YYYY-MM-DD", \uC808\uC740 "### Added|Changed|Removed|Fixed", \uD56D\uBAA9\uC740 "- "\uB85C \uC501\uB2C8\uB2E4: {text}',
|
|
3509
|
+
"changelog.noVersions": "\uBC84\uC804\uC774 \uD558\uB098\uB3C4 \uC5C6\uC2B5\uB2C8\uB2E4."
|
|
3413
3510
|
};
|
|
3511
|
+
|
|
3512
|
+
// ../../packages/core/dist/shared/i18n/index.js
|
|
3513
|
+
var defaultLanguage = "ko";
|
|
3514
|
+
var catalogs = { ko: messages_default };
|
|
3515
|
+
function t(key, values = {}, lang = defaultLanguage) {
|
|
3516
|
+
return catalogs[lang][key].replace(/\{(\w+)\}/g, (whole, name) => name in values ? String(values[name]) : whole);
|
|
3517
|
+
}
|
|
3518
|
+
|
|
3519
|
+
// ../../packages/core/dist/domain/read-error.js
|
|
3414
3520
|
var RepositoryReadError = class extends Error {
|
|
3415
3521
|
code;
|
|
3416
3522
|
constructor(code) {
|
|
3417
|
-
super(
|
|
3523
|
+
super(t(`readError.${code}`));
|
|
3418
3524
|
this.name = "RepositoryReadError";
|
|
3419
3525
|
this.code = code;
|
|
3420
3526
|
}
|
|
@@ -3451,12 +3557,12 @@ function parseProjectConfig(text2) {
|
|
|
3451
3557
|
try {
|
|
3452
3558
|
value = JSON.parse(text2);
|
|
3453
3559
|
} catch {
|
|
3454
|
-
throw new InitError("INVALID_CONFIG", "
|
|
3560
|
+
throw new InitError("INVALID_CONFIG", t("config.jsonUnreadable"));
|
|
3455
3561
|
}
|
|
3456
3562
|
if (object(value) && value.kind === "tryce-project" && typeof value.format === "string" && !["init-1", "prototype-1", "workflow-1"].includes(value.format)) {
|
|
3457
|
-
throw new InitError("UNSUPPORTED_FORMAT", "
|
|
3563
|
+
throw new InitError("UNSUPPORTED_FORMAT", t("config.unsupportedFormat"));
|
|
3458
3564
|
}
|
|
3459
|
-
const invalid2 = () => new InitError("INVALID_CONFIG", "
|
|
3565
|
+
const invalid2 = () => new InitError("INVALID_CONFIG", t("config.invalidFields"));
|
|
3460
3566
|
if (!object(value) || !keys(value, ["kind", "format", "mode", "baseline"]) || value.kind !== "tryce-project" || !["init-1", "prototype-1", "workflow-1"].includes(String(value.format)) || typeof value.format !== "string" || typeof value.mode !== "string" || !(value.format === "workflow-1" ? ["auto", "approval"] : ["normal", "prototype"]).includes(value.mode) || !object(value.baseline))
|
|
3461
3567
|
throw invalid2();
|
|
3462
3568
|
const b = value.baseline;
|
|
@@ -3477,13 +3583,13 @@ function parseManagedConfig(text2) {
|
|
|
3477
3583
|
try {
|
|
3478
3584
|
value = JSON.parse(text2);
|
|
3479
3585
|
} catch {
|
|
3480
|
-
throw new InitError("INVALID_CONFIG", "
|
|
3586
|
+
throw new InitError("INVALID_CONFIG", t("config.jsonUnreadableShort"));
|
|
3481
3587
|
}
|
|
3482
3588
|
if (!value || typeof value !== "object" || Array.isArray(value) || !("schemaVersion" in value))
|
|
3483
3589
|
return parseProjectConfig(text2);
|
|
3484
3590
|
const config2 = value;
|
|
3485
3591
|
if (Object.keys(config2).sort().join(",") !== "baseline,schemaVersion" || config2.schemaVersion !== 1)
|
|
3486
|
-
throw new InitError("INVALID_CONFIG", "
|
|
3592
|
+
throw new InitError("INVALID_CONFIG", t("config.schemaFields"));
|
|
3487
3593
|
const checked = parseProjectConfig(JSON.stringify({ kind: "tryce-project", format: "workflow-1", mode: "auto", baseline: config2.baseline }));
|
|
3488
3594
|
return { schemaVersion: 1, baseline: checked.baseline };
|
|
3489
3595
|
}
|
|
@@ -3514,13 +3620,13 @@ var nameToken = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
|
3514
3620
|
function validateDocumentRelativePath(relative) {
|
|
3515
3621
|
const parts = relative.split("/");
|
|
3516
3622
|
if (relative.length > 200 || parts.length > 8)
|
|
3517
|
-
fail("
|
|
3623
|
+
fail(t("document.pathTooLong", { path: relative }));
|
|
3518
3624
|
const file2 = parts.pop();
|
|
3519
3625
|
if (!file2.endsWith(".md") || !nameToken.test(file2.slice(0, -3)))
|
|
3520
|
-
fail("
|
|
3626
|
+
fail(t("document.fileName", { path: relative }));
|
|
3521
3627
|
for (const part of parts)
|
|
3522
3628
|
if (!nameToken.test(part) || part.length > 80)
|
|
3523
|
-
fail("
|
|
3629
|
+
fail(t("document.folderName", { path: relative }));
|
|
3524
3630
|
}
|
|
3525
3631
|
var storeRelative = (path3) => path3.replace(/^\.(?:gitifact|tryce)\//, "");
|
|
3526
3632
|
var reqId = new RegExp(`^R-${token}$`);
|
|
@@ -3538,19 +3644,19 @@ ${design.body}
|
|
|
3538
3644
|
}
|
|
3539
3645
|
function parseDesignPreview(source, specId) {
|
|
3540
3646
|
if (source.includes("\0") || /\r(?!\n)/.test(source))
|
|
3541
|
-
fail("
|
|
3647
|
+
fail(t("design.invalidCharacters"));
|
|
3542
3648
|
const lines = normalized(source).split("\n");
|
|
3543
3649
|
if (!new RegExp(`^<!-- ${marker}-design: ${specId} -->$`).test(lines.shift() ?? ""))
|
|
3544
|
-
fail("
|
|
3650
|
+
fail(t("design.idMismatch"));
|
|
3545
3651
|
while (lines[0] === "")
|
|
3546
3652
|
lines.shift();
|
|
3547
3653
|
const heading = lines.shift();
|
|
3548
3654
|
if (!heading?.startsWith("# ") || !heading.slice(2).trim())
|
|
3549
|
-
fail("
|
|
3655
|
+
fail(t("design.titleRequired"));
|
|
3550
3656
|
const title = heading.slice(2).trim();
|
|
3551
3657
|
const raw = normalized(lines.join("\n"));
|
|
3552
3658
|
if (!raw)
|
|
3553
|
-
fail("
|
|
3659
|
+
fail(t("design.bodyRequired"));
|
|
3554
3660
|
const references = /* @__PURE__ */ new Set();
|
|
3555
3661
|
let fence;
|
|
3556
3662
|
const body = raw.split("\n").map((line) => {
|
|
@@ -3565,11 +3671,11 @@ function parseDesignPreview(source, specId) {
|
|
|
3565
3671
|
return line;
|
|
3566
3672
|
}
|
|
3567
3673
|
if (/^#\s/.test(line))
|
|
3568
|
-
fail("
|
|
3674
|
+
fail(t("design.singleTopHeading"));
|
|
3569
3675
|
if (/<!-- (?:gitifact|tryce)-/.test(line)) {
|
|
3570
3676
|
const ref = /^<!-- (?:gitifact|tryce)-ref: (R-[a-z2-7]{10}(?:, R-[a-z2-7]{10})*) -->$/.exec(line);
|
|
3571
3677
|
if (!ref)
|
|
3572
|
-
fail("
|
|
3678
|
+
fail(t("design.referenceFormat"));
|
|
3573
3679
|
for (const id of ref[1].split(", "))
|
|
3574
3680
|
references.add(id);
|
|
3575
3681
|
return `<!-- gitifact-ref: ${ref[1]} -->`;
|
|
@@ -3577,7 +3683,7 @@ function parseDesignPreview(source, specId) {
|
|
|
3577
3683
|
return line;
|
|
3578
3684
|
}).join("\n");
|
|
3579
3685
|
if (fence)
|
|
3580
|
-
fail("
|
|
3686
|
+
fail(t("design.unclosedFence"));
|
|
3581
3687
|
return { title, body, requirements: [...references] };
|
|
3582
3688
|
}
|
|
3583
3689
|
function renderDocument(doc) {
|
|
@@ -3591,28 +3697,28 @@ ${doc.body}
|
|
|
3591
3697
|
function parseDocument(path3, source) {
|
|
3592
3698
|
const match = documentPathPattern.exec(path3);
|
|
3593
3699
|
if (!match)
|
|
3594
|
-
fail("
|
|
3700
|
+
fail(t("document.unsupportedPath", { path: path3 }));
|
|
3595
3701
|
const kind = kindOfDir(match[1]);
|
|
3596
3702
|
if (kind === "product") {
|
|
3597
3703
|
if (path3 !== PRODUCT_PATH)
|
|
3598
|
-
fail("
|
|
3704
|
+
fail(t("document.productOnly", { path: path3 }));
|
|
3599
3705
|
} else
|
|
3600
3706
|
validateDocumentRelativePath(match[2]);
|
|
3601
3707
|
if (source.includes("\0") || /\r(?!\n)/.test(source))
|
|
3602
|
-
fail("
|
|
3708
|
+
fail(t("document.invalidCharacters", { path: path3 }));
|
|
3603
3709
|
const lines = normalized(source).split("\n");
|
|
3604
3710
|
const id = new RegExp(`^<!-- gitifact-${kind}: ([PG]-${token}) -->$`).exec(lines.shift() ?? "")?.[1];
|
|
3605
3711
|
if (!id || id[0] !== (kind === "product" ? "P" : "G"))
|
|
3606
|
-
return fail(
|
|
3712
|
+
return fail(t("document.idRequired", { kind, path: path3 }));
|
|
3607
3713
|
while (lines[0] === "")
|
|
3608
3714
|
lines.shift();
|
|
3609
3715
|
const heading = lines.shift();
|
|
3610
3716
|
if (!heading?.startsWith("# ") || !heading.slice(2).trim())
|
|
3611
|
-
fail("
|
|
3717
|
+
fail(t("document.titleRequired", { path: path3 }));
|
|
3612
3718
|
const title = heading.slice(2).trim();
|
|
3613
3719
|
const body = normalized(lines.join("\n"));
|
|
3614
3720
|
if (!body)
|
|
3615
|
-
fail("
|
|
3721
|
+
fail(t("document.bodyRequired", { path: path3 }));
|
|
3616
3722
|
let fence;
|
|
3617
3723
|
for (const line of body.split("\n")) {
|
|
3618
3724
|
if (fence) {
|
|
@@ -3626,12 +3732,12 @@ function parseDocument(path3, source) {
|
|
|
3626
3732
|
continue;
|
|
3627
3733
|
}
|
|
3628
3734
|
if (/^#\s/.test(line))
|
|
3629
|
-
fail("
|
|
3735
|
+
fail(t("document.singleTopHeading", { path: path3 }));
|
|
3630
3736
|
if (/<!-- (?:gitifact|tryce)-/.test(line))
|
|
3631
|
-
fail("
|
|
3737
|
+
fail(t("document.noMarkerInBody", { path: path3 }));
|
|
3632
3738
|
}
|
|
3633
3739
|
if (fence)
|
|
3634
|
-
fail("
|
|
3740
|
+
fail(t("document.unclosedFence", { path: path3 }));
|
|
3635
3741
|
return { id, kind, path: path3, title, body };
|
|
3636
3742
|
}
|
|
3637
3743
|
function parseDocumentFiles(files) {
|
|
@@ -3652,22 +3758,22 @@ function validateDocumentSets(sets) {
|
|
|
3652
3758
|
const paths2 = /* @__PURE__ */ new Set();
|
|
3653
3759
|
const historyIds = /* @__PURE__ */ new Set();
|
|
3654
3760
|
if (sets.map((s) => s.kind).sort().join(",") !== "guide,product")
|
|
3655
|
-
fail("
|
|
3761
|
+
fail(t("document.kindSet"));
|
|
3656
3762
|
for (const set2 of sets) {
|
|
3657
3763
|
for (const d of set2.documents) {
|
|
3658
3764
|
if (d.kind !== set2.kind)
|
|
3659
|
-
fail("
|
|
3765
|
+
fail(t("document.kindMismatch", { path: d.path }));
|
|
3660
3766
|
if (ids.has(d.id))
|
|
3661
|
-
fail("
|
|
3767
|
+
fail(t("document.duplicateId", { id: d.id }));
|
|
3662
3768
|
ids.add(d.id);
|
|
3663
3769
|
const lower = d.path.toLowerCase();
|
|
3664
3770
|
if (paths2.has(lower))
|
|
3665
|
-
fail("
|
|
3771
|
+
fail(t("document.caseOnlyPath", { path: d.path }));
|
|
3666
3772
|
paths2.add(lower);
|
|
3667
3773
|
}
|
|
3668
3774
|
for (const h of set2.history) {
|
|
3669
3775
|
if (historyIds.has(h.id))
|
|
3670
|
-
fail("
|
|
3776
|
+
fail(t("history.duplicateId", { id: h.id }));
|
|
3671
3777
|
historyIds.add(h.id);
|
|
3672
3778
|
}
|
|
3673
3779
|
}
|
|
@@ -3685,7 +3791,7 @@ function validateBundle(bundle) {
|
|
|
3685
3791
|
const ids = /* @__PURE__ */ new Set();
|
|
3686
3792
|
for (const h of [...bundle.specs.flatMap((s) => s.history), ...bundle.documents.flatMap((d) => d.history)]) {
|
|
3687
3793
|
if (ids.has(h.id))
|
|
3688
|
-
fail("
|
|
3794
|
+
fail(t("history.duplicateId", { id: h.id }));
|
|
3689
3795
|
ids.add(h.id);
|
|
3690
3796
|
}
|
|
3691
3797
|
}
|
|
@@ -3701,20 +3807,20 @@ function parsePreviewFiles(files) {
|
|
|
3701
3807
|
if (path3.endsWith("/requirements.md")) {
|
|
3702
3808
|
specs.push(parseSpecPreview(path3, source, files.get(path3.replace(/requirements\.md$/, "history.jsonl")) ?? "", files.get(path3.replace(/requirements\.md$/, "design.md"))));
|
|
3703
3809
|
} else if (!files.has(path3.replace(/(?:history\.jsonl|design\.md)$/, "requirements.md")))
|
|
3704
|
-
fail("
|
|
3810
|
+
fail(t("spec.orphanFile", { path: path3 }));
|
|
3705
3811
|
}
|
|
3706
3812
|
validatePreviewSnapshot(specs);
|
|
3707
3813
|
return specs;
|
|
3708
3814
|
}
|
|
3709
3815
|
function parseSpecPreview(path3, source, history = "", designSource) {
|
|
3710
3816
|
if (!/^\.(?:gitifact|tryce)\/spec\/[^/]+\/requirements\.md$/.test(path3))
|
|
3711
|
-
fail("
|
|
3817
|
+
fail(t("spec.unsupportedPath", { path: path3 }));
|
|
3712
3818
|
if (source.includes("\0") || source.includes("\r") && /\r(?!\n)/.test(source))
|
|
3713
|
-
fail("
|
|
3819
|
+
fail(t("spec.invalidCharacters", { path: path3 }));
|
|
3714
3820
|
const lines = normalized(source).split("\n");
|
|
3715
3821
|
const specMatch = new RegExp(`^<!-- ${marker}-spec: (S-${token}) -->$`).exec(lines[0] ?? "");
|
|
3716
3822
|
if (!specMatch)
|
|
3717
|
-
fail("
|
|
3823
|
+
fail(t("spec.idRequired", { path: path3 }));
|
|
3718
3824
|
let title = "";
|
|
3719
3825
|
let description = "";
|
|
3720
3826
|
let current;
|
|
@@ -3732,7 +3838,7 @@ function parseSpecPreview(path3, source, history = "", designSource) {
|
|
|
3732
3838
|
if (waitingId) {
|
|
3733
3839
|
const match = new RegExp(`^<!-- ${marker}-req: (R-${token}) -->$`).exec(line);
|
|
3734
3840
|
if (!match || !current)
|
|
3735
|
-
fail("
|
|
3841
|
+
fail(t("spec.requirementIdRequired", { path: path3 }));
|
|
3736
3842
|
current.id = match[1];
|
|
3737
3843
|
waitingId = false;
|
|
3738
3844
|
continue;
|
|
@@ -3746,42 +3852,42 @@ function parseSpecPreview(path3, source, history = "", designSource) {
|
|
|
3746
3852
|
const opening = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
|
|
3747
3853
|
if (opening) {
|
|
3748
3854
|
if (opening[1][0] === "`" && opening[2].includes("`"))
|
|
3749
|
-
fail("
|
|
3855
|
+
fail(t("spec.invalidFence"));
|
|
3750
3856
|
fence = { char: opening[1][0], size: opening[1].length };
|
|
3751
3857
|
append(line);
|
|
3752
3858
|
continue;
|
|
3753
3859
|
}
|
|
3754
3860
|
if (/^# /.test(line)) {
|
|
3755
3861
|
if (title || current || description.trim())
|
|
3756
|
-
fail("
|
|
3862
|
+
fail(t("spec.titleOnce", { path: path3 }));
|
|
3757
3863
|
title = line.slice(2).trim();
|
|
3758
3864
|
if (!title)
|
|
3759
|
-
fail("
|
|
3865
|
+
fail(t("spec.emptyTitle"));
|
|
3760
3866
|
continue;
|
|
3761
3867
|
}
|
|
3762
3868
|
if (/^## /.test(line)) {
|
|
3763
3869
|
if (!title)
|
|
3764
|
-
fail("
|
|
3870
|
+
fail(t("spec.titleMissing", { path: path3 }));
|
|
3765
3871
|
current = { id: "", title: line.slice(3).trim(), body: "" };
|
|
3766
3872
|
if (!current.title)
|
|
3767
|
-
fail("
|
|
3873
|
+
fail(t("spec.emptyRequirementTitle"));
|
|
3768
3874
|
requirements.push(current);
|
|
3769
3875
|
waitingId = true;
|
|
3770
3876
|
continue;
|
|
3771
3877
|
}
|
|
3772
3878
|
if (line.includes("<!--") || line.includes("-->"))
|
|
3773
|
-
fail("
|
|
3879
|
+
fail(t("spec.commentPosition", { path: path3 }));
|
|
3774
3880
|
if (/^ {1,3}#{1,2}\s|^#{1,2}\t|^\s*(?:===+|---+)\s*$/.test(line))
|
|
3775
|
-
fail("
|
|
3881
|
+
fail(t("spec.atxOnly", { path: path3 }));
|
|
3776
3882
|
append(line);
|
|
3777
3883
|
}
|
|
3778
3884
|
if (!title || waitingId || fence)
|
|
3779
|
-
fail("
|
|
3885
|
+
fail(t("spec.incomplete", { path: path3 }));
|
|
3780
3886
|
const ids = /* @__PURE__ */ new Set();
|
|
3781
3887
|
for (const r of requirements) {
|
|
3782
3888
|
r.body = normalized(r.body);
|
|
3783
3889
|
if (!r.body || ids.has(r.id))
|
|
3784
|
-
fail("
|
|
3890
|
+
fail(t("spec.emptyOrDuplicateRequirement", { id: r.id }));
|
|
3785
3891
|
ids.add(r.id);
|
|
3786
3892
|
}
|
|
3787
3893
|
return { id: specMatch[1], path: path3, title, description: normalized(description), requirements, history: parsePreviewHistory(history), ...designSource === void 0 ? {} : { design: parseDesignPreview(designSource, specMatch[1]) } };
|
|
@@ -3797,13 +3903,13 @@ function parsePreviewHistory(source, scope = "spec") {
|
|
|
3797
3903
|
try {
|
|
3798
3904
|
value = JSON.parse(line);
|
|
3799
3905
|
} catch {
|
|
3800
|
-
fail("
|
|
3906
|
+
fail(t("history.invalidJsonl"));
|
|
3801
3907
|
}
|
|
3802
3908
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
3803
|
-
fail("
|
|
3909
|
+
fail(t("history.invalidRecord"));
|
|
3804
3910
|
const r = value;
|
|
3805
3911
|
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" || !/^[PG]-[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)
|
|
3806
|
-
fail("
|
|
3912
|
+
fail(t("history.invalidFields"));
|
|
3807
3913
|
ids.add(r.id);
|
|
3808
3914
|
records.push({ id: r.id, requirements: r.requirements, ...r.designs === void 0 ? {} : { designs: r.designs }, ...r.documents === void 0 ? {} : { documents: r.documents }, reason: r.reason });
|
|
3809
3915
|
}
|
|
@@ -3815,16 +3921,16 @@ function validatePreviewSnapshot(specs) {
|
|
|
3815
3921
|
const historyIds = /* @__PURE__ */ new Set();
|
|
3816
3922
|
for (const s of specs) {
|
|
3817
3923
|
if (specIds.has(s.id))
|
|
3818
|
-
fail("
|
|
3924
|
+
fail(t("spec.duplicateId", { id: s.id }));
|
|
3819
3925
|
specIds.add(s.id);
|
|
3820
3926
|
for (const r of s.requirements) {
|
|
3821
3927
|
if (reqIds.has(r.id))
|
|
3822
|
-
fail("
|
|
3928
|
+
fail(t("spec.duplicateRequirementId", { id: r.id }));
|
|
3823
3929
|
reqIds.add(r.id);
|
|
3824
3930
|
}
|
|
3825
3931
|
for (const h of s.history) {
|
|
3826
3932
|
if (historyIds.has(h.id))
|
|
3827
|
-
fail("
|
|
3933
|
+
fail(t("history.duplicateId", { id: h.id }));
|
|
3828
3934
|
historyIds.add(h.id);
|
|
3829
3935
|
}
|
|
3830
3936
|
}
|
|
@@ -3843,7 +3949,7 @@ function compareSpecPreviews(before, after) {
|
|
|
3843
3949
|
const reasons = after.flatMap((s) => s.history).filter((h) => {
|
|
3844
3950
|
const old = previousHistory.get(h.id);
|
|
3845
3951
|
if (old && JSON.stringify(old) !== JSON.stringify(h))
|
|
3846
|
-
fail("
|
|
3952
|
+
fail(t("history.changed", { id: h.id }));
|
|
3847
3953
|
return !old;
|
|
3848
3954
|
});
|
|
3849
3955
|
const changes = [.../* @__PURE__ */ new Set([...prev.keys(), ...next.keys()])].sort().flatMap((id) => {
|
|
@@ -3865,7 +3971,7 @@ function compareSpecPreviews(before, after) {
|
|
|
3865
3971
|
const changed = new Set(changes.map((c) => c.id));
|
|
3866
3972
|
for (const h of reasons)
|
|
3867
3973
|
if ([...h.requirements, ...h.designs ?? []].some((id) => !changed.has(id)))
|
|
3868
|
-
fail("
|
|
3974
|
+
fail(t("history.unlinkedRequirement", { id: h.id }));
|
|
3869
3975
|
const prevSpecs = new Map(before.map((s) => [s.id, s]));
|
|
3870
3976
|
const nextSpecs = new Map(after.map((s) => [s.id, s]));
|
|
3871
3977
|
const specChanges = [.../* @__PURE__ */ new Set([...prevSpecs.keys(), ...nextSpecs.keys()])].sort().flatMap((id) => {
|
|
@@ -3889,7 +3995,7 @@ function compareDocumentSets(before, after) {
|
|
|
3889
3995
|
const reasons = after.flatMap((s) => s.history).filter((h) => {
|
|
3890
3996
|
const old = previousHistory.get(h.id);
|
|
3891
3997
|
if (old && JSON.stringify(old) !== JSON.stringify(h))
|
|
3892
|
-
fail("
|
|
3998
|
+
fail(t("history.changed", { id: h.id }));
|
|
3893
3999
|
return !old;
|
|
3894
4000
|
});
|
|
3895
4001
|
const changes = [.../* @__PURE__ */ new Set([...prev.keys(), ...next.keys()])].sort().flatMap((id) => {
|
|
@@ -3912,7 +4018,7 @@ function compareDocumentSets(before, after) {
|
|
|
3912
4018
|
const changed = new Set(changes.map((c) => c.id));
|
|
3913
4019
|
for (const h of reasons)
|
|
3914
4020
|
if ((h.documents ?? []).some((id) => !changed.has(id)))
|
|
3915
|
-
fail("
|
|
4021
|
+
fail(t("history.unlinkedDocument", { id: h.id }));
|
|
3916
4022
|
return changes;
|
|
3917
4023
|
}
|
|
3918
4024
|
function comparePreviewBundles(before, after) {
|
|
@@ -3924,6 +4030,70 @@ function comparePreviewBundles(before, after) {
|
|
|
3924
4030
|
return { specChanges: specs.specChanges, changes: [...specs.changes, ...compareDocumentSets(a.documents, b.documents)] };
|
|
3925
4031
|
}
|
|
3926
4032
|
|
|
4033
|
+
// ../../packages/core/dist/formats/changelog.js
|
|
4034
|
+
var changelogSections = ["added", "changed", "removed", "fixed"];
|
|
4035
|
+
var versionLine = /^## (\d+)\.(\d+)\.(\d+) - (\d{4})-(\d{2})-(\d{2})$/;
|
|
4036
|
+
var sectionLine = /^### (Added|Changed|Removed|Fixed)$/;
|
|
4037
|
+
var itemLine = /^- (\S.*)$/;
|
|
4038
|
+
var realDate = (year, month, day) => {
|
|
4039
|
+
const date5 = new Date(Date.UTC(year, month - 1, day));
|
|
4040
|
+
return date5.getUTCFullYear() === year && date5.getUTCMonth() === month - 1 && date5.getUTCDate() === day;
|
|
4041
|
+
};
|
|
4042
|
+
function parseChangelog(text2) {
|
|
4043
|
+
const entries = [];
|
|
4044
|
+
let previous;
|
|
4045
|
+
let entry2;
|
|
4046
|
+
let section;
|
|
4047
|
+
const fail8 = (line, key, values = {}) => new InitError("INVALID_CHANGELOG", t("changelog.atLine", { line, reason: t(key, values) }));
|
|
4048
|
+
const lines = text2.replace(/\r\n/g, "\n").split("\n");
|
|
4049
|
+
const close = (line) => {
|
|
4050
|
+
if (entry2 && changelogSections.every((name) => entry2[name].length === 0))
|
|
4051
|
+
throw fail8(line, "changelog.emptyVersion", { version: entry2.version });
|
|
4052
|
+
};
|
|
4053
|
+
lines.forEach((raw, index) => {
|
|
4054
|
+
const line = index + 1;
|
|
4055
|
+
if (raw.trim() === "")
|
|
4056
|
+
return;
|
|
4057
|
+
const version2 = versionLine.exec(raw);
|
|
4058
|
+
if (version2) {
|
|
4059
|
+
close(line);
|
|
4060
|
+
const core = [Number(version2[1]), Number(version2[2]), Number(version2[3])];
|
|
4061
|
+
if (!realDate(Number(version2[4]), Number(version2[5]), Number(version2[6])))
|
|
4062
|
+
throw fail8(line, "changelog.invalidDate", { text: raw });
|
|
4063
|
+
if (previous && !(core[0] < previous[0] || core[0] === previous[0] && (core[1] < previous[1] || core[1] === previous[1] && core[2] < previous[2]))) {
|
|
4064
|
+
throw fail8(line, "changelog.order", { version: core.join(".") });
|
|
4065
|
+
}
|
|
4066
|
+
previous = core;
|
|
4067
|
+
section = void 0;
|
|
4068
|
+
entry2 = { version: core.join("."), date: version2[4] + "-" + version2[5] + "-" + version2[6], added: [], changed: [], removed: [], fixed: [] };
|
|
4069
|
+
entries.push(entry2);
|
|
4070
|
+
return;
|
|
4071
|
+
}
|
|
4072
|
+
const heading = sectionLine.exec(raw);
|
|
4073
|
+
if (heading) {
|
|
4074
|
+
if (!entry2)
|
|
4075
|
+
throw fail8(line, "changelog.sectionBeforeVersion");
|
|
4076
|
+
const name = heading[1].toLowerCase();
|
|
4077
|
+
if (entry2[name].length > 0)
|
|
4078
|
+
throw fail8(line, "changelog.duplicateSection", { section: heading[1] });
|
|
4079
|
+
section = name;
|
|
4080
|
+
return;
|
|
4081
|
+
}
|
|
4082
|
+
const item = itemLine.exec(raw);
|
|
4083
|
+
if (item) {
|
|
4084
|
+
if (!entry2 || !section)
|
|
4085
|
+
throw fail8(line, "changelog.itemOutsideSection");
|
|
4086
|
+
entry2[section].push(item[1].trimEnd());
|
|
4087
|
+
return;
|
|
4088
|
+
}
|
|
4089
|
+
throw fail8(line, "changelog.unknownLine", { text: raw });
|
|
4090
|
+
});
|
|
4091
|
+
close(lines.length);
|
|
4092
|
+
if (entries.length === 0)
|
|
4093
|
+
throw fail8(1, "changelog.noVersions");
|
|
4094
|
+
return entries;
|
|
4095
|
+
}
|
|
4096
|
+
|
|
3927
4097
|
// ../../packages/core/dist/use-cases/edit-spec-preview.js
|
|
3928
4098
|
var fail2 = (message) => {
|
|
3929
4099
|
throw new SpecPreviewError(message);
|
|
@@ -3932,7 +4102,7 @@ var featurePattern = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
|
3932
4102
|
var reserved = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/;
|
|
3933
4103
|
function previewPath(feature2) {
|
|
3934
4104
|
if (!featurePattern.test(feature2) || feature2.length > 80 || reserved.test(feature2))
|
|
3935
|
-
fail2("
|
|
4105
|
+
fail2(t("edit.invalidFeatureName"));
|
|
3936
4106
|
return `.gitifact/spec/${feature2}/requirements.md`;
|
|
3937
4107
|
}
|
|
3938
4108
|
function renderSpecPreview(spec2) {
|
|
@@ -3948,7 +4118,7 @@ ${r.body}
|
|
|
3948
4118
|
}
|
|
3949
4119
|
function editSpecPreview(original, input2, generate) {
|
|
3950
4120
|
if (!Array.isArray(input2) || !input2.length || input2.length > 100)
|
|
3951
|
-
fail2("
|
|
4121
|
+
fail2(t("edit.operationCount"));
|
|
3952
4122
|
const source = asBundle(original);
|
|
3953
4123
|
const specs = source.specs.map((s) => ({ ...s, requirements: s.requirements.map((r) => ({ ...r })), history: s.history.map((h) => ({ ...h, requirements: [...h.requirements] })) }));
|
|
3954
4124
|
const documents = source.documents.map((set2) => ({ ...set2, documents: set2.documents.map((d) => ({ ...d })), history: set2.history.map((h) => ({ ...h })) }));
|
|
@@ -3958,18 +4128,18 @@ function editSpecPreview(original, input2, generate) {
|
|
|
3958
4128
|
for (let attempt = 0; attempt < 100; attempt++) {
|
|
3959
4129
|
const id = generate(prefix);
|
|
3960
4130
|
if (!new RegExp(`^${prefix}-[a-z2-7]{10}$`).test(id))
|
|
3961
|
-
fail2("
|
|
4131
|
+
fail2(t("edit.idGenerated"));
|
|
3962
4132
|
if (!used.has(id)) {
|
|
3963
4133
|
used.add(id);
|
|
3964
4134
|
return id;
|
|
3965
4135
|
}
|
|
3966
4136
|
}
|
|
3967
|
-
return fail2("
|
|
4137
|
+
return fail2(t("edit.idUnavailable"));
|
|
3968
4138
|
};
|
|
3969
4139
|
const results = [];
|
|
3970
4140
|
for (const raw of input2) {
|
|
3971
4141
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
3972
|
-
fail2("
|
|
4142
|
+
fail2(t("edit.invalidOperation"));
|
|
3973
4143
|
const op = raw;
|
|
3974
4144
|
const schemas = {
|
|
3975
4145
|
create: ["type", "feature", "title", "description"],
|
|
@@ -3989,27 +4159,27 @@ function editSpecPreview(original, input2, generate) {
|
|
|
3989
4159
|
const type = String(op.type);
|
|
3990
4160
|
const fields2 = schemas[type];
|
|
3991
4161
|
if (!fields2 || Object.keys(op).some((k) => !fields2.includes(k)))
|
|
3992
|
-
fail2("
|
|
4162
|
+
fail2(t("edit.unsupportedField"));
|
|
3993
4163
|
const str = (key, optional3 = false) => {
|
|
3994
4164
|
if (optional3 && op[key] === void 0)
|
|
3995
4165
|
return "";
|
|
3996
4166
|
if (typeof op[key] !== "string" || !op[key].trim())
|
|
3997
|
-
return fail2("
|
|
4167
|
+
return fail2(t("edit.emptyField", { field: key }));
|
|
3998
4168
|
const value = op[key].replace(/\r\n/g, "\n").trim();
|
|
3999
4169
|
if (value.includes("\0") || value.includes("\r") || key !== "body" && key !== "description" && /[\n]/.test(value))
|
|
4000
|
-
fail2("
|
|
4170
|
+
fail2(t("edit.invalidCharacters", { field: key }));
|
|
4001
4171
|
return value;
|
|
4002
4172
|
};
|
|
4003
4173
|
const target = () => {
|
|
4004
4174
|
const path3 = previewPath(str("feature"));
|
|
4005
|
-
return specs.find((s) => s.path === path3) ?? fail2("
|
|
4175
|
+
return specs.find((s) => s.path === path3) ?? fail2(t("edit.specNotFound", { path: path3 }));
|
|
4006
4176
|
};
|
|
4007
4177
|
if (type === "set-product" || type === "delete-product") {
|
|
4008
4178
|
const set2 = documents.find((s) => s.kind === "product");
|
|
4009
4179
|
const existing = set2.documents[0];
|
|
4010
4180
|
if (type === "delete-product") {
|
|
4011
4181
|
if (!existing)
|
|
4012
|
-
fail2("
|
|
4182
|
+
fail2(t("edit.noProductToDelete"));
|
|
4013
4183
|
set2.documents = [];
|
|
4014
4184
|
results.push({ type, id: existing.id });
|
|
4015
4185
|
} else {
|
|
@@ -4026,14 +4196,14 @@ function editSpecPreview(original, input2, generate) {
|
|
|
4026
4196
|
validateDocumentRelativePath(relative);
|
|
4027
4197
|
const path3 = `${DOCUMENT_DIRS[kind]}/${relative}`;
|
|
4028
4198
|
if (self && self.path === path3)
|
|
4029
|
-
fail2("
|
|
4199
|
+
fail2(t("edit.samePath"));
|
|
4030
4200
|
if (all().some((d) => d !== self && d.path.toLowerCase() === path3.toLowerCase()))
|
|
4031
|
-
fail2("
|
|
4201
|
+
fail2(t("edit.documentPathExists", { path: path3 }));
|
|
4032
4202
|
return path3;
|
|
4033
4203
|
};
|
|
4034
4204
|
const find = () => {
|
|
4035
4205
|
const id = str("id");
|
|
4036
|
-
return all().find((d) => d.id === id) ?? fail2("
|
|
4206
|
+
return all().find((d) => d.id === id) ?? fail2(t("edit.guideIdNotFound", { id }));
|
|
4037
4207
|
};
|
|
4038
4208
|
if (type === "create-doc") {
|
|
4039
4209
|
const kind = "guide";
|
|
@@ -4060,7 +4230,7 @@ function editSpecPreview(original, input2, generate) {
|
|
|
4060
4230
|
if (type === "create") {
|
|
4061
4231
|
const path3 = previewPath(str("feature"));
|
|
4062
4232
|
if (specs.some((s) => s.path.toLowerCase() === path3.toLowerCase()))
|
|
4063
|
-
fail2("
|
|
4233
|
+
fail2(t("edit.featureExists"));
|
|
4064
4234
|
const spec2 = { id: allocate("S"), path: path3, title: str("title"), description: str("description", true), requirements: [], history: [] };
|
|
4065
4235
|
specs.push(spec2);
|
|
4066
4236
|
results.push({ type, id: spec2.id });
|
|
@@ -4073,23 +4243,23 @@ function editSpecPreview(original, input2, generate) {
|
|
|
4073
4243
|
const spec2 = target();
|
|
4074
4244
|
if (type === "delete-design") {
|
|
4075
4245
|
if (!spec2.design)
|
|
4076
|
-
fail2("
|
|
4246
|
+
fail2(t("edit.noDesignToDelete"));
|
|
4077
4247
|
delete spec2.design;
|
|
4078
4248
|
} else
|
|
4079
4249
|
spec2.design = parseDesignPreview(renderDesignPreview(spec2.id, { title: str("title"), body: str("body") }), spec2.id);
|
|
4080
4250
|
results.push({ type, id: spec2.id });
|
|
4081
4251
|
} else if (type === "rename-spec") {
|
|
4082
|
-
const spec2 = specs.find((s) => s.id === str("id")) ?? fail2("
|
|
4252
|
+
const spec2 = specs.find((s) => s.id === str("id")) ?? fail2(t("edit.specIdNotFound"));
|
|
4083
4253
|
spec2.title = str("title");
|
|
4084
4254
|
results.push({ type, id: spec2.id });
|
|
4085
4255
|
} else {
|
|
4086
4256
|
const id = str("id");
|
|
4087
|
-
const source2 = specs.find((s) => s.requirements.some((r) => r.id === id)) ?? fail2("
|
|
4257
|
+
const source2 = specs.find((s) => s.requirements.some((r) => r.id === id)) ?? fail2(t("edit.requirementIdNotFound"));
|
|
4088
4258
|
const req = source2.requirements.find((r) => r.id === id);
|
|
4089
4259
|
if (type === "move") {
|
|
4090
4260
|
const destination = target();
|
|
4091
4261
|
if (source2 === destination)
|
|
4092
|
-
fail2("
|
|
4262
|
+
fail2(t("edit.sameSpec"));
|
|
4093
4263
|
source2.requirements = source2.requirements.filter((r) => r.id !== id);
|
|
4094
4264
|
destination.requirements.push(req);
|
|
4095
4265
|
} else {
|
|
@@ -4102,13 +4272,13 @@ function editSpecPreview(original, input2, generate) {
|
|
|
4102
4272
|
for (const spec2 of specs) {
|
|
4103
4273
|
const parsed = parseSpecPreview(spec2.path, renderSpecPreview(spec2), "", spec2.design ? renderDesignPreview(spec2.id, spec2.design) : void 0);
|
|
4104
4274
|
if (JSON.stringify({ ...parsed, history: spec2.history }) !== JSON.stringify(spec2))
|
|
4105
|
-
fail2("
|
|
4275
|
+
fail2(t("edit.bodyChangesSpecStructure"));
|
|
4106
4276
|
}
|
|
4107
4277
|
for (const set2 of documents) {
|
|
4108
4278
|
set2.documents.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
4109
4279
|
for (const doc of set2.documents)
|
|
4110
4280
|
if (JSON.stringify(parseDocument(doc.path, renderDocument(doc))) !== JSON.stringify(doc))
|
|
4111
|
-
fail2("
|
|
4281
|
+
fail2(t("edit.bodyChangesDocumentStructure", { path: doc.path }));
|
|
4112
4282
|
}
|
|
4113
4283
|
validateBundle({ specs, documents });
|
|
4114
4284
|
return { specs, documents, results };
|
|
@@ -4136,14 +4306,14 @@ function finalSpecPreviewChanges(beforeValue, currentValue) {
|
|
|
4136
4306
|
for (const previous of before.specs) {
|
|
4137
4307
|
const next = current.specs.find((s) => s.id === previous.id);
|
|
4138
4308
|
if (previous.history.length && !next)
|
|
4139
|
-
fail3("
|
|
4309
|
+
fail3(t("reason.keepEmptySpec", { id: previous.id }));
|
|
4140
4310
|
if (next && !equal(next.history.slice(0, previous.history.length), previous.history))
|
|
4141
|
-
fail3("
|
|
4311
|
+
fail3(t("reason.committedImmutable", { id: previous.id }));
|
|
4142
4312
|
}
|
|
4143
4313
|
for (const previous of before.documents) {
|
|
4144
4314
|
const next = current.documents.find((s) => s.kind === previous.kind);
|
|
4145
4315
|
if (!equal(next.history.slice(0, previous.history.length), previous.history))
|
|
4146
|
-
fail3("
|
|
4316
|
+
fail3(t("reason.committedDocumentImmutable", { kind: previous.kind }));
|
|
4147
4317
|
}
|
|
4148
4318
|
const clean = {
|
|
4149
4319
|
specs: current.specs.map((s) => ({ ...s, history: before.specs.find((p) => p.id === s.id)?.history ?? [] })),
|
|
@@ -4158,7 +4328,7 @@ function prepareSpecPreview(beforeValue, currentValue, baseFiles, currentFiles,
|
|
|
4158
4328
|
const current = currentBundle.specs;
|
|
4159
4329
|
const delta = finalSpecPreviewChanges(beforeBundle, currentBundle);
|
|
4160
4330
|
if (!Array.isArray(input2) || input2.length > 100)
|
|
4161
|
-
fail3("
|
|
4331
|
+
fail3(t("reason.count"));
|
|
4162
4332
|
const writes = /* @__PURE__ */ new Map();
|
|
4163
4333
|
const pending = /* @__PURE__ */ new Map();
|
|
4164
4334
|
const covered = /* @__PURE__ */ new Set();
|
|
@@ -4168,34 +4338,34 @@ function prepareSpecPreview(beforeValue, currentValue, baseFiles, currentFiles,
|
|
|
4168
4338
|
for (let attempt = 0; attempt < 100; attempt++) {
|
|
4169
4339
|
const id = generate();
|
|
4170
4340
|
if (!/^H-[a-z2-7]{10}$/.test(id))
|
|
4171
|
-
fail3("
|
|
4341
|
+
fail3(t("reason.idGenerated"));
|
|
4172
4342
|
if (!used.has(id)) {
|
|
4173
4343
|
used.add(id);
|
|
4174
4344
|
return id;
|
|
4175
4345
|
}
|
|
4176
4346
|
}
|
|
4177
|
-
return fail3("
|
|
4347
|
+
return fail3(t("reason.idUnavailable"));
|
|
4178
4348
|
};
|
|
4179
4349
|
for (const value of input2) {
|
|
4180
4350
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
4181
|
-
fail3("
|
|
4351
|
+
fail3(t("reason.invalidInput"));
|
|
4182
4352
|
const raw = value;
|
|
4183
4353
|
const shape = Object.keys(raw).sort().join(",");
|
|
4184
4354
|
if (!["reason,requirements", "designs,reason,requirements", "documents,reason,requirements"].includes(shape) || typeof raw.reason !== "string" || !raw.reason.trim() || raw.reason.includes("\0") || raw.reason.length > 16e3 || !Array.isArray(raw.requirements) || raw.designs !== void 0 && !Array.isArray(raw.designs) || raw.documents !== void 0 && !Array.isArray(raw.documents) || !(raw.requirements.length || raw.designs?.length || raw.documents?.length))
|
|
4185
|
-
fail3("
|
|
4355
|
+
fail3(t("reason.targetsRequired"));
|
|
4186
4356
|
const reason = raw.reason.trim();
|
|
4187
4357
|
const groups = /* @__PURE__ */ new Map();
|
|
4188
4358
|
if (raw.documents !== void 0) {
|
|
4189
4359
|
if (raw.requirements.length)
|
|
4190
|
-
fail3("
|
|
4360
|
+
fail3(t("reason.documentWithRequirements"));
|
|
4191
4361
|
const ids = raw.documents;
|
|
4192
4362
|
let kind;
|
|
4193
4363
|
for (const value2 of ids) {
|
|
4194
4364
|
if (typeof value2 !== "string" || !/^[PG]-[a-z2-7]{10}$/.test(value2) || covered.has(value2))
|
|
4195
|
-
return fail3("
|
|
4196
|
-
const change2 = delta.changes.find((c) => c.id === value2) ?? fail3("
|
|
4365
|
+
return fail3(t("reason.documentTargetInvalid"));
|
|
4366
|
+
const change2 = delta.changes.find((c) => c.id === value2) ?? fail3(t("reason.documentUnchanged", { id: value2 }));
|
|
4197
4367
|
if (kind && change2.kind !== kind)
|
|
4198
|
-
fail3("
|
|
4368
|
+
fail3(t("reason.singleDocumentKind"));
|
|
4199
4369
|
kind = change2.kind;
|
|
4200
4370
|
covered.add(value2);
|
|
4201
4371
|
}
|
|
@@ -4208,16 +4378,16 @@ function prepareSpecPreview(beforeValue, currentValue, baseFiles, currentFiles,
|
|
|
4208
4378
|
}
|
|
4209
4379
|
for (const value2 of [...raw.requirements, ...raw.designs ?? []]) {
|
|
4210
4380
|
if (typeof value2 !== "string")
|
|
4211
|
-
fail3("
|
|
4381
|
+
fail3(t("reason.invalidTarget"));
|
|
4212
4382
|
const id = value2;
|
|
4213
4383
|
if (raw.requirements.includes(id) ? !/^R-[a-z2-7]{10}$/.test(id) : !/^S-[a-z2-7]{10}$/.test(id))
|
|
4214
|
-
fail3("
|
|
4384
|
+
fail3(t("reason.targetKind"));
|
|
4215
4385
|
if (typeof id !== "string" || covered.has(id))
|
|
4216
|
-
fail3("
|
|
4217
|
-
const change2 = delta.changes.find((c) => c.id === id) ?? fail3("
|
|
4386
|
+
fail3(t("reason.targetInvalid"));
|
|
4387
|
+
const change2 = delta.changes.find((c) => c.id === id) ?? fail3(t("reason.requirementUnchanged", { id }));
|
|
4218
4388
|
const specId = (change2.after ?? change2.before).specId;
|
|
4219
4389
|
if (!current.some((s) => s.id === specId))
|
|
4220
|
-
fail3("
|
|
4390
|
+
fail3(t("reason.keepDeletedSpec"));
|
|
4221
4391
|
covered.add(id);
|
|
4222
4392
|
groups.set(specId, [...groups.get(specId) ?? [], id]);
|
|
4223
4393
|
}
|
|
@@ -4359,9 +4529,9 @@ function parsePorcelain(buffer, format) {
|
|
|
4359
4529
|
entries.sort((a, b) => Buffer.compare(Buffer.from(a.change.path), Buffer.from(b.change.path)));
|
|
4360
4530
|
return {
|
|
4361
4531
|
head,
|
|
4362
|
-
changes: entries.map((
|
|
4532
|
+
changes: entries.map((entry2) => entry2.change),
|
|
4363
4533
|
// Keep modes and object IDs: an unchanged count/XY is not an unchanged index.
|
|
4364
|
-
comparison: JSON.stringify([head, entries.map((
|
|
4534
|
+
comparison: JSON.stringify([head, entries.map((entry2) => entry2.raw)])
|
|
4365
4535
|
};
|
|
4366
4536
|
}
|
|
4367
4537
|
|
|
@@ -5406,8 +5576,8 @@ function numKeys(data) {
|
|
|
5406
5576
|
return keyCount;
|
|
5407
5577
|
}
|
|
5408
5578
|
var getParsedType = (data) => {
|
|
5409
|
-
const
|
|
5410
|
-
switch (
|
|
5579
|
+
const t3 = typeof data;
|
|
5580
|
+
switch (t3) {
|
|
5411
5581
|
case "undefined":
|
|
5412
5582
|
return "undefined";
|
|
5413
5583
|
case "string":
|
|
@@ -5446,7 +5616,7 @@ var getParsedType = (data) => {
|
|
|
5446
5616
|
}
|
|
5447
5617
|
return "object";
|
|
5448
5618
|
default:
|
|
5449
|
-
throw new Error(`Unknown data type: ${
|
|
5619
|
+
throw new Error(`Unknown data type: ${t3}`);
|
|
5450
5620
|
}
|
|
5451
5621
|
};
|
|
5452
5622
|
var propertyKeyTypes = /* @__PURE__ */ new Set(["string", "number", "symbol"]);
|
|
@@ -5734,8 +5904,8 @@ function getLengthableOrigin(input2) {
|
|
|
5734
5904
|
return "unknown";
|
|
5735
5905
|
}
|
|
5736
5906
|
function parsedType(data) {
|
|
5737
|
-
const
|
|
5738
|
-
switch (
|
|
5907
|
+
const t3 = typeof data;
|
|
5908
|
+
switch (t3) {
|
|
5739
5909
|
case "number": {
|
|
5740
5910
|
return Number.isNaN(data) ? "nan" : "number";
|
|
5741
5911
|
}
|
|
@@ -5752,7 +5922,7 @@ function parsedType(data) {
|
|
|
5752
5922
|
}
|
|
5753
5923
|
}
|
|
5754
5924
|
}
|
|
5755
|
-
return
|
|
5925
|
+
return t3;
|
|
5756
5926
|
}
|
|
5757
5927
|
function issue(...args) {
|
|
5758
5928
|
const [iss, input2, inst] = args;
|
|
@@ -7950,7 +8120,7 @@ function handleCatchall(proms, input2, payload, ctx, def, inst, abortEarly) {
|
|
|
7950
8120
|
const unrecognized = [];
|
|
7951
8121
|
const keySet = def.keySet;
|
|
7952
8122
|
const _catchall = def.catchall._zod;
|
|
7953
|
-
const
|
|
8123
|
+
const t3 = _catchall.def.type;
|
|
7954
8124
|
const optin = _catchall.optin;
|
|
7955
8125
|
const optout = _catchall.optout;
|
|
7956
8126
|
let seen = 0;
|
|
@@ -7963,11 +8133,11 @@ function handleCatchall(proms, input2, payload, ctx, def, inst, abortEarly) {
|
|
|
7963
8133
|
if (keySet.has(key))
|
|
7964
8134
|
continue;
|
|
7965
8135
|
if (key === "__proto__") {
|
|
7966
|
-
if (
|
|
8136
|
+
if (t3 === "never")
|
|
7967
8137
|
unrecognized.push(key);
|
|
7968
8138
|
continue;
|
|
7969
8139
|
}
|
|
7970
|
-
if (
|
|
8140
|
+
if (t3 === "never") {
|
|
7971
8141
|
unrecognized.push(key);
|
|
7972
8142
|
continue;
|
|
7973
8143
|
}
|
|
@@ -8533,7 +8703,7 @@ function handleIntersectionResults(result, left, right) {
|
|
|
8533
8703
|
}
|
|
8534
8704
|
var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
|
|
8535
8705
|
$ZodType.init(inst, def);
|
|
8536
|
-
const
|
|
8706
|
+
const items2 = def.items;
|
|
8537
8707
|
const memo2 = globalConfig.memoizer;
|
|
8538
8708
|
memo2?.attach(inst);
|
|
8539
8709
|
inst._zod.parse = (payload, ctx) => {
|
|
@@ -8549,8 +8719,8 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
|
|
|
8549
8719
|
}
|
|
8550
8720
|
payload.value = memo2 ? memo2.alloc(inst, payload, [], ctx) : [];
|
|
8551
8721
|
const proms = [];
|
|
8552
|
-
const optinStart = getTupleOptStart(
|
|
8553
|
-
const optoutStart = getTupleOptStart(
|
|
8722
|
+
const optinStart = getTupleOptStart(items2, "optin");
|
|
8723
|
+
const optoutStart = getTupleOptStart(items2, "optout");
|
|
8554
8724
|
if (!def.rest) {
|
|
8555
8725
|
if (input2.length < optinStart) {
|
|
8556
8726
|
payload.issues.push({
|
|
@@ -8563,10 +8733,10 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
|
|
|
8563
8733
|
});
|
|
8564
8734
|
return payload;
|
|
8565
8735
|
}
|
|
8566
|
-
if (input2.length >
|
|
8736
|
+
if (input2.length > items2.length) {
|
|
8567
8737
|
payload.issues.push({
|
|
8568
8738
|
code: "too_big",
|
|
8569
|
-
maximum:
|
|
8739
|
+
maximum: items2.length,
|
|
8570
8740
|
inclusive: true,
|
|
8571
8741
|
input: input2,
|
|
8572
8742
|
inst,
|
|
@@ -8574,11 +8744,11 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
|
|
|
8574
8744
|
});
|
|
8575
8745
|
}
|
|
8576
8746
|
}
|
|
8577
|
-
const itemResults = new Array(
|
|
8747
|
+
const itemResults = new Array(items2.length);
|
|
8578
8748
|
const abortEarly = def.rest ? ctx?.abortEarly : void 0;
|
|
8579
8749
|
let itemAborted = false;
|
|
8580
|
-
for (let i = 0; i <
|
|
8581
|
-
const r =
|
|
8750
|
+
for (let i = 0; i < items2.length; i++) {
|
|
8751
|
+
const r = items2[i]._zod.run({ value: input2[i], issues: [] }, ctx);
|
|
8582
8752
|
if (r instanceof Promise) {
|
|
8583
8753
|
proms.push(r.then((rr) => {
|
|
8584
8754
|
itemResults[i] = rr;
|
|
@@ -8590,8 +8760,8 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
|
|
|
8590
8760
|
}
|
|
8591
8761
|
}
|
|
8592
8762
|
if (def.rest && !itemAborted) {
|
|
8593
|
-
let i =
|
|
8594
|
-
const rest = input2.slice(
|
|
8763
|
+
let i = items2.length - 1;
|
|
8764
|
+
const rest = input2.slice(items2.length);
|
|
8595
8765
|
let seen = payload.issues.length;
|
|
8596
8766
|
for (const el of rest) {
|
|
8597
8767
|
if (abortEarly && payload.issues.length !== seen) {
|
|
@@ -8609,14 +8779,14 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
|
|
|
8609
8779
|
}
|
|
8610
8780
|
}
|
|
8611
8781
|
if (proms.length) {
|
|
8612
|
-
return Promise.all(proms).then(() => handleTupleResults(itemResults, payload,
|
|
8782
|
+
return Promise.all(proms).then(() => handleTupleResults(itemResults, payload, items2, input2, optoutStart));
|
|
8613
8783
|
}
|
|
8614
|
-
return handleTupleResults(itemResults, payload,
|
|
8784
|
+
return handleTupleResults(itemResults, payload, items2, input2, optoutStart);
|
|
8615
8785
|
};
|
|
8616
8786
|
});
|
|
8617
|
-
function getTupleOptStart(
|
|
8618
|
-
for (let i =
|
|
8619
|
-
const omittable = key === "optin" ?
|
|
8787
|
+
function getTupleOptStart(items2, key) {
|
|
8788
|
+
for (let i = items2.length - 1; i >= 0; i--) {
|
|
8789
|
+
const omittable = key === "optin" ? items2[i]._zod.optin !== void 0 : items2[i]._zod.optout === "optional";
|
|
8620
8790
|
if (!omittable)
|
|
8621
8791
|
return i + 1;
|
|
8622
8792
|
}
|
|
@@ -8628,11 +8798,11 @@ function handleTupleResult(result, final, index) {
|
|
|
8628
8798
|
}
|
|
8629
8799
|
final.value[index] = result.value;
|
|
8630
8800
|
}
|
|
8631
|
-
function handleTupleResults(itemResults, final,
|
|
8632
|
-
for (let i = 0; i <
|
|
8801
|
+
function handleTupleResults(itemResults, final, items2, input2, optoutStart) {
|
|
8802
|
+
for (let i = 0; i < items2.length; i++) {
|
|
8633
8803
|
const r = itemResults[i];
|
|
8634
8804
|
const isPresent = i < input2.length;
|
|
8635
|
-
if (!isPresent && i >= optoutStart &&
|
|
8805
|
+
if (!isPresent && i >= optoutStart && items2[i]._zod.optin === "optional") {
|
|
8636
8806
|
final.value.length = i;
|
|
8637
8807
|
break;
|
|
8638
8808
|
}
|
|
@@ -8646,7 +8816,7 @@ function handleTupleResults(itemResults, final, items, input2, optoutStart) {
|
|
|
8646
8816
|
final.value[i] = r.value;
|
|
8647
8817
|
}
|
|
8648
8818
|
for (let i = final.value.length - 1; i >= input2.length; i--) {
|
|
8649
|
-
if (
|
|
8819
|
+
if (items2[i]._zod.optout === "optional" && final.value[i] === void 0) {
|
|
8650
8820
|
final.value.length = i;
|
|
8651
8821
|
} else {
|
|
8652
8822
|
break;
|
|
@@ -9685,9 +9855,9 @@ var memo = {
|
|
|
9685
9855
|
if (!bucket)
|
|
9686
9856
|
return empty;
|
|
9687
9857
|
handoff = void 0;
|
|
9688
|
-
const
|
|
9689
|
-
bucket.set(payload.value,
|
|
9690
|
-
open.push(
|
|
9858
|
+
const entry2 = { value: empty, issues: null };
|
|
9859
|
+
bucket.set(payload.value, entry2);
|
|
9860
|
+
open.push(entry2);
|
|
9691
9861
|
return empty;
|
|
9692
9862
|
},
|
|
9693
9863
|
guard(inst) {
|
|
@@ -9761,16 +9931,16 @@ var memo = {
|
|
|
9761
9931
|
const depth = open.length;
|
|
9762
9932
|
const result = base(payload, ctx);
|
|
9763
9933
|
handoff = void 0;
|
|
9764
|
-
const
|
|
9934
|
+
const entry2 = open.length > depth ? open.pop() : void 0;
|
|
9765
9935
|
if (result instanceof Promise) {
|
|
9766
9936
|
return result.then((r) => {
|
|
9767
|
-
if (
|
|
9768
|
-
|
|
9937
|
+
if (entry2)
|
|
9938
|
+
entry2.issues = r.issues.length ? cloneIssues(r.issues) : NO_ISSUES;
|
|
9769
9939
|
return r;
|
|
9770
9940
|
});
|
|
9771
9941
|
}
|
|
9772
|
-
if (
|
|
9773
|
-
|
|
9942
|
+
if (entry2)
|
|
9943
|
+
entry2.issues = result.issues.length ? cloneIssues(result.issues) : NO_ISSUES;
|
|
9774
9944
|
return result;
|
|
9775
9945
|
};
|
|
9776
9946
|
inst._zod.parse = wrapped;
|
|
@@ -12201,16 +12371,16 @@ var error20 = () => {
|
|
|
12201
12371
|
number: { unit: "", shortLabel: "\u05E7\u05D8\u05DF", longLabel: "\u05D2\u05D3\u05D5\u05DC" }
|
|
12202
12372
|
// no unit
|
|
12203
12373
|
};
|
|
12204
|
-
const typeEntry = (
|
|
12205
|
-
const typeLabel = (
|
|
12206
|
-
const e = typeEntry(
|
|
12374
|
+
const typeEntry = (t3) => t3 ? TypeNames[t3] : void 0;
|
|
12375
|
+
const typeLabel = (t3) => {
|
|
12376
|
+
const e = typeEntry(t3);
|
|
12207
12377
|
if (e)
|
|
12208
12378
|
return e.label;
|
|
12209
|
-
return
|
|
12379
|
+
return t3 ?? TypeNames.unknown.label;
|
|
12210
12380
|
};
|
|
12211
|
-
const withDefinite = (
|
|
12212
|
-
const verbFor = (
|
|
12213
|
-
const e = typeEntry(
|
|
12381
|
+
const withDefinite = (t3) => `\u05D4${typeLabel(t3)}`;
|
|
12382
|
+
const verbFor = (t3) => {
|
|
12383
|
+
const e = typeEntry(t3);
|
|
12214
12384
|
const gender = e?.gender ?? "m";
|
|
12215
12385
|
return gender === "f" ? "\u05E6\u05E8\u05D9\u05DB\u05D4 \u05DC\u05D4\u05D9\u05D5\u05EA" : "\u05E6\u05E8\u05D9\u05DA \u05DC\u05D4\u05D9\u05D5\u05EA";
|
|
12216
12386
|
};
|
|
@@ -18554,20 +18724,20 @@ function generateNonOptionalCheck(doc, ctx, schema, accessor) {
|
|
|
18554
18724
|
}
|
|
18555
18725
|
function generateTupleCheck(doc, ctx, schema, accessor) {
|
|
18556
18726
|
const def = schema._zod.def;
|
|
18557
|
-
const
|
|
18727
|
+
const items2 = def.items;
|
|
18558
18728
|
const rest = def.rest;
|
|
18559
18729
|
doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
|
|
18560
|
-
const optinStart = getTupleOptStart2(
|
|
18561
|
-
const optoutStart = getTupleOptStart2(
|
|
18730
|
+
const optinStart = getTupleOptStart2(items2, "optin");
|
|
18731
|
+
const optoutStart = getTupleOptStart2(items2, "optout");
|
|
18562
18732
|
if (rest) {
|
|
18563
18733
|
doc.write(`if (${accessor}.length < ${optinStart}) return INVALID;`);
|
|
18564
18734
|
} else {
|
|
18565
|
-
doc.write(`if (${accessor}.length < ${optinStart} || ${accessor}.length > ${
|
|
18735
|
+
doc.write(`if (${accessor}.length < ${optinStart} || ${accessor}.length > ${items2.length}) return INVALID;`);
|
|
18566
18736
|
}
|
|
18567
18737
|
const outputVar = newVar(ctx);
|
|
18568
18738
|
doc.write(`const ${outputVar} = [];`);
|
|
18569
|
-
for (let i = 0; i <
|
|
18570
|
-
const itemSchema =
|
|
18739
|
+
for (let i = 0; i < items2.length; i++) {
|
|
18740
|
+
const itemSchema = items2[i];
|
|
18571
18741
|
if (i >= optoutStart) {
|
|
18572
18742
|
doc.write(`if (${outputVar}.length === ${i}) {`);
|
|
18573
18743
|
doc.indented((d) => {
|
|
@@ -18609,7 +18779,7 @@ function generateTupleCheck(doc, ctx, schema, accessor) {
|
|
|
18609
18779
|
if (rest) {
|
|
18610
18780
|
const iVar = newVar(ctx);
|
|
18611
18781
|
const elemVar = newVar(ctx);
|
|
18612
|
-
doc.write(`for (let ${iVar} = ${
|
|
18782
|
+
doc.write(`for (let ${iVar} = ${items2.length}; ${iVar} < ${accessor}.length; ${iVar}++) {`);
|
|
18613
18783
|
doc.indented((d) => {
|
|
18614
18784
|
d.write(`const ${elemVar} = ${accessor}[${iVar}];`);
|
|
18615
18785
|
const elemOutput = compileChild(d, ctx, rest, elemVar);
|
|
@@ -18619,9 +18789,9 @@ function generateTupleCheck(doc, ctx, schema, accessor) {
|
|
|
18619
18789
|
}
|
|
18620
18790
|
return outputVar;
|
|
18621
18791
|
}
|
|
18622
|
-
function getTupleOptStart2(
|
|
18623
|
-
for (let i =
|
|
18624
|
-
const omittable = key === "optin" ?
|
|
18792
|
+
function getTupleOptStart2(items2, key) {
|
|
18793
|
+
for (let i = items2.length - 1; i >= 0; i--) {
|
|
18794
|
+
const omittable = key === "optin" ? items2[i]._zod.optin !== void 0 : items2[i]._zod.optout === "optional";
|
|
18625
18795
|
if (!omittable)
|
|
18626
18796
|
return i + 1;
|
|
18627
18797
|
}
|
|
@@ -19755,13 +19925,13 @@ function _intersection(Class2, left, right) {
|
|
|
19755
19925
|
});
|
|
19756
19926
|
}
|
|
19757
19927
|
// @__NO_SIDE_EFFECTS__
|
|
19758
|
-
function _tuple(Class2,
|
|
19928
|
+
function _tuple(Class2, items2, _paramsOrRest, _params) {
|
|
19759
19929
|
const hasRest = _paramsOrRest instanceof $ZodType;
|
|
19760
19930
|
const params = hasRest ? _params : _paramsOrRest;
|
|
19761
19931
|
const rest = hasRest ? _paramsOrRest : null;
|
|
19762
19932
|
return new Class2({
|
|
19763
19933
|
type: "tuple",
|
|
19764
|
-
items,
|
|
19934
|
+
items: items2,
|
|
19765
19935
|
rest,
|
|
19766
19936
|
...normalizeParams(params)
|
|
19767
19937
|
});
|
|
@@ -20176,42 +20346,42 @@ function extractDefs(ctx, schema) {
|
|
|
20176
20346
|
if (ctx.external && ctx.sharedDefsExtractedFor === ctx.external)
|
|
20177
20347
|
return;
|
|
20178
20348
|
const idToSchema = /* @__PURE__ */ new Map();
|
|
20179
|
-
for (const
|
|
20180
|
-
const id = ctx.metadataRegistry.get(
|
|
20349
|
+
for (const entry2 of ctx.seen.entries()) {
|
|
20350
|
+
const id = ctx.metadataRegistry.get(entry2[0])?.id;
|
|
20181
20351
|
if (id) {
|
|
20182
20352
|
const existing = idToSchema.get(id);
|
|
20183
|
-
if (existing && existing !==
|
|
20353
|
+
if (existing && existing !== entry2[0]) {
|
|
20184
20354
|
throw new Error(`Duplicate schema id "${id}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
|
|
20185
20355
|
}
|
|
20186
|
-
idToSchema.set(id,
|
|
20356
|
+
idToSchema.set(id, entry2[0]);
|
|
20187
20357
|
}
|
|
20188
20358
|
}
|
|
20189
|
-
const makeURI = (
|
|
20359
|
+
const makeURI = (entry2) => {
|
|
20190
20360
|
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
|
20191
20361
|
if (ctx.external) {
|
|
20192
|
-
const externalId = ctx.external.registry.get(
|
|
20362
|
+
const externalId = ctx.external.registry.get(entry2[0])?.id;
|
|
20193
20363
|
const uriGenerator = ctx.external.uri ?? ((id2) => id2);
|
|
20194
20364
|
if (externalId) {
|
|
20195
20365
|
return { ref: uriGenerator(externalId) };
|
|
20196
20366
|
}
|
|
20197
|
-
const id =
|
|
20198
|
-
|
|
20367
|
+
const id = entry2[1].defId ?? entry2[1].schema.id ?? `schema${ctx.counter++}`;
|
|
20368
|
+
entry2[1].defId = id;
|
|
20199
20369
|
return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id)}` };
|
|
20200
20370
|
}
|
|
20201
20371
|
const uriPrefix = `#`;
|
|
20202
20372
|
const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
|
|
20203
|
-
if (
|
|
20373
|
+
if (entry2[1] === root && !entry2[1].schema.id) {
|
|
20204
20374
|
return { ref: uriPrefix };
|
|
20205
20375
|
}
|
|
20206
|
-
const defId =
|
|
20376
|
+
const defId = entry2[1].schema.id ?? `__schema${ctx.counter++}`;
|
|
20207
20377
|
return { defId, ref: defUriPrefix + encodeJSONPointerSegment(defId) };
|
|
20208
20378
|
};
|
|
20209
|
-
const extractToDef = (
|
|
20210
|
-
if (
|
|
20379
|
+
const extractToDef = (entry2) => {
|
|
20380
|
+
if (entry2[1].schema.$ref) {
|
|
20211
20381
|
return;
|
|
20212
20382
|
}
|
|
20213
|
-
const seen =
|
|
20214
|
-
const { ref, defId } = makeURI(
|
|
20383
|
+
const seen = entry2[1];
|
|
20384
|
+
const { ref, defId } = makeURI(entry2);
|
|
20215
20385
|
seen.def = { ...seen.schema };
|
|
20216
20386
|
if (defId)
|
|
20217
20387
|
seen.defId = defId;
|
|
@@ -20222,8 +20392,8 @@ function extractDefs(ctx, schema) {
|
|
|
20222
20392
|
schema2.$ref = ref;
|
|
20223
20393
|
};
|
|
20224
20394
|
if (ctx.cycles === "throw") {
|
|
20225
|
-
for (const
|
|
20226
|
-
const seen =
|
|
20395
|
+
for (const entry2 of ctx.seen.entries()) {
|
|
20396
|
+
const seen = entry2[1];
|
|
20227
20397
|
if (seen.cycle) {
|
|
20228
20398
|
throw new Error(`Cycle detected: #/${seen.cycle?.join("/")}/<root>
|
|
20229
20399
|
|
|
@@ -20231,31 +20401,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20231
20401
|
}
|
|
20232
20402
|
}
|
|
20233
20403
|
}
|
|
20234
|
-
for (const
|
|
20235
|
-
const seen =
|
|
20236
|
-
if (schema ===
|
|
20237
|
-
extractToDef(
|
|
20404
|
+
for (const entry2 of ctx.seen.entries()) {
|
|
20405
|
+
const seen = entry2[1];
|
|
20406
|
+
if (schema === entry2[0]) {
|
|
20407
|
+
extractToDef(entry2);
|
|
20238
20408
|
continue;
|
|
20239
20409
|
}
|
|
20240
20410
|
if (ctx.external) {
|
|
20241
|
-
const ext = ctx.external.registry.get(
|
|
20242
|
-
if (schema !==
|
|
20243
|
-
extractToDef(
|
|
20411
|
+
const ext = ctx.external.registry.get(entry2[0])?.id;
|
|
20412
|
+
if (schema !== entry2[0] && ext) {
|
|
20413
|
+
extractToDef(entry2);
|
|
20244
20414
|
continue;
|
|
20245
20415
|
}
|
|
20246
20416
|
}
|
|
20247
|
-
const id = ctx.metadataRegistry.get(
|
|
20417
|
+
const id = ctx.metadataRegistry.get(entry2[0])?.id;
|
|
20248
20418
|
if (id) {
|
|
20249
|
-
extractToDef(
|
|
20419
|
+
extractToDef(entry2);
|
|
20250
20420
|
continue;
|
|
20251
20421
|
}
|
|
20252
20422
|
if (seen.cycle) {
|
|
20253
|
-
extractToDef(
|
|
20423
|
+
extractToDef(entry2);
|
|
20254
20424
|
continue;
|
|
20255
20425
|
}
|
|
20256
20426
|
if (seen.count > 1) {
|
|
20257
20427
|
if (ctx.reused === "ref") {
|
|
20258
|
-
extractToDef(
|
|
20428
|
+
extractToDef(entry2);
|
|
20259
20429
|
}
|
|
20260
20430
|
}
|
|
20261
20431
|
}
|
|
@@ -20437,12 +20607,12 @@ function finalize(ctx, schema) {
|
|
|
20437
20607
|
});
|
|
20438
20608
|
};
|
|
20439
20609
|
if (!ctx.external || ctx.sharedEmitDoneFor !== ctx.external) {
|
|
20440
|
-
for (const
|
|
20441
|
-
flattenRef(
|
|
20610
|
+
for (const entry2 of [...ctx.seen.entries()].reverse()) {
|
|
20611
|
+
flattenRef(entry2[0]);
|
|
20442
20612
|
}
|
|
20443
20613
|
if (ctx.target !== "openapi-3.0") {
|
|
20444
|
-
for (const
|
|
20445
|
-
compactTypeUnion(
|
|
20614
|
+
for (const entry2 of ctx.seen.entries()) {
|
|
20615
|
+
compactTypeUnion(entry2[1].def ?? entry2[1].schema);
|
|
20446
20616
|
}
|
|
20447
20617
|
}
|
|
20448
20618
|
for (const rewrite of ctx.deferred)
|
|
@@ -20489,8 +20659,8 @@ function finalize(ctx, schema) {
|
|
|
20489
20659
|
delete result.id;
|
|
20490
20660
|
const defs = ctx.external?.defs ?? {};
|
|
20491
20661
|
if (!ctx.external || ctx.sharedEmitDoneFor !== ctx.external) {
|
|
20492
|
-
for (const
|
|
20493
|
-
const seen =
|
|
20662
|
+
for (const entry2 of ctx.seen.entries()) {
|
|
20663
|
+
const seen = entry2[1];
|
|
20494
20664
|
if (seen.def && seen.defId) {
|
|
20495
20665
|
if (seen.def.id === seen.defId)
|
|
20496
20666
|
delete seen.def.id;
|
|
@@ -21083,7 +21253,7 @@ function stringifyKeyNames(bySchema, json2, visited) {
|
|
|
21083
21253
|
json2 = { ...json2, [keyword]: mapped };
|
|
21084
21254
|
}
|
|
21085
21255
|
const types = Array.isArray(json2.type) ? json2.type : [json2.type];
|
|
21086
|
-
const numericType = !types.includes("string") && types.some((
|
|
21256
|
+
const numericType = !types.includes("string") && types.some((t3) => t3 === "number" || t3 === "integer");
|
|
21087
21257
|
const values = json2.enum ?? (json2.const !== void 0 ? [json2.const] : void 0);
|
|
21088
21258
|
if (!numericType && !values?.some((v) => typeof v === "number"))
|
|
21089
21259
|
return json2;
|
|
@@ -21102,9 +21272,9 @@ function stringifyKeyNames(bySchema, json2, visited) {
|
|
|
21102
21272
|
var pendingRecords = /* @__PURE__ */ new WeakMap();
|
|
21103
21273
|
function rewriteKeyNames(ctx) {
|
|
21104
21274
|
const bySchema = /* @__PURE__ */ new Map();
|
|
21105
|
-
for (const
|
|
21106
|
-
if (
|
|
21107
|
-
bySchema.set(
|
|
21275
|
+
for (const entry2 of ctx.seen.values()) {
|
|
21276
|
+
if (entry2.def && !bySchema.has(entry2.schema))
|
|
21277
|
+
bySchema.set(entry2.schema, entry2);
|
|
21108
21278
|
}
|
|
21109
21279
|
const rewrites = /* @__PURE__ */ new Map();
|
|
21110
21280
|
for (const record3 of pendingRecords.get(ctx) ?? []) {
|
|
@@ -21118,8 +21288,8 @@ function rewriteKeyNames(ctx) {
|
|
|
21118
21288
|
}
|
|
21119
21289
|
if (!rewrites.size)
|
|
21120
21290
|
return;
|
|
21121
|
-
for (const
|
|
21122
|
-
for (const carrier of [
|
|
21291
|
+
for (const entry2 of ctx.seen.values()) {
|
|
21292
|
+
for (const carrier of [entry2.schema, entry2.def]) {
|
|
21123
21293
|
const rewritten = carrier && rewrites.get(carrier.propertyNames);
|
|
21124
21294
|
if (rewritten)
|
|
21125
21295
|
carrier.propertyNames = rewritten;
|
|
@@ -21313,8 +21483,8 @@ function toJSONSchema(input2, params) {
|
|
|
21313
21483
|
const registry2 = input2;
|
|
21314
21484
|
const ctx2 = initializeContext({ ...params, processors: allProcessors });
|
|
21315
21485
|
const defs = {};
|
|
21316
|
-
for (const
|
|
21317
|
-
const [_, schema] =
|
|
21486
|
+
for (const entry2 of registry2._idmap.entries()) {
|
|
21487
|
+
const [_, schema] = entry2;
|
|
21318
21488
|
processSchema(schema, ctx2);
|
|
21319
21489
|
}
|
|
21320
21490
|
const schemas = {};
|
|
@@ -21324,8 +21494,8 @@ function toJSONSchema(input2, params) {
|
|
|
21324
21494
|
defs
|
|
21325
21495
|
};
|
|
21326
21496
|
ctx2.external = external;
|
|
21327
|
-
for (const
|
|
21328
|
-
const [key, schema] =
|
|
21497
|
+
for (const entry2 of registry2._idmap.entries()) {
|
|
21498
|
+
const [key, schema] = entry2;
|
|
21329
21499
|
extractDefs(ctx2, schema);
|
|
21330
21500
|
assignProp(schemas, key, finalize(ctx2, schema));
|
|
21331
21501
|
}
|
|
@@ -22659,13 +22829,13 @@ var ZodTuple = /* @__PURE__ */ $constructor("ZodTuple", (inst, def) => {
|
|
|
22659
22829
|
});
|
|
22660
22830
|
}
|
|
22661
22831
|
});
|
|
22662
|
-
function tuple(
|
|
22832
|
+
function tuple(items2, _paramsOrRest, _params) {
|
|
22663
22833
|
const hasRest = _paramsOrRest instanceof $ZodType;
|
|
22664
22834
|
const params = hasRest ? _params : _paramsOrRest;
|
|
22665
22835
|
const rest = hasRest ? _paramsOrRest : null;
|
|
22666
22836
|
return new ZodTuple({
|
|
22667
22837
|
type: "tuple",
|
|
22668
|
-
items,
|
|
22838
|
+
items: items2,
|
|
22669
22839
|
rest,
|
|
22670
22840
|
...util_exports.normalizeParams(params)
|
|
22671
22841
|
});
|
|
@@ -23306,8 +23476,8 @@ function detectVersion(schema, defaultTarget) {
|
|
|
23306
23476
|
}
|
|
23307
23477
|
return defaultTarget ?? "draft-2020-12";
|
|
23308
23478
|
}
|
|
23309
|
-
function applyMinItems(
|
|
23310
|
-
return
|
|
23479
|
+
function applyMinItems(items2, minItems) {
|
|
23480
|
+
return items2.map((item, index) => index < minItems ? item : item.optional());
|
|
23311
23481
|
}
|
|
23312
23482
|
function decodeJSONPointerSegment(segment) {
|
|
23313
23483
|
return segment.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
@@ -23461,13 +23631,13 @@ function plural(n) {
|
|
|
23461
23631
|
}
|
|
23462
23632
|
function checkArrayGuards(arraySchema, guards) {
|
|
23463
23633
|
const guard = z.transform((value) => value).check((payload) => {
|
|
23464
|
-
const
|
|
23465
|
-
if (!Array.isArray(
|
|
23634
|
+
const items2 = payload.value;
|
|
23635
|
+
if (!Array.isArray(items2))
|
|
23466
23636
|
return;
|
|
23467
23637
|
if (guards.uniqueItems === true) {
|
|
23468
23638
|
const firstSeen = /* @__PURE__ */ new Map();
|
|
23469
|
-
for (let i = 0; i <
|
|
23470
|
-
const key = canonicalKey(
|
|
23639
|
+
for (let i = 0; i < items2.length; i++) {
|
|
23640
|
+
const key = canonicalKey(items2[i], /* @__PURE__ */ new Set());
|
|
23471
23641
|
if (key === null)
|
|
23472
23642
|
continue;
|
|
23473
23643
|
const first = firstSeen.get(key);
|
|
@@ -23478,7 +23648,7 @@ function checkArrayGuards(arraySchema, guards) {
|
|
|
23478
23648
|
payload.issues.push({
|
|
23479
23649
|
code: "custom",
|
|
23480
23650
|
message: `Array items must be unique: element at index ${i} duplicates the one at index ${first}`,
|
|
23481
|
-
input:
|
|
23651
|
+
input: items2,
|
|
23482
23652
|
path: [i],
|
|
23483
23653
|
continue: true
|
|
23484
23654
|
});
|
|
@@ -23488,7 +23658,7 @@ function checkArrayGuards(arraySchema, guards) {
|
|
|
23488
23658
|
const minContains = guards.minContains ?? 1;
|
|
23489
23659
|
const ceiling = guards.maxContains !== void 0 ? guards.maxContains + 1 : Number.POSITIVE_INFINITY;
|
|
23490
23660
|
let matches = 0;
|
|
23491
|
-
for (const item of
|
|
23661
|
+
for (const item of items2) {
|
|
23492
23662
|
if (guards.containsSchema.safeParse(item).success && ++matches >= ceiling)
|
|
23493
23663
|
break;
|
|
23494
23664
|
}
|
|
@@ -23496,7 +23666,7 @@ function checkArrayGuards(arraySchema, guards) {
|
|
|
23496
23666
|
payload.issues.push({
|
|
23497
23667
|
code: "custom",
|
|
23498
23668
|
message: `Array must contain at least ${minContains} matching ${plural(minContains)}; found ${matches}`,
|
|
23499
|
-
input:
|
|
23669
|
+
input: items2,
|
|
23500
23670
|
continue: true
|
|
23501
23671
|
});
|
|
23502
23672
|
}
|
|
@@ -23504,7 +23674,7 @@ function checkArrayGuards(arraySchema, guards) {
|
|
|
23504
23674
|
payload.issues.push({
|
|
23505
23675
|
code: "custom",
|
|
23506
23676
|
message: `Array must contain at most ${guards.maxContains} matching ${plural(guards.maxContains)}`,
|
|
23507
|
-
input:
|
|
23677
|
+
input: items2,
|
|
23508
23678
|
continue: true
|
|
23509
23679
|
});
|
|
23510
23680
|
}
|
|
@@ -23586,8 +23756,8 @@ function convertBaseSchema(schema, ctx) {
|
|
|
23586
23756
|
}
|
|
23587
23757
|
const type = schema.type;
|
|
23588
23758
|
if (Array.isArray(type)) {
|
|
23589
|
-
const typeSchemas = type.map((
|
|
23590
|
-
const typeSchema = { ...schema, type:
|
|
23759
|
+
const typeSchemas = type.map((t3) => {
|
|
23760
|
+
const typeSchema = { ...schema, type: t3 };
|
|
23591
23761
|
return convertBaseSchema(typeSchema, ctx);
|
|
23592
23762
|
});
|
|
23593
23763
|
if (typeSchemas.length === 0) {
|
|
@@ -23790,12 +23960,12 @@ function convertBaseSchema(schema, ctx) {
|
|
|
23790
23960
|
}
|
|
23791
23961
|
case "array": {
|
|
23792
23962
|
const prefixItems = schema.prefixItems;
|
|
23793
|
-
const
|
|
23963
|
+
const items2 = schema.items;
|
|
23794
23964
|
if (prefixItems && Array.isArray(prefixItems)) {
|
|
23795
23965
|
const minItems = typeof schema.minItems === "number" ? schema.minItems : 0;
|
|
23796
23966
|
const tupleItems = prefixItems.map((item) => convertSchema(item, ctx));
|
|
23797
23967
|
const positionalItems = applyMinItems(tupleItems, minItems);
|
|
23798
|
-
const rest = !Array.isArray(
|
|
23968
|
+
const rest = !Array.isArray(items2) ? getTupleRest(items2, ctx) : void 0;
|
|
23799
23969
|
const tupleSchema = z.tuple(positionalItems);
|
|
23800
23970
|
zodSchema = rest ? tupleSchema.rest(rest) : tupleSchema;
|
|
23801
23971
|
if (typeof schema.minItems === "number") {
|
|
@@ -23804,9 +23974,9 @@ function convertBaseSchema(schema, ctx) {
|
|
|
23804
23974
|
if (typeof schema.maxItems === "number") {
|
|
23805
23975
|
zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
|
|
23806
23976
|
}
|
|
23807
|
-
} else if (Array.isArray(
|
|
23977
|
+
} else if (Array.isArray(items2)) {
|
|
23808
23978
|
const minItems = typeof schema.minItems === "number" ? schema.minItems : 0;
|
|
23809
|
-
const tupleItems =
|
|
23979
|
+
const tupleItems = items2.map((item) => convertSchema(item, ctx));
|
|
23810
23980
|
const positionalItems = applyMinItems(tupleItems, minItems);
|
|
23811
23981
|
const rest = getTupleRest(schema.additionalItems, ctx);
|
|
23812
23982
|
const tupleSchema = z.tuple(positionalItems);
|
|
@@ -23817,8 +23987,8 @@ function convertBaseSchema(schema, ctx) {
|
|
|
23817
23987
|
if (typeof schema.maxItems === "number") {
|
|
23818
23988
|
zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
|
|
23819
23989
|
}
|
|
23820
|
-
} else if (
|
|
23821
|
-
const element = convertSchema(
|
|
23990
|
+
} else if (items2 !== void 0) {
|
|
23991
|
+
const element = convertSchema(items2, ctx);
|
|
23822
23992
|
let arraySchema = z.array(element);
|
|
23823
23993
|
if (typeof schema.minItems === "number") {
|
|
23824
23994
|
arraySchema = arraySchema.min(schema.minItems);
|
|
@@ -24274,16 +24444,7 @@ var repositoryStatusFailureV1 = external_exports.strictObject({
|
|
|
24274
24444
|
});
|
|
24275
24445
|
var repositoryStatusV1 = external_exports.union([repositoryStatusSuccessV1, repositoryStatusFailureV1]);
|
|
24276
24446
|
|
|
24277
|
-
// ../../packages/contracts/dist/versions/browser-
|
|
24278
|
-
var browserSessionV1 = external_exports.strictObject({
|
|
24279
|
-
contract: external_exports.literal("browser-session"),
|
|
24280
|
-
version: external_exports.literal(1),
|
|
24281
|
-
sessionId: external_exports.uuid(),
|
|
24282
|
-
repository: external_exports.strictObject({
|
|
24283
|
-
key: external_exports.string().regex(/^repo:[0-9a-f]{64}$/),
|
|
24284
|
-
worktreeKey: external_exports.string().regex(/^worktree:[0-9a-f]{64}$/)
|
|
24285
|
-
})
|
|
24286
|
-
});
|
|
24447
|
+
// ../../packages/contracts/dist/versions/browser-http-error-v1.js
|
|
24287
24448
|
var browserHttpErrorV1 = external_exports.strictObject({
|
|
24288
24449
|
contract: external_exports.literal("browser-http-error"),
|
|
24289
24450
|
version: external_exports.literal(1),
|
|
@@ -24358,6 +24519,322 @@ var browserSpecsV1 = external_exports.strictObject({
|
|
|
24358
24519
|
boundary: external_exports.boolean()
|
|
24359
24520
|
});
|
|
24360
24521
|
|
|
24522
|
+
// ../../packages/contracts/dist/versions/changelog-v1.js
|
|
24523
|
+
var items = external_exports.array(external_exports.string().min(1));
|
|
24524
|
+
var entry = external_exports.strictObject({
|
|
24525
|
+
version: external_exports.string().regex(/^\d+\.\d+\.\d+$/),
|
|
24526
|
+
date: external_exports.iso.date(),
|
|
24527
|
+
added: items,
|
|
24528
|
+
changed: items,
|
|
24529
|
+
removed: items,
|
|
24530
|
+
fixed: items
|
|
24531
|
+
}).refine((value) => value.added.length + value.changed.length + value.removed.length + value.fixed.length > 0, "A version must list at least one change.");
|
|
24532
|
+
var changelogV1 = external_exports.strictObject({
|
|
24533
|
+
contract: external_exports.literal("changelog"),
|
|
24534
|
+
version: external_exports.literal(1),
|
|
24535
|
+
language: external_exports.string().regex(/^[a-z]{2}(?:-[A-Z]{2})?$/),
|
|
24536
|
+
fallback: external_exports.boolean(),
|
|
24537
|
+
entries: external_exports.array(entry)
|
|
24538
|
+
}).superRefine((value, context2) => {
|
|
24539
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24540
|
+
for (const [index, item] of value.entries.entries()) {
|
|
24541
|
+
if (seen.has(item.version))
|
|
24542
|
+
context2.addIssue({ code: "custom", path: ["entries", index, "version"], message: "Duplicate version." });
|
|
24543
|
+
seen.add(item.version);
|
|
24544
|
+
}
|
|
24545
|
+
});
|
|
24546
|
+
|
|
24547
|
+
// ../../packages/contracts/dist/versions/browser-session-v2.js
|
|
24548
|
+
var release = external_exports.string().regex(/^\d+\.\d+\.\d+$/);
|
|
24549
|
+
var updateStateV1 = external_exports.strictObject({
|
|
24550
|
+
status: external_exports.enum(["checking", "available", "up-to-date", "unavailable", "disabled"]),
|
|
24551
|
+
latestVersion: release.nullable()
|
|
24552
|
+
}).refine((value) => (value.status === "available" || value.status === "up-to-date") === (value.latestVersion !== null), "latestVersion is set exactly when the check produced a result.");
|
|
24553
|
+
var browserSessionV2 = external_exports.strictObject({
|
|
24554
|
+
contract: external_exports.literal("browser-session"),
|
|
24555
|
+
version: external_exports.literal(2),
|
|
24556
|
+
sessionId: external_exports.uuid(),
|
|
24557
|
+
repository: external_exports.strictObject({
|
|
24558
|
+
key: external_exports.string().regex(/^repo:[0-9a-f]{64}$/),
|
|
24559
|
+
worktreeKey: external_exports.string().regex(/^worktree:[0-9a-f]{64}$/)
|
|
24560
|
+
}),
|
|
24561
|
+
// The running CLI, the same value as `gitifact --version`. A development build may carry a pre-release suffix.
|
|
24562
|
+
cliVersion: external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/),
|
|
24563
|
+
update: updateStateV1
|
|
24564
|
+
});
|
|
24565
|
+
|
|
24566
|
+
// ../../packages/contracts/dist/versions/update-v1.js
|
|
24567
|
+
var updateV1 = external_exports.discriminatedUnion("ok", [
|
|
24568
|
+
external_exports.strictObject({
|
|
24569
|
+
contract: external_exports.literal("update"),
|
|
24570
|
+
version: external_exports.literal(1),
|
|
24571
|
+
ok: external_exports.literal(true),
|
|
24572
|
+
cliVersion: external_exports.string().min(1),
|
|
24573
|
+
update: updateStateV1,
|
|
24574
|
+
// Present only when a newer release exists. The command is for npm global installs; other installs differ.
|
|
24575
|
+
install: external_exports.strictObject({ npmGlobal: external_exports.string().min(1) }).nullable(),
|
|
24576
|
+
// refreshed: blocks whose version line differed were rewritten. current: every block already matched.
|
|
24577
|
+
// not-initialized: no .gitifact config here, so only the version check ran. no-block: no file carries a block.
|
|
24578
|
+
agentDocs: external_exports.strictObject({ state: external_exports.enum(["refreshed", "current", "not-initialized", "no-block"]), paths: external_exports.array(external_exports.string()) })
|
|
24579
|
+
}),
|
|
24580
|
+
external_exports.strictObject({ contract: external_exports.literal("update"), version: external_exports.literal(1), ok: external_exports.literal(false), error: external_exports.strictObject({ code: external_exports.string(), message: external_exports.string() }) })
|
|
24581
|
+
]);
|
|
24582
|
+
|
|
24583
|
+
// src/shared/i18n/ko/messages.json
|
|
24584
|
+
var messages_default2 = {
|
|
24585
|
+
"help.program": "\uD504\uB85C\uC81D\uD2B8\uC758 \uC694\uAD6C\uC0AC\uD56D\uACFC \uACB0\uC815 \uC774\uB825\uC744 Git\uC5D0 \uB0A8\uAE30\uB294 \uB3C4\uAD6C",
|
|
24586
|
+
"help.notYet": "\uC804\uCCB4 \uC774\uB825 \uAC80\uC0AC\uC640 GUI \uC694\uAD6C\uC0AC\uD56D \uD3B8\uC9D1\uC740 \uC544\uC9C1 \uC81C\uACF5\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24587
|
+
"help.status": "\uD604\uC7AC checkout\uC758 Git \uC0C1\uD0DC \uC870\uD68C (gitifact \uAC80\uC0AC \uBBF8\uC2E4\uD589)",
|
|
24588
|
+
"help.format": "\uCD9C\uB825 \uD615\uC2DD",
|
|
24589
|
+
"help.browser": "\uD604\uC7AC checkout\uC758 Git \uC0C1\uD0DC\uB97C \uB85C\uCEEC \uBE0C\uB77C\uC6B0\uC800\uB85C \uC870\uD68C",
|
|
24590
|
+
"help.browserPort": "\uC218\uC2E0 \uD3EC\uD2B8 (0\uC740 \uC790\uB3D9 \uC120\uD0DD)",
|
|
24591
|
+
"help.browserDev": "Vite \uAC1C\uBC1C \uC11C\uBC84 Origin \uD5C8\uC6A9",
|
|
24592
|
+
"help.init": "\uD504\uB85C\uC81D\uD2B8 \uC124\uC815\xB7\uAE30\uC900\uC120 \uC0DD\uC131\uACFC \uC5D0\uC774\uC804\uD2B8 \uC9C0\uCE68 \uD30C\uC77C\uC758 GITIFACT \uBE14\uB85D \uC124\uCE58 (\uC7AC\uC2E4\uD589 \uC2DC \uBE14\uB85D \uAC31\uC2E0)",
|
|
24593
|
+
"help.initDryRun": "\uD30C\uC77C\uC744 \uB9CC\uB4E4\uC9C0 \uC54A\uACE0 \uCD08\uAE30\uD654 \uACC4\uD68D \uD655\uC778",
|
|
24594
|
+
"help.initAgent": "\uC9C0\uCE68 \uD30C\uC77C \uB300\uC0C1 (\uAE30\uBCF8: \uAE30\uC874 \uD30C\uC77C \uC804\uBD80, \uC5C6\uC73C\uBA74 AGENTS.md)",
|
|
24595
|
+
"help.initRemoveAgents": "GITIFACT \uBE14\uB85D\uC744 \uC81C\uAC70",
|
|
24596
|
+
"help.initSkipAgents": "\uC9C0\uCE68 \uD30C\uC77C\uC744 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC74C",
|
|
24597
|
+
"help.docs": "\uC5D0\uC774\uC804\uD2B8\uC6A9 \uC791\uC5C5 \uC9C0\uCE68 \uCD9C\uB825 (\uC8FC\uC81C \uC5C6\uC774 \uC2E4\uD589\uD558\uBA74 \uBAA9\uB85D)",
|
|
24598
|
+
"help.docsTopic": "workflow, spec, design, product, commit \uC911 \uD558\uB098",
|
|
24599
|
+
"help.migrate": ".tryce \uC800\uC7A5\uC18C\uB97C .gitifact\uB85C \uC804\uD658 (\uACBD\uB85C\uC640 \uB9C8\uCEE4\uB9CC \uBC14\uAFB8\uACE0 ID\xB7\uC774\uC720\xB7\uC774\uB825\uC740 \uBCF4\uC874)",
|
|
24600
|
+
"help.migrateDryRun": "\uD30C\uC77C\uC744 \uBC14\uAFB8\uC9C0 \uC54A\uACE0 \uC804\uD658 \uACC4\uD68D \uD655\uC778",
|
|
24601
|
+
"help.spec": "Markdown \uBA85\uC138 \uC791\uC131\xB7\uC870\uD68C\xB7Git \uAE30\uB85D",
|
|
24602
|
+
"help.deprecated": "Deprecated: 0.6.0\uC5D0\uC11C \uC81C\uAC70 \uC608\uC815. spec commit\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
24603
|
+
"help.specCommit": "\uBCC0\uACBD \uC774\uC720 \uAE30\uB85D\uACFC \uAD00\uB828 \uD30C\uC77C \uCEE4\uBC0B\uC744 \uD55C \uBC88\uC5D0 \uC2E4\uD589",
|
|
24604
|
+
"help.specCommitFile": "reasons\xB7paths\xB7message\xB7authorization\uC744 \uB2F4\uC740 JSON \uD30C\uC77C",
|
|
24605
|
+
"help.specCommitDryRun": "\uD30C\uC77C\uC744 \uC4F0\uAC70\uB098 \uCEE4\uBC0B\uD558\uC9C0 \uC54A\uACE0 \uACB0\uACFC\uB9CC \uD655\uC778",
|
|
24606
|
+
"help.specCommitPlanFile": "\uCEE4\uBC0B \uC785\uB825 \uB610\uB294 \uACC4\uD68D JSON \uD30C\uC77C",
|
|
24607
|
+
"help.specPrepareFile": "expected\uC640 \uCD5C\uC885 reasons\uB97C \uB2F4\uC740 JSON \uD30C\uC77C",
|
|
24608
|
+
"help.specVerifyFile": "prepare\uC758 verification \uAC1D\uCCB4\uB97C \uB2F4\uC740 JSON \uD30C\uC77C",
|
|
24609
|
+
"help.specVerifyStaged": "index \uC6D0\uBB38\uB3C4 \uBE44\uAD50",
|
|
24610
|
+
"help.specSaveFile": "expected\uC640 operations\uB97C \uB2F4\uC740 UTF-8 JSON \uD30C\uC77C",
|
|
24611
|
+
"help.specReadRef": "\uC77D\uC744 \uCEE4\uBC0B",
|
|
24612
|
+
"help.specDiffFrom": "\uC774\uC804 \uCEE4\uBC0B",
|
|
24613
|
+
"help.specDiffTo": "\uC774\uD6C4 \uCEE4\uBC0B",
|
|
24614
|
+
"help.specChanges": "HEAD \uB300\uBE44 \uCD5C\uC885 \uBA85\uC138 \uCC28\uC774\uC640 \uBBF8\uCEE4\uBC0B \uC774\uC720 \uC870\uD68C",
|
|
24615
|
+
"help.specWorking": "\uD604\uC7AC \uBA85\uC138\xB7\uC81C\uD488\xB7\uC9C0\uCE68 \uC804\uCCB4\uC640 stamp \uC870\uD68C",
|
|
24616
|
+
"help.specSave": "\uC694\uAD6C\uC0AC\uD56D\xB7\uC124\uACC4\xB7\uBB38\uC11C \uC800\uC7A5",
|
|
24617
|
+
"help.specRead": "\uCEE4\uBC0B \uC2DC\uC810\uC758 \uBA85\uC138 \uC870\uD68C",
|
|
24618
|
+
"help.specDiff": "\uB450 \uCEE4\uBC0B \uC0AC\uC774\uC758 \uBA85\uC138 \uBCC0\uACBD \uC870\uD68C",
|
|
24619
|
+
"git.operationInProgress": "Git \uC791\uC5C5\uC774 \uC9C4\uD589 \uC911\uC785\uB2C8\uB2E4: {marker}",
|
|
24620
|
+
"git.resolveConflicts": "Git \uCDA9\uB3CC\uC744 \uBA3C\uC800 \uD574\uACB0\uD558\uC138\uC694.",
|
|
24621
|
+
"migrate.locked": "\uC7A0\uAE08 \uB610\uB294 \uBCF5\uAD6C \uC790\uB8CC\uAC00 \uC788\uC2B5\uB2C8\uB2E4: {path}",
|
|
24622
|
+
"migrate.alreadyMigrated": ".gitifact\uAC00 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4. .tryce\uAC00 \uB0A8\uC544 \uC788\uC73C\uBA74 \uB0B4\uC6A9\uC744 \uBE44\uAD50\uD55C \uB4A4 \uC9C1\uC811 \uC815\uB9AC\uD558\uC138\uC694.",
|
|
24623
|
+
"migrate.nothingToMigrate": ".tryce \uC800\uC7A5\uC18C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24624
|
+
"migrate.notDirectory": ".tryce\uB294 \uB9C1\uD06C\uAC00 \uC544\uB2CC \uC77C\uBC18 \uB514\uB809\uD130\uB9AC\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
24625
|
+
"migrate.noConfig": ".tryce/config.json\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24626
|
+
"migrate.legacyJson": "\uAD6C\uD615 JSON \uD615\uC2DD\uC740 \uC804\uD658\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uAE30\uB85D\uC744 \uBCF4\uC874\uD558\uACE0 \uBCC4\uB3C4 \uC808\uCC28\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24627
|
+
"migrate.extraEntries": ".tryce\uC5D0 config.json\xB7spec \uC678 \uD56D\uBAA9\uC774 \uC788\uC2B5\uB2C8\uB2E4. \uC815\uB9AC\uD55C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
24628
|
+
"migrate.notSpecFolder": "\uBA85\uC138 \uD3F4\uB354\uAC00 \uC544\uB2D9\uB2C8\uB2E4: {feature}",
|
|
24629
|
+
"migrate.unsupportedFile": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uBA85\uC138 \uD30C\uC77C\uC785\uB2C8\uB2E4: .tryce/spec/{feature}/{name}",
|
|
24630
|
+
"migrate.fileTooLarge": "\uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2C8\uAC70\uB098 1 MiB\uB97C \uB118\uC2B5\uB2C8\uB2E4: {name}",
|
|
24631
|
+
"migrate.nextCommit": "\uBCC0\uACBD\uC744 \uD655\uC778\uD55C \uB4A4 gitifact spec commit\uC73C\uB85C .tryce \uC0AD\uC81C\uC640 .gitifact \uCD94\uAC00\uB97C \uD568\uAED8 \uCEE4\uBC0B\uD558\uC138\uC694.",
|
|
24632
|
+
"migrate.nextLegacyJson": "\uAD6C\uD615 JSON \uBA85\uC138(tryce.json)\uB294 \uC77D\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB0B4\uC6A9\uC744 Markdown \uBA85\uC138\uB85C \uC62E\uAE34 \uB4A4 \uC0AD\uC81C\uB97C spec commit\uC5D0 \uC120\uD0DD\uD558\uC138\uC694.",
|
|
24633
|
+
"migrate.nextSkills": ".agents/skills/tryce-workflow\uC640 .claude \uBCF5\uC0AC\uBCF8\uC774 \uC788\uC73C\uBA74 \uC815\uB9AC\uD558\uACE0 gitifact init\uC744 \uB2E4\uC2DC \uC2E4\uD589\uD574 AGENTS.md \uB4F1\uC758 GITIFACT \uBE14\uB85D\uC744 \uAC31\uC2E0\uD558\uC138\uC694.",
|
|
24634
|
+
"migrate.nextRename": ".gitignore\xB7AGENTS.md\xB7CLAUDE.md\uC758 .tryce\xB7tryce-workflow \uC5B8\uAE09\uC744 \uC0C8 \uC774\uB984\uC73C\uB85C \uB9DE\uCD94\uC138\uC694.",
|
|
24635
|
+
"migrate.failed": "\uC804\uD658\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. .tryce\uC640 .gitifact\uC758 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24636
|
+
"preview.notInitialized": "\uBA3C\uC800 gitifact init\uC73C\uB85C \uCD08\uAE30\uD654\uD558\uC138\uC694.",
|
|
24637
|
+
"preview.legacyProject": "\uAE30\uC874 \uD504\uB85C\uC81D\uD2B8\uB294 \uBCC4\uB3C4 \uC804\uD658\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24638
|
+
"preview.inputFile": "\uC785\uB825\uC740 1 MiB \uC774\uD558\uC758 JSON \uD30C\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
24639
|
+
"preview.inputSize": "\uC785\uB825 \uD06C\uAE30\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24640
|
+
"preview.inputJson": "\uC785\uB825 \uD30C\uC77C\uC740 UTF-8 JSON\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
24641
|
+
"preview.failed": "\uAC80\uD1A0 \uBA85\uC138 \uC791\uC5C5\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24642
|
+
"initRepo.configIgnored": "\uC124\uC815\uC774 ignore \uADDC\uCE59\uC73C\uB85C \uC81C\uC678\uB429\uB2C8\uB2E4: {rule}",
|
|
24643
|
+
"initRepo.baselineMismatch": "\uAE30\uC900\uC120\uACFC \uD604\uC7AC \uC800\uC7A5\uC18C\uAC00 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24644
|
+
"initRepo.baselineUnverified": "\uAE30\uC900\uC120 \uCEE4\uBC0B\uC758 \uC874\uC7AC\uC640 \uC870\uC0C1 \uAD00\uACC4\uB97C \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uAE30\uC900\uC120\uC744 \uBCF4\uC874\uD558\uACE0 \uC774\uB825\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
24645
|
+
"commit.unknownField": "\uC54C \uC218 \uC5C6\uB294 \uCEE4\uBC0B \uC785\uB825 \uD544\uB4DC\uC785\uB2C8\uB2E4.",
|
|
24646
|
+
"commit.authorizationRequired": "\uC0AC\uC6A9\uC790 \uC694\uCCAD \uB610\uB294 \uBA85\uC2DC\uC801 \uC815\uCC45\uC5D0 \uB530\uB978 \uCEE4\uBC0B \uADFC\uAC70\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24647
|
+
"commit.trailerInMessage": "Gitifact \uD2B8\uB808\uC77C\uB7EC\uB294 requirements\uB85C \uC9C0\uC815\uD558\uC138\uC694.",
|
|
24648
|
+
"commit.invalidReferences": "\uC798\uBABB\uB41C \uC694\uAD6C\uC0AC\uD56D \uCC38\uC870\uC785\uB2C8\uB2E4.",
|
|
24649
|
+
"commit.busy": "\uC774\uC804 \uCEE4\uBC0B \uC791\uC5C5 \uB610\uB294 \uBCF5\uAD6C \uC790\uB8CC\uAC00 \uC788\uC2B5\uB2C8\uB2E4: {path}",
|
|
24650
|
+
"commit.selectPending": "\uBCC0\uACBD\uB41C \uBA85\uC138\uC640 \uC774\uC720\uB97C \uD568\uAED8 \uC120\uD0DD\uD558\uC138\uC694. \uBBF8\uC120\uD0DD \uBA85\uC138\uB97C \uC790\uB3D9 \uD3EC\uD568\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24651
|
+
"commit.unknownRequirement": "\uC2E4\uC81C \uC694\uAD6C\uC0AC\uD56D ID\uB9CC \uCC38\uC870\uD558\uC138\uC694.",
|
|
24652
|
+
"commit.unexpectedFiles": "\uBE48 \uCEE4\uBC0B \uB610\uB294 \uC120\uD0DD \uBC16 \uD30C\uC77C\uC774 \uAC10\uC9C0\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24653
|
+
"commit.filterChanged": "Git \uD544\uD130\uAC00 \uBA85\uC138\xB7\uC774\uC720 \uC6D0\uBB38\uC744 \uBCC0\uACBD\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24654
|
+
"commit.specsChangedPreparing": "\uCEE4\uBC0B \uC900\uBE44 \uC911 \uBA85\uC138 \uC9D1\uD569\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24655
|
+
"commit.integrationStarted": "Git \uD1B5\uD569 \uC791\uC5C5\uC774 \uC2DC\uC791\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24656
|
+
"commit.headChanged": "HEAD\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24657
|
+
"commit.resultAltered": "\uCEE4\uBC0B\uC740 \uC2E4\uD589\uB410\uC9C0\uB9CC \uD6C5\xB7\uB3D9\uC2DC \uC791\uC5C5\uC774 \uACB0\uACFC\uB97C \uBCC0\uACBD\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24658
|
+
"commit.indexChangedAfter": "\uCEE4\uBC0B \uD6C4 \uC6D0\uB798 index \uBCC0\uACBD\uC744 \uAC10\uC9C0\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24659
|
+
"commit.hookChangedStaging": "\uD6C5\uC774 \uCEE4\uBC0B \uD6C4 staging\uC744 \uBCC0\uACBD\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24660
|
+
"commit.expectedType": "expected\uB294 changes\uAC00 \uBC18\uD658\uD55C \uBB38\uC790\uC5F4\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
24661
|
+
"commit.existingStaging": "\uAE30\uC874 staging\uC744 \uBCF4\uC874\uD569\uB2C8\uB2E4. \uC120\uD0DD \uBC94\uC704\uB97C \uC815\uB9AC\uD55C \uD6C4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
24662
|
+
"commit.staleInput": "\uC785\uB825\uC774 \uC624\uB798\uB410\uC2B5\uB2C8\uB2E4. changes\uBD80\uD130 \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694.",
|
|
24663
|
+
"commit.newlinePath": "\uC904\uBC14\uAFC8\uC774 \uD3EC\uD568\uB41C \uBA85\uC138 \uACBD\uB85C\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24664
|
+
"commit.storedShape": "\uBA85\uC138 \uD30C\uC77C\uC758 Git \uC800\uC7A5 \uD615\uD0DC\uB97C \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24665
|
+
"commit.indexChanged": "\uC2E4\uD589 \uC911 index\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24666
|
+
"commit.fileChangedRunning": "\uC2E4\uD589 \uC911 \uD30C\uC77C\xB7\uC815\uCC45\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4: {path}",
|
|
24667
|
+
"commit.stagedUnreadable": "staging\uB41C \uBA85\uC138\xB7\uC774\uC720\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: {path}",
|
|
24668
|
+
"commit.fileChangedPreparing": "\uCEE4\uBC0B \uC900\uBE44 \uC911 \uD30C\uC77C\xB7\uC815\uCC45\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4: {path}",
|
|
24669
|
+
"commit.resultUnknown": "\uCEE4\uBC0B \uACB0\uACFC\uB97C \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24670
|
+
"commit.uncertain": "Git \uC2E4\uD589 \uACB0\uACFC\uB97C \uD655\uC778\uD574\uC57C \uD569\uB2C8\uB2E4. \uC7AC\uC2DC\uB3C4\uD558\uC9C0 \uB9D0\uACE0 HEAD\uC640 \uBCF5\uAD6C \uC790\uB8CC\uB97C \uD655\uC778\uD558\uC138\uC694: {path}",
|
|
24671
|
+
"commit.existingStagingPlan": "\uAE30\uC874 staging\uC744 \uBCF4\uC874\uD569\uB2C8\uB2E4. \uC120\uD0DD \uBC94\uC704\uB97C \uC815\uB9AC\uD55C \uD6C4 \uB2E4\uC2DC \uACC4\uD68D\uD558\uC138\uC694.",
|
|
24672
|
+
"commit.designUseSpecCommit": "\uC124\uACC4 \uBCC0\uACBD\uC740 spec commit\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
24673
|
+
"commit.indexChangedPlanning": "\uACC4\uD68D \uC911 index\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24674
|
+
"commit.planCorrupted": "\uCEE4\uBC0B \uACC4\uD68D\uC774 \uC190\uC0C1\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uACC4\uD68D\uD558\uC138\uC694.",
|
|
24675
|
+
"commit.planScope": "\uACC4\uD68D\uC758 \uC800\uC7A5\uC18C \uB610\uB294 \uD30C\uC77C \uBC94\uC704\uAC00 \uB2E4\uB985\uB2C8\uB2E4.",
|
|
24676
|
+
"commit.planStale": "\uACC4\uD68D \uC774\uD6C4 \uD30C\uC77C\xB7\uC815\uCC45\xB7index\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uACC4\uD68D\uD558\uC138\uC694.",
|
|
24677
|
+
"commit.indexChangedLocked": "\uC7A0\uAE08 \uC911 index\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24678
|
+
"store.legacyLock": "\uC774\uC804 Tryce \uC2E4\uD589\uC758 \uC7A0\uAE08 \uB610\uB294 \uBCF5\uAD6C \uC790\uB8CC\uAC00 \uC788\uC2B5\uB2C8\uB2E4: {path}",
|
|
24679
|
+
"store.storeNotDirectory": ".gitifact\uB294 \uC77C\uBC18 \uB514\uB809\uD130\uB9AC\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
24680
|
+
"store.migrateFirst": ".tryce \uC800\uC7A5\uC18C\uC785\uB2C8\uB2E4. gitifact migrate\uB85C .gitifact\uC5D0 \uC804\uD658\uD55C \uB4A4 \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
24681
|
+
"store.legacyProject": "\uAE30\uC874 \uD504\uB85C\uC81D\uD2B8 \uD615\uC2DD\uC740 \uBCC4\uB3C4 \uC804\uD658\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24682
|
+
"store.linkOrSpecial": "\uB9C1\uD06C\xB7\uD2B9\uC218 \uD30C\uC77C\uC740 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: {path}",
|
|
24683
|
+
"store.tooManyFiles": "\uBA85\uC138 \uD30C\uC77C \uC218 \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24684
|
+
"store.tooDeep": "\uC911\uCCA9 \uD3F4\uB354 \uAE4A\uC774 \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4: {path}",
|
|
24685
|
+
"store.legacyJson": "\uAE30\uC874 JSON \uD615\uC2DD\uC740 \uC804\uD658\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24686
|
+
"store.unsupportedPath": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uBA85\uC138 \uACBD\uB85C\uC785\uB2C8\uB2E4: {path}",
|
|
24687
|
+
"store.hardLinkOrSize": "\uD558\uB4DC \uB9C1\uD06C \uB610\uB294 1 MiB \uD55C\uB3C4\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24688
|
+
"store.sizeLimit": "\uBA85\uC138 \uD06C\uAE30 \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24689
|
+
"store.locked": "\uBA85\uC138 \uC800\uC7A5 \uC7A0\uAE08 \uB610\uB294 \uBCF5\uAD6C \uC790\uB8CC\uAC00 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
24690
|
+
"store.changedWhileReading": "\uC870\uD68C \uC911 \uBA85\uC138\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC77D\uC73C\uC138\uC694.",
|
|
24691
|
+
"store.lockedWhileReading": "\uC870\uD68C \uC911 \uC800\uC7A5 \uC7A0\uAE08\uC774 \uC0DD\uACBC\uC2B5\uB2C8\uB2E4.",
|
|
24692
|
+
"store.invalidInput": "\uC800\uC7A5 \uC785\uB825\uC774 \uC798\uBABB\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24693
|
+
"store.expectedOperations": "expected\uC640 operations\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24694
|
+
"store.notDirectory": "\uC77C\uBC18 \uB514\uB809\uD130\uB9AC\uAC00 \uC544\uB2D9\uB2C8\uB2E4: {path}",
|
|
24695
|
+
"store.staleExpected": "\uC77D\uC740 \uB4A4 \uBA85\uC138\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. working\uC73C\uB85C \uB2E4\uC2DC \uC77D\uC73C\uC138\uC694.",
|
|
24696
|
+
"store.unsupportedSavePath": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC800\uC7A5 \uACBD\uB85C\uC785\uB2C8\uB2E4.",
|
|
24697
|
+
"store.fileSizeLimit": "\uBA85\uC138 1 MiB \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24698
|
+
"store.totalLimit": "\uBA85\uC138 \uC804\uCCB4 \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24699
|
+
"store.changedPreparing": "\uC800\uC7A5 \uC900\uBE44 \uC911 \uBA85\uC138\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24700
|
+
"store.changedBeforeWrite": "\uC800\uC7A5 \uC9C1\uC804 \uD30C\uC77C\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24701
|
+
"store.changedWhileWriting": "\uC800\uC7A5 \uC911 \uBA85\uC138 \uB610\uB294 \uC124\uC815\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24702
|
+
"store.recoveryIncomplete": "\uC790\uB3D9 \uBCF5\uAD6C\uB97C \uC644\uB8CC\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uB978 \uD3B8\uC9D1\uC744 \uBCF4\uC874\uD588\uC2B5\uB2C8\uB2E4. \uBCF5\uAD6C \uC790\uB8CC: {path}",
|
|
24703
|
+
"server.closing": "\uC11C\uBC84\uB97C \uC885\uB8CC\uD558\uACE0 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
24704
|
+
"server.forbiddenHost": "\uD5C8\uC6A9\uD558\uC9C0 \uC54A\uB294 Host\uC785\uB2C8\uB2E4.",
|
|
24705
|
+
"server.forbiddenOrigin": "\uD5C8\uC6A9\uD558\uC9C0 \uC54A\uB294 Origin\uC785\uB2C8\uB2E4.",
|
|
24706
|
+
"server.badPath": "\uC798\uBABB\uB41C \uACBD\uB85C\uC785\uB2C8\uB2E4.",
|
|
24707
|
+
"server.noBody": "\uC694\uCCAD \uBCF8\uBB38\uC744 \uBC1B\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24708
|
+
"server.crossSite": "\uC678\uBD80 \uD398\uC774\uC9C0\uC758 \uC694\uCCAD\uC744 \uD5C8\uC6A9\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24709
|
+
"server.noQuery": "\uC870\uD68C \uC778\uC790\uB97C \uBC1B\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24710
|
+
"server.methodNotAllowed": "\uD5C8\uC6A9\uD558\uC9C0 \uC54A\uB294 \uBA54\uC11C\uB4DC\uC785\uB2C8\uB2E4.",
|
|
24711
|
+
"server.productImageNotFound": "\uC81C\uD488 \uC774\uBBF8\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24712
|
+
"server.apiNotFound": "API\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24713
|
+
"server.sessionChanged": "\uC11C\uBC84 \uC138\uC158\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC5F0\uACB0\uD558\uC138\uC694.",
|
|
24714
|
+
"server.badRange": "\uC870\uD68C \uBC94\uC704\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24715
|
+
"server.specsUnreadable": "\uBA85\uC138\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24716
|
+
"server.refreshOrigin": "\uC0C8\uB85C\uACE0\uCE68\uC5D0\uB294 \uAC19\uC740 \uCD9C\uCC98\uC758 Origin\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24717
|
+
"server.fileNotFound": "\uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24718
|
+
"server.internal": "\uC694\uCCAD\uC744 \uCC98\uB9AC\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24719
|
+
"server.portInUse": "\uC694\uCCAD\uD55C \uD3EC\uD2B8\uAC00 \uC0AC\uC6A9 \uC911\uC785\uB2C8\uB2E4. \uB2E4\uB978 \uD3EC\uD2B8\uB97C \uC120\uD0DD\uD558\uC138\uC694.",
|
|
24720
|
+
"server.addressUnknown": "\uC11C\uBC84 \uC8FC\uC18C\uB97C \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24721
|
+
"reader.gitContextOverride": "Git \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uB36E\uC5B4\uC4F0\uB294 \uD658\uACBD\uC5D0\uC11C\uB294 \uC870\uD68C\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24722
|
+
"reader.notUtf8": "UTF-8 \uC6D0\uBB38\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
24723
|
+
"reader.invalidIndexEntry": "\uC798\uBABB\uB41C index \uD56D\uBAA9\uC785\uB2C8\uB2E4.",
|
|
24724
|
+
"reader.stagingConflictOrLink": "\uBA85\uC138 staging\uC5D0 \uCDA9\uB3CC \uB610\uB294 \uB9C1\uD06C\uAC00 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
24725
|
+
"reader.stagingUnsupported": "\uBA85\uC138 staging\uC5D0 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD30C\uC77C\uC774 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
24726
|
+
"reader.headUnknown": "HEAD\uB97C \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24727
|
+
"reader.damagedHead": "\uC190\uC0C1\uB41C HEAD\uB97C \uBE48 \uC800\uC7A5\uC18C\uB85C \uCC98\uB9AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24728
|
+
"reader.objectFormat": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 Git \uAC1D\uCCB4 \uD615\uC2DD\uC785\uB2C8\uB2E4.",
|
|
24729
|
+
"reader.commitUnknown": "\uCEE4\uBC0B\uC744 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24730
|
+
"reader.invalidTree": "\uC798\uBABB\uB41C Git tree\uC785\uB2C8\uB2E4.",
|
|
24731
|
+
"reader.linkOrSubmodule": "\uBA85\uC138 \uC601\uC5ED\uC5D0 \uB9C1\uD06C \uB610\uB294 \uC11C\uBE0C\uBAA8\uB4C8\uC774 \uC788\uC2B5\uB2C8\uB2E4: {path}",
|
|
24732
|
+
"reader.legacyJson": "\uAE30\uC874 JSON \uD615\uC2DD\uC740 req \uBA85\uB839\uC73C\uB85C \uC870\uD68C\uD558\uC138\uC694. \uC774 \uBA85\uB839\uC740 \uC804\uD658\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24733
|
+
"reader.unsupportedEntry": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uACBD\uB85C \uB610\uB294 \uD30C\uC77C \uC885\uB958: {path}",
|
|
24734
|
+
"reader.mixedStores": "\uACFC\uAC70 \uCEE4\uBC0B\uC5D0 .gitifact\uC640 .tryce \uBA85\uC138\uAC00 \uD568\uAED8 \uC788\uC2B5\uB2C8\uB2E4. \uC804\uD658 \uCEE4\uBC0B\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
24735
|
+
"reader.mixedFormats": "\uACFC\uAC70 \uCEE4\uBC0B\uC5D0 \uC2E0\uAD6C \uBA85\uC138\uAC00 \uD63C\uD569\uB3FC \uC788\uC2B5\uB2C8\uB2E4.",
|
|
24736
|
+
"reader.fileLimit": "\uAC80\uD1A0 \uC870\uD68C \uD30C\uC77C \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24737
|
+
"reader.blobShape": "\uAC80\uD1A0 \uC870\uD68C blob \uD615\uC2DD \uB610\uB294 1 MiB \uD55C\uB3C4\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24738
|
+
"reader.totalLimit": "\uBA85\uC138 \uC804\uCCB4 \uC870\uD68C 16 MiB \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24739
|
+
"reader.blobBoundary": "Git blob \uC751\uB2F5 \uACBD\uACC4\uAC00 \uB2E4\uB985\uB2C8\uB2E4.",
|
|
24740
|
+
"prepare.integrationInProgress": "Git \uD1B5\uD569 \uC791\uC5C5 \uC911\uC5D0\uB294 \uC2E4\uD5D8\uC6A9 \uCEE4\uBC0B \uC900\uBE44\uB97C \uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24741
|
+
"prepare.headChanged": "HEAD \uB610\uB294 \uBE0C\uB79C\uCE58\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. changes\uBD80\uD130 \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694.",
|
|
24742
|
+
"prepare.invalidInput": "\uC798\uBABB\uB41C \uC900\uBE44 \uC785\uB825\uC785\uB2C8\uB2E4.",
|
|
24743
|
+
"prepare.expectedReasons": "expected\uC640 reasons\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24744
|
+
"prepare.staleInput": "\uC900\uBE44 \uC785\uB825\uC774 \uC624\uB798\uB410\uC2B5\uB2C8\uB2E4. changes\uBD80\uD130 \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694.",
|
|
24745
|
+
"prepare.invalidVerifyInput": "\uC798\uBABB\uB41C \uD655\uC778 \uC785\uB825\uC785\uB2C8\uB2E4.",
|
|
24746
|
+
"prepare.verificationRequired": "prepare\uAC00 \uBC18\uD658\uD55C verification \uAC1D\uCCB4\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24747
|
+
"prepare.changedAfterPrepare": "\uC900\uBE44 \uB4A4 HEAD \uB610\uB294 \uBA85\uC138\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC900\uBE44\uD558\uC138\uC694.",
|
|
24748
|
+
"prepare.stagingScope": "staging\uC758 \uBA85\uC138 \uBC94\uC704\uAC00 \uC900\uBE44\uD55C \uC6D0\uBB38\uACFC \uB2E4\uB985\uB2C8\uB2E4.",
|
|
24749
|
+
"prepare.stagingContent": "staging \uC6D0\uBB38\uC774 \uC900\uBE44\uD55C \uD30C\uC77C\uACFC \uB2E4\uB985\uB2C8\uB2E4: {path}",
|
|
24750
|
+
"prepare.stagingChanged": "\uD655\uC778 \uC911 staging\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24751
|
+
"prepare.specsChanged": "\uD655\uC778 \uC911 \uBA85\uC138\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24752
|
+
"commitFiles.relativePath": "\uC800\uC7A5\uC18C \uC0C1\uB300 \uACBD\uB85C\uC758 \uBA85\uC138 \uB610\uB294 \uC77C\uBC18 \uD30C\uC77C\uB9CC \uC120\uD0DD\uD558\uC138\uC694.",
|
|
24753
|
+
"commitFiles.linkOrDirectory": "\uB9C1\uD06C\xB7\uB514\uB809\uD130\uB9AC\xB7\uD2B9\uC218 \uD30C\uC77C\uC740 \uC120\uD0DD\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24754
|
+
"commitFiles.nestedRepository": "\uC911\uCCA9 \uC800\uC7A5\uC18C\uB294 \uC120\uD0DD\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24755
|
+
"commitFiles.hardLinkOrSize": "\uD558\uB4DC \uB9C1\uD06C \uB610\uB294 \uD30C\uC77C \uD06C\uAE30 \uD55C\uB3C4\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24756
|
+
"commitFiles.invalidInput": "\uC798\uBABB\uB41C \uCEE4\uBC0B \uC785\uB825\uC785\uB2C8\uB2E4.",
|
|
24757
|
+
"commitFiles.emptyOrTooLong": "\uBE48 \uBB38\uC790\uC5F4 \uB610\uB294 \uC785\uB825 \uD55C\uB3C4 \uCD08\uACFC\uC785\uB2C8\uB2E4.",
|
|
24758
|
+
"commitFiles.invalidPaths": "\uD30C\uC77C \uBAA9\uB85D \uAC1C\uC218 \uB610\uB294 \uD615\uC2DD\uC774 \uC798\uBABB\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24759
|
+
"commitFiles.legacyDeleteOnly": ".gitifact\uC758 \uAD6C\uD615 \uAE30\uB85D\uC740 \uC0AD\uC81C\uB9CC \uC120\uD0DD\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4: {path}",
|
|
24760
|
+
"commitFiles.tryceDeleteOnly": ".tryce\uC758 \uC774\uC804 \uAE30\uB85D\uC740 \uC804\uD658 \uC2DC \uC0AD\uC81C\uB9CC \uC120\uD0DD\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4: {path}",
|
|
24761
|
+
"init.migrationRequired": "\uAE30\uC874 \uD615\uC2DD\uC740 \uBCC4\uB3C4 \uC804\uD658\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC124\uC815\uACFC \uAE30\uB85D\uC744 \uBCF4\uC874\uD558\uC138\uC694.",
|
|
24762
|
+
"init.inputChanged": "\uCD08\uAE30\uD654 \uC870\uD68C \uC911 \uC785\uB825\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24763
|
+
"init.configDeleted": "\uAE30\uC874 \uC124\uC815\uC758 \uC0AD\uC81C\uB97C \uC2E0\uADDC \uB3C4\uC785\uC73C\uB85C \uCC98\uB9AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24764
|
+
"init.existingSpecs": "\uAE30\uC874 specs \uACBD\uB85C\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24765
|
+
"init.orphanStore": "\uC124\uC815 \uC5C6\uB294 .gitifact \uC790\uB8CC\uB97C \uC790\uB3D9 \uCC44\uD0DD\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
24766
|
+
"init.headOrIndexChanged": "HEAD \uB610\uB294 index\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24767
|
+
"init.configAppeared": "\uB2E4\uB978 \uC2E4\uD589\uC774 \uC124\uC815\uC744 \uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4.",
|
|
24768
|
+
"init.changedAfterWrite": "\uC124\uC815 \uC0DD\uC131 \uD6C4 \uC785\uB825\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uD604\uC7AC \uD30C\uC77C\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
24769
|
+
"init.text.skipped": "\uAC74\uB108\uB700",
|
|
24770
|
+
"init.text.blockRemoved": "\uBE14\uB85D \uC81C\uAC70",
|
|
24771
|
+
"init.text.blockPlanned": "\uBE14\uB85D \uC124\uCE58 \uC608\uC815",
|
|
24772
|
+
"init.text.blockUpdated": "\uBE14\uB85D \uAC31\uC2E0",
|
|
24773
|
+
"init.text.storage": "\uC800\uC7A5 \uADDC\uC57D",
|
|
24774
|
+
"init.text.agentDocs": "\uC5D0\uC774\uC804\uD2B8 \uC9C0\uCE68",
|
|
24775
|
+
"init.failed": "\uCD08\uAE30\uD654\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uD30C\uC77C \uC811\uADFC \uAD8C\uD55C\uACFC \uC0DD\uC131\uB41C \uC124\uC815\xB7\uC784\uC2DC \uD30C\uC77C\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
24776
|
+
"config.storeNotDirectory": ".gitifact\uB294 \uB9C1\uD06C\uAC00 \uC544\uB2CC \uC77C\uBC18 \uB514\uB809\uD130\uB9AC\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
24777
|
+
"config.migrateFirst": ".tryce \uC800\uC7A5\uC18C\uC785\uB2C8\uB2E4. gitifact migrate\uB85C .gitifact\uC5D0 \uC804\uD658\uD558\uC138\uC694.",
|
|
24778
|
+
"config.fileShape": "config.json\uC740 64 KiB \uC774\uD558\uC758 \uC77C\uBC18 \uD30C\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
24779
|
+
"config.changedWhileReading": "\uC124\uC815 \uD30C\uC77C\uC774 \uC870\uD68C \uC911 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
24780
|
+
"config.notUtf8Json": "\uC124\uC815\uC740 UTF-8 JSON\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
24781
|
+
"config.directoryChanged": "\uC124\uC815 \uB514\uB809\uD130\uB9AC\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uC784\uC2DC \uD30C\uC77C\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
24782
|
+
"config.temporaryChanged": "\uC784\uC2DC \uC124\uC815\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
|
|
24783
|
+
"managedFile.notRegularPath": "\uC77C\uBC18 \uACBD\uB85C\uAC00 \uC544\uB2D9\uB2C8\uB2E4: {path}",
|
|
24784
|
+
"managedFile.tooLarge": "{kib} KiB\uB97C \uCD08\uACFC\uD569\uB2C8\uB2E4: {path}",
|
|
24785
|
+
"managedFile.changedWhileReading": "\uC870\uD68C \uC911 \uD30C\uC77C\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4: {path}",
|
|
24786
|
+
"managedFile.notUtf8": "UTF-8 \uD30C\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: {path}",
|
|
24787
|
+
"managedFile.targetChanged": "\uB300\uC0C1 \uACBD\uB85C\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4: {path}",
|
|
24788
|
+
"managedFile.removeTargetChanged": "\uC81C\uAC70 \uB300\uC0C1\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4: {path}",
|
|
24789
|
+
"managedFile.publishTargetChanged": "\uAC8C\uC2DC \uB300\uC0C1\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4: {path}",
|
|
24790
|
+
"agentBlock.endWithoutStart": "\uC2DC\uC791 \uB9C8\uCEE4 \uC5C6\uC774 \uC885\uB8CC \uB9C8\uCEE4\uB9CC \uC788\uC2B5\uB2C8\uB2E4. \uBE14\uB85D\uC744 \uC815\uB9AC\uD55C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
24791
|
+
"agentBlock.startWithoutEnd": "\uC885\uB8CC \uB9C8\uCEE4\uAC00 \uC5C6\uB294 GITIFACT \uBE14\uB85D\uC774 \uC788\uC2B5\uB2C8\uB2E4. \uBE14\uB85D\uC744 \uC815\uB9AC\uD55C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
24792
|
+
"agentBlock.duplicateStart": "GITIFACT \uC2DC\uC791 \uB9C8\uCEE4\uAC00 \uC5EC\uB7EC \uAC1C\uC785\uB2C8\uB2E4. \uC911\uBCF5 \uBE14\uB85D\uC744 \uC815\uB9AC\uD55C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
24793
|
+
"specReader.headUnreadable": "HEAD\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24794
|
+
"specReader.schemaRequired": "\uC0C8 \uC2A4\uD0A4\uB9C8 \uD504\uB85C\uC81D\uD2B8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24795
|
+
"specReader.historyChanged": "\uC774\uB825\uC774 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uC0C8\uB85C\uACE0\uCE68 \uD6C4 \uB2E4\uC2DC \uC870\uD68C\uD558\uC138\uC694.",
|
|
24796
|
+
"specReader.authorUnreadable": "Git \uC791\uC131\uC790\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24797
|
+
"specReader.historyUnreadable": "Git \uC774\uB825 \uD615\uC2DD\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24798
|
+
"specReader.projectChanged": "\uC870\uD68C \uC911 \uD504\uB85C\uC81D\uD2B8\uAC00 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uC0C8\uB85C\uACE0\uCE68\uD558\uC138\uC694.",
|
|
24799
|
+
"docs.unknownTopic": "\uC54C \uC218 \uC5C6\uB294 \uC8FC\uC81C\uC785\uB2C8\uB2E4: {topic}. \uC0AC\uC6A9 \uAC00\uB2A5: {topics}",
|
|
24800
|
+
"status.text.repository": "\uC800\uC7A5\uC18C: {path}",
|
|
24801
|
+
"status.text.changes": "Git \uBCC0\uACBD \uACBD\uB85C {count}\uAC1C, gitifact \uAC80\uC0AC \uBBF8\uC2E4\uD589",
|
|
24802
|
+
"status.text.observed": "\uAD00\uCE21: {at} (best-effort, \uD30C\uC77C \uB0B4\uC6A9 \uC2A4\uB0C5\uC0F7 \uC544\uB2D8)",
|
|
24803
|
+
"browser.invalidPort": "\uD3EC\uD2B8\uB294 0\uBD80\uD130 65535 \uC0AC\uC774\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
24804
|
+
"browser.failed": "\uBE0C\uB77C\uC6B0\uC800 \uC11C\uBC84\uB97C \uC2E4\uD589\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24805
|
+
"browser.assetSymlink": "\uBE0C\uB77C\uC6B0\uC800 \uC790\uC0B0\uC5D0 symlink\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24806
|
+
"browser.assetsUnreadable": "\uBE0C\uB77C\uC6B0\uC800 \uBE4C\uB4DC \uC790\uC0B0\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. pnpm build\uB85C \uB2E4\uC2DC \uBE4C\uB4DC\uD558\uC138\uC694.",
|
|
24807
|
+
"docs.summary.workflow": "\uC2DC\uC791 \uC2DC \uD655\uC778\uD560 \uAC83, \uC694\uAD6C\uC0AC\uD56D\uC73C\uB85C \uB0A8\uAE38 \uC694\uCCAD\uC758 \uAD6C\uBD84, \uB9C8\uBB34\uB9AC \uBCF4\uACE0",
|
|
24808
|
+
"docs.summary.spec": "\uC0AC\uC6A9\uC790 \uC2A4\uD1A0\uB9AC\xB7\uC218\uC6A9 \uC870\uAC74 \uD615\uC2DD, ID \uADDC\uCE59, spec save \uC785\uB825",
|
|
24809
|
+
"docs.summary.design": "design.md \uBAA9\uCC28, \uCC38\uC870 \uC8FC\uC11D, \uAC1C\uC815 \uBC29\uC2DD",
|
|
24810
|
+
"docs.summary.product": "PRODUCT.md\uC640 guides \uBB38\uC11C\uC758 \uC5ED\uD560\uACFC \uC800\uC7A5 \uBA85\uB839",
|
|
24811
|
+
"docs.summary.commit": "spec commit \uC785\uB825, \uC774\uC720 \uAE30\uB85D, \uC2E4\uD328 \uD6C4 \uBCF5\uAD6C",
|
|
24812
|
+
"help.browserNoUpdateCheck": "\uC0C8 \uBC84\uC804 \uD655\uC778\uC744 \uC704\uD55C npm \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uC870\uD68C\uB97C \uB054 (GITIFACT_NO_UPDATE_CHECK\uC640 \uAC19\uC74C)",
|
|
24813
|
+
"help.update": "\uC0C8 \uBC84\uC804 \uD655\uC778\uACFC \uC124\uCE58 \uBC29\uBC95 \uC548\uB0B4, \uD504\uB85C\uC81D\uD2B8 \uC9C0\uCE68 \uD30C\uC77C\uC758 GITIFACT \uBE14\uB85D\uC744 \uD604\uC7AC \uBC84\uC804\uC73C\uB85C \uAC31\uC2E0",
|
|
24814
|
+
"server.badLanguage": "\uC5B8\uC5B4 \uCF54\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24815
|
+
"server.changelogNotFound": "\uD328\uCE58\uB178\uD2B8\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24816
|
+
"server.changelogUnreadable": "\uD328\uCE58\uB178\uD2B8\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24817
|
+
"update.text.current": "\uD604\uC7AC \uBC84\uC804: {version}",
|
|
24818
|
+
"update.text.available": "\uC0C8 \uBC84\uC804: {version}",
|
|
24819
|
+
"update.text.upToDate": "\uCD5C\uC2E0 \uBC84\uC804\uC744 \uC0AC\uC6A9 \uC911\uC785\uB2C8\uB2E4.",
|
|
24820
|
+
"update.text.disabled": "\uC0C8 \uBC84\uC804 \uD655\uC778\uC774 \uAEBC\uC838 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
24821
|
+
"update.text.unavailable": "\uC0C8 \uBC84\uC804\uC744 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uB124\uD2B8\uC6CC\uD06C \uC5F0\uACB0\uC744 \uD655\uC778\uD558\uC138\uC694.",
|
|
24822
|
+
"update.text.install": "npm \uC804\uC5ED \uC124\uCE58\uC6A9: {command}",
|
|
24823
|
+
"update.text.afterInstall": "\uC124\uCE58\uD55C \uB4A4 gitifact update\uB97C \uB2E4\uC2DC \uC2E4\uD589\uD558\uBA74 \uC9C0\uCE68 \uBE14\uB85D\uC774 \uC0C8 \uBC84\uC804\uC73C\uB85C \uAC31\uC2E0\uB429\uB2C8\uB2E4.",
|
|
24824
|
+
"update.text.blockRefreshed": "\uC9C0\uCE68 \uBE14\uB85D \uAC31\uC2E0: {paths}",
|
|
24825
|
+
"update.text.blockCurrent": "\uC9C0\uCE68 \uBE14\uB85D\uC740 \uC774\uBBF8 \uD604\uC7AC \uBC84\uC804\uC785\uB2C8\uB2E4: {paths}",
|
|
24826
|
+
"update.text.noBlock": "GITIFACT \uBE14\uB85D\uC774 \uC788\uB294 \uC9C0\uCE68 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. gitifact init\uC73C\uB85C \uC124\uCE58\uD558\uC138\uC694.",
|
|
24827
|
+
"update.text.notInitialized": "\uCD08\uAE30\uD654\uB41C \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2C8\uC5B4\uC11C \uBC84\uC804\uB9CC \uD655\uC778\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24828
|
+
"update.failed": "\uC5C5\uB370\uC774\uD2B8 \uD655\uC778\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4."
|
|
24829
|
+
};
|
|
24830
|
+
|
|
24831
|
+
// src/shared/i18n/index.ts
|
|
24832
|
+
var defaultLanguage2 = "ko";
|
|
24833
|
+
var catalogs2 = { ko: messages_default2 };
|
|
24834
|
+
function t2(key, values = {}, lang = defaultLanguage2) {
|
|
24835
|
+
return catalogs2[lang][key].replace(/\{(\w+)\}/g, (whole, name) => name in values ? String(values[name]) : whole);
|
|
24836
|
+
}
|
|
24837
|
+
|
|
24361
24838
|
// src/output/repository-status.ts
|
|
24362
24839
|
function statusDto(observation) {
|
|
24363
24840
|
return repositoryStatusSuccessV1.parse({
|
|
@@ -24390,11 +24867,11 @@ function escapeTerminal(value) {
|
|
|
24390
24867
|
function statusText(value) {
|
|
24391
24868
|
const { head, summary } = value;
|
|
24392
24869
|
const lines = [
|
|
24393
|
-
"
|
|
24870
|
+
t2("status.text.repository", { path: escapeTerminal(value.repository.rootPath) }),
|
|
24394
24871
|
"HEAD: " + head.state + (head.branch ? " " + escapeTerminal(head.branch) : "") + (head.commit ? " " + head.commit : ""),
|
|
24395
|
-
"
|
|
24872
|
+
t2("status.text.changes", { count: value.changes.length }),
|
|
24396
24873
|
"staged " + summary.staged + " / unstaged " + summary.unstaged + " / untracked " + summary.untracked + " / conflicted " + summary.conflicted,
|
|
24397
|
-
"
|
|
24874
|
+
t2("status.text.observed", { at: value.observation.completedAt })
|
|
24398
24875
|
];
|
|
24399
24876
|
for (const change2 of value.changes) {
|
|
24400
24877
|
let line = (change2.xy ?? "??") + " " + escapeTerminal(change2.path);
|
|
@@ -24433,18 +24910,18 @@ import { join } from "node:path";
|
|
|
24433
24910
|
async function loadBrowserAssets(directory) {
|
|
24434
24911
|
const assets = /* @__PURE__ */ new Map();
|
|
24435
24912
|
async function walk(current, prefix) {
|
|
24436
|
-
for (const
|
|
24437
|
-
if (
|
|
24438
|
-
const name = prefix +
|
|
24439
|
-
if (
|
|
24440
|
-
else if (
|
|
24913
|
+
for (const entry2 of await readdir(current, { withFileTypes: true })) {
|
|
24914
|
+
if (entry2.isSymbolicLink()) throw new Error(t2("browser.assetSymlink"));
|
|
24915
|
+
const name = prefix + entry2.name;
|
|
24916
|
+
if (entry2.isDirectory()) await walk(join(current, entry2.name), name + "/");
|
|
24917
|
+
else if (entry2.isFile()) assets.set("/" + name, await readFile(join(current, entry2.name)));
|
|
24441
24918
|
}
|
|
24442
24919
|
}
|
|
24443
24920
|
try {
|
|
24444
24921
|
await walk(directory, "");
|
|
24445
24922
|
if (!assets.has("/index.html")) throw new Error("missing index");
|
|
24446
24923
|
} catch {
|
|
24447
|
-
throw new Error("
|
|
24924
|
+
throw new Error(t2("browser.assetsUnreadable"));
|
|
24448
24925
|
}
|
|
24449
24926
|
return assets;
|
|
24450
24927
|
}
|
|
@@ -24463,17 +24940,63 @@ function contentType(path3) {
|
|
|
24463
24940
|
|
|
24464
24941
|
// src/server/status-session.ts
|
|
24465
24942
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
24466
|
-
|
|
24467
|
-
|
|
24468
|
-
|
|
24469
|
-
|
|
24470
|
-
|
|
24471
|
-
|
|
24472
|
-
|
|
24943
|
+
|
|
24944
|
+
// src/shared/update-check.ts
|
|
24945
|
+
var updateCheckTimeoutMs = 3e3;
|
|
24946
|
+
var release2 = /^(\d+)\.(\d+)\.(\d+)$/;
|
|
24947
|
+
var running = /^(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?$/;
|
|
24948
|
+
function isNewerRelease(latest, current) {
|
|
24949
|
+
const next = release2.exec(latest);
|
|
24950
|
+
const now = running.exec(current);
|
|
24951
|
+
if (!next || !now) return false;
|
|
24952
|
+
for (let index = 1; index <= 3; index++) {
|
|
24953
|
+
const difference = Number(next[index]) - Number(now[index]);
|
|
24954
|
+
if (difference !== 0) return difference > 0;
|
|
24955
|
+
}
|
|
24956
|
+
return now[4] !== void 0;
|
|
24957
|
+
}
|
|
24958
|
+
var updateCheckDisabled = (env, flagged = false) => flagged || env.GITIFACT_NO_UPDATE_CHECK !== void 0 && env.GITIFACT_NO_UPDATE_CHECK !== "" && env.GITIFACT_NO_UPDATE_CHECK !== "0";
|
|
24959
|
+
var checkingUpdate = { status: "checking", latestVersion: null };
|
|
24960
|
+
var disabledUpdate = { status: "disabled", latestVersion: null };
|
|
24961
|
+
async function resolveUpdate(current, fetchLatest, signal, timeoutMs = updateCheckTimeoutMs) {
|
|
24962
|
+
const controller = new AbortController();
|
|
24963
|
+
const abort = () => controller.abort();
|
|
24964
|
+
const timer = setTimeout(abort, timeoutMs);
|
|
24965
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
24966
|
+
if (signal?.aborted) controller.abort();
|
|
24967
|
+
try {
|
|
24968
|
+
const latest = await Promise.race([
|
|
24969
|
+
fetchLatest(controller.signal),
|
|
24970
|
+
new Promise((_resolve, reject) => {
|
|
24971
|
+
if (controller.signal.aborted) reject(new Error("aborted"));
|
|
24972
|
+
else controller.signal.addEventListener("abort", () => reject(new Error("aborted")), { once: true });
|
|
24973
|
+
})
|
|
24974
|
+
]);
|
|
24975
|
+
if (typeof latest !== "string" || !release2.test(latest)) return { status: "unavailable", latestVersion: null };
|
|
24976
|
+
return { status: isNewerRelease(latest, current) ? "available" : "up-to-date", latestVersion: latest };
|
|
24977
|
+
} catch {
|
|
24978
|
+
return { status: "unavailable", latestVersion: null };
|
|
24979
|
+
} finally {
|
|
24980
|
+
clearTimeout(timer);
|
|
24981
|
+
signal?.removeEventListener("abort", abort);
|
|
24982
|
+
}
|
|
24983
|
+
}
|
|
24984
|
+
var npmGlobalInstall = (version2) => "npm install -g gitifact@" + version2;
|
|
24985
|
+
|
|
24986
|
+
// src/server/status-session.ts
|
|
24987
|
+
function createStatusSession(initial, read, cliVersion = "0.0.0") {
|
|
24988
|
+
const identity2 = { sessionId: randomUUID2(), repository: { key: initial.repository.key, worktreeKey: initial.repository.worktreeKey } };
|
|
24989
|
+
let update = disabledUpdate;
|
|
24473
24990
|
let latest = initial;
|
|
24474
24991
|
let pending;
|
|
24475
24992
|
return {
|
|
24476
|
-
session
|
|
24993
|
+
// The identity never changes; only the update state moves (checking → a final state), so the session is built per read.
|
|
24994
|
+
get session() {
|
|
24995
|
+
return browserSessionV2.parse({ contract: "browser-session", version: 2, ...identity2, cliVersion, update });
|
|
24996
|
+
},
|
|
24997
|
+
setUpdate(next) {
|
|
24998
|
+
update = next;
|
|
24999
|
+
},
|
|
24477
25000
|
get latest() {
|
|
24478
25001
|
return latest;
|
|
24479
25002
|
},
|
|
@@ -24485,7 +25008,7 @@ function createStatusSession(initial, read) {
|
|
|
24485
25008
|
pending = (async () => {
|
|
24486
25009
|
try {
|
|
24487
25010
|
const next = await read();
|
|
24488
|
-
if (next.repository.key !==
|
|
25011
|
+
if (next.repository.key !== identity2.repository.key || next.repository.worktreeKey !== identity2.repository.worktreeKey) {
|
|
24489
25012
|
throw new RepositoryReadError("REPOSITORY_CHANGED");
|
|
24490
25013
|
}
|
|
24491
25014
|
latest = next;
|
|
@@ -24519,9 +25042,11 @@ function commandScoped(key, load) {
|
|
|
24519
25042
|
|
|
24520
25043
|
// src/adapters/git/spec-preview-reader.ts
|
|
24521
25044
|
var RECORD_PATHSPECS = [...STORE_DIRS.map((d) => d + "/spec/"), ...Object.values(DOCUMENT_DIRS).map((d) => d + "/")];
|
|
25045
|
+
var LegacyBaselineError = class extends SpecPreviewError {
|
|
25046
|
+
};
|
|
24522
25047
|
function specPreviewReader(cwd) {
|
|
24523
25048
|
for (const key of Object.keys(process.env)) if (/^GIT_(DIR|WORK_TREE|COMMON_DIR|INDEX_FILE|OBJECT_DIRECTORY|ALTERNATE_OBJECT_DIRECTORIES|CONFIG_COUNT|CONFIG_PARAMETERS|CONFIG_KEY_\d+|CONFIG_VALUE_\d+)$/i.test(key)) {
|
|
24524
|
-
throw new SpecPreviewError("
|
|
25049
|
+
throw new SpecPreviewError(t2("reader.gitContextOverride"));
|
|
24525
25050
|
}
|
|
24526
25051
|
const runner = createGitRunner();
|
|
24527
25052
|
const env = { ...process.env, GIT_OPTIONAL_LOCKS: "0", GIT_NO_LAZY_FETCH: "1", GIT_NO_REPLACE_OBJECTS: "1", GIT_TERMINAL_PROMPT: "0", GIT_LITERAL_PATHSPECS: "0", GIT_GLOB_PATHSPECS: "0", GIT_NOGLOB_PATHSPECS: "0", GIT_ICASE_PATHSPECS: "0", LC_ALL: "C" };
|
|
@@ -24537,7 +25062,7 @@ function specPreviewReader(cwd) {
|
|
|
24537
25062
|
try {
|
|
24538
25063
|
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
24539
25064
|
} catch {
|
|
24540
|
-
throw new SpecPreviewError("
|
|
25065
|
+
throw new SpecPreviewError(t2("reader.notUtf8"));
|
|
24541
25066
|
}
|
|
24542
25067
|
};
|
|
24543
25068
|
return {
|
|
@@ -24546,12 +25071,12 @@ function specPreviewReader(cwd) {
|
|
|
24546
25071
|
const files = /* @__PURE__ */ new Map();
|
|
24547
25072
|
for (const row of output2.split("\0").filter(Boolean)) {
|
|
24548
25073
|
const match = /^(\d+) ([a-f0-9]+) ([0-3])\t([\s\S]+)$/.exec(row);
|
|
24549
|
-
if (!match) throw new SpecPreviewError("
|
|
25074
|
+
if (!match) throw new SpecPreviewError(t2("reader.invalidIndexEntry"));
|
|
24550
25075
|
const [, mode, oid2, stage, path3] = match;
|
|
24551
|
-
if (!["100644", "100755"].includes(mode) || stage !== "0") throw new SpecPreviewError("
|
|
25076
|
+
if (!["100644", "100755"].includes(mode) || stage !== "0") throw new SpecPreviewError(t2("reader.stagingConflictOrLink"));
|
|
24552
25077
|
if (!recordPathPattern.test(path3)) {
|
|
24553
25078
|
if (/^\.gitifact\/(?:product|guides)\//.test(path3)) continue;
|
|
24554
|
-
throw new SpecPreviewError("
|
|
25079
|
+
throw new SpecPreviewError(t2("reader.stagingUnsupported"));
|
|
24555
25080
|
}
|
|
24556
25081
|
files.set(path3, oid2);
|
|
24557
25082
|
}
|
|
@@ -24568,10 +25093,10 @@ function specPreviewReader(cwd) {
|
|
|
24568
25093
|
const head = decode5(headOutput).trim();
|
|
24569
25094
|
const branch = decode5(branchOutput).trim();
|
|
24570
25095
|
if (head) {
|
|
24571
|
-
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) throw new SpecPreviewError("
|
|
25096
|
+
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) throw new SpecPreviewError(t2("reader.headUnknown"));
|
|
24572
25097
|
return { head, branch: branch || null };
|
|
24573
25098
|
}
|
|
24574
|
-
if (!branch.startsWith("refs/heads/") || (await git(["for-each-ref", "--format=%(refname)", "--", branch])).length) throw new SpecPreviewError("
|
|
25099
|
+
if (!branch.startsWith("refs/heads/") || (await git(["for-each-ref", "--format=%(refname)", "--", branch])).length) throw new SpecPreviewError(t2("reader.damagedHead"));
|
|
24575
25100
|
return { head: null, branch };
|
|
24576
25101
|
},
|
|
24577
25102
|
location() {
|
|
@@ -24581,13 +25106,13 @@ function specPreviewReader(cwd) {
|
|
|
24581
25106
|
let values = line(await git(["rev-parse", "--path-format=absolute", ...fields2.flat()])).split("\n");
|
|
24582
25107
|
if (values.length !== fields2.length) values = await Promise.all(fields2.map(async (flags) => line(await git(["rev-parse", "--path-format=absolute", ...flags]))));
|
|
24583
25108
|
const [root, gitDir, indexPath, objectFormat] = values.map((value) => value.trim());
|
|
24584
|
-
if (objectFormat !== "sha1" && objectFormat !== "sha256") throw new SpecPreviewError("
|
|
25109
|
+
if (objectFormat !== "sha1" && objectFormat !== "sha256") throw new SpecPreviewError(t2("reader.objectFormat"));
|
|
24585
25110
|
return { root, gitDir, indexPath, objectFormat };
|
|
24586
25111
|
});
|
|
24587
25112
|
},
|
|
24588
25113
|
async resolve(ref) {
|
|
24589
25114
|
const oid2 = (await git(["rev-parse", "--verify", "--end-of-options", ref + "^{commit}"])).toString("ascii").trim();
|
|
24590
|
-
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(oid2)) throw new SpecPreviewError("
|
|
25115
|
+
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(oid2)) throw new SpecPreviewError(t2("reader.commitUnknown"));
|
|
24591
25116
|
return oid2;
|
|
24592
25117
|
},
|
|
24593
25118
|
async files(oid2, allowLegacyBaseline = false) {
|
|
@@ -24596,24 +25121,24 @@ function specPreviewReader(cwd) {
|
|
|
24596
25121
|
let legacy;
|
|
24597
25122
|
for (const row of entries.split("\0").filter(Boolean)) {
|
|
24598
25123
|
const match = /^(\d+) (\w+) ([a-f0-9]+)\t([\s\S]+)$/.exec(row);
|
|
24599
|
-
if (!match) throw new SpecPreviewError("
|
|
25124
|
+
if (!match) throw new SpecPreviewError(t2("reader.invalidTree"));
|
|
24600
25125
|
const [, mode, type, object4, path3] = match;
|
|
24601
|
-
if (!["100644", "100755"].includes(mode) || type !== "blob") throw new SpecPreviewError("
|
|
25126
|
+
if (!["100644", "100755"].includes(mode) || type !== "blob") throw new SpecPreviewError(t2("reader.linkOrSubmodule", { path: path3 }));
|
|
24602
25127
|
if (!recordPathPattern.test(path3) && !path3.endsWith("/tryce.json")) continue;
|
|
24603
25128
|
if (path3.endsWith("/tryce.json")) {
|
|
24604
|
-
if (!allowLegacyBaseline) throw new
|
|
25129
|
+
if (!allowLegacyBaseline) throw new LegacyBaselineError(t2("reader.legacyJson"));
|
|
24605
25130
|
legacy = path3.split("/")[0];
|
|
24606
25131
|
continue;
|
|
24607
25132
|
}
|
|
24608
|
-
if (!recordPathPattern.test(path3) || !["100644", "100755"].includes(mode) || type !== "blob") throw new SpecPreviewError("
|
|
25133
|
+
if (!recordPathPattern.test(path3) || !["100644", "100755"].includes(mode) || type !== "blob") throw new SpecPreviewError(t2("reader.unsupportedEntry", { path: path3 }));
|
|
24609
25134
|
files.set(path3, object4);
|
|
24610
25135
|
}
|
|
24611
|
-
if (new Set([...files.keys()].map((p) => p.split("/")[0])).size > 1) throw new SpecPreviewError("
|
|
25136
|
+
if (new Set([...files.keys()].map((p) => p.split("/")[0])).size > 1) throw new SpecPreviewError(t2("reader.mixedStores"));
|
|
24612
25137
|
if (legacy) {
|
|
24613
|
-
if (files.size) throw new SpecPreviewError("
|
|
25138
|
+
if (files.size) throw new SpecPreviewError(t2("reader.mixedFormats"));
|
|
24614
25139
|
parseProjectConfig(decode5(await git(["show", `${oid2}:${legacy}/config.json`])));
|
|
24615
25140
|
}
|
|
24616
|
-
if (files.size > 2e3) throw new SpecPreviewError("
|
|
25141
|
+
if (files.size > 2e3) throw new SpecPreviewError(t2("reader.fileLimit"));
|
|
24617
25142
|
const blobs = /* @__PURE__ */ new Map();
|
|
24618
25143
|
const ids = [...new Set(files.values())];
|
|
24619
25144
|
let totalBytes = 0;
|
|
@@ -24625,13 +25150,13 @@ function specPreviewReader(cwd) {
|
|
|
24625
25150
|
const end = output2.indexOf(10, offset);
|
|
24626
25151
|
const header = output2.subarray(offset, end).toString("ascii").split(" ");
|
|
24627
25152
|
const size = Number(header[2]);
|
|
24628
|
-
if (end < offset || header[0] !== id || header[1] !== "blob" || !Number.isSafeInteger(size) || size < 0 || size > 1024 * 1024 || output2[end + size + 1] !== 10) throw new SpecPreviewError("
|
|
25153
|
+
if (end < offset || header[0] !== id || header[1] !== "blob" || !Number.isSafeInteger(size) || size < 0 || size > 1024 * 1024 || output2[end + size + 1] !== 10) throw new SpecPreviewError(t2("reader.blobShape"));
|
|
24629
25154
|
totalBytes += size;
|
|
24630
|
-
if (totalBytes > 16 * 1024 * 1024) throw new SpecPreviewError("
|
|
25155
|
+
if (totalBytes > 16 * 1024 * 1024) throw new SpecPreviewError(t2("reader.totalLimit"));
|
|
24631
25156
|
blobs.set(id, decode5(output2.subarray(end + 1, end + size + 1)));
|
|
24632
25157
|
offset = end + size + 2;
|
|
24633
25158
|
}
|
|
24634
|
-
if (offset !== output2.length) throw new SpecPreviewError("
|
|
25159
|
+
if (offset !== output2.length) throw new SpecPreviewError(t2("reader.blobBoundary"));
|
|
24635
25160
|
}
|
|
24636
25161
|
return new Map([...files].map(([path3, id]) => [path3, blobs.get(id)]));
|
|
24637
25162
|
},
|
|
@@ -24662,7 +25187,7 @@ var fileInfo = (path3) => lstat(path3).catch((error62) => {
|
|
|
24662
25187
|
async function configDirectory(root) {
|
|
24663
25188
|
const path3 = join2(root, ".gitifact");
|
|
24664
25189
|
const info4 = await fileInfo(path3);
|
|
24665
|
-
if (info4 && (!info4.isDirectory() || info4.isSymbolicLink())) throw new InitError("PATH_CONFLICT", ".
|
|
25190
|
+
if (info4 && (!info4.isDirectory() || info4.isSymbolicLink())) throw new InitError("PATH_CONFLICT", t2("config.storeNotDirectory"));
|
|
24666
25191
|
return info4;
|
|
24667
25192
|
}
|
|
24668
25193
|
async function readConfigFile(root) {
|
|
@@ -24670,20 +25195,20 @@ async function readConfigFile(root) {
|
|
|
24670
25195
|
const path3 = join2(root, ".gitifact", "config.json");
|
|
24671
25196
|
const info4 = await fileInfo(path3);
|
|
24672
25197
|
if (!info4) {
|
|
24673
|
-
if (await fileInfo(join2(root, ".tryce", "config.json"))) throw new InitError("MIGRATION_REQUIRED", ".
|
|
25198
|
+
if (await fileInfo(join2(root, ".tryce", "config.json"))) throw new InitError("MIGRATION_REQUIRED", t2("config.migrateFirst"));
|
|
24674
25199
|
return void 0;
|
|
24675
25200
|
}
|
|
24676
|
-
if (!info4.isFile() || info4.isSymbolicLink() || info4.size > 65536) throw new InitError("PATH_CONFLICT", "config.
|
|
25201
|
+
if (!info4.isFile() || info4.isSymbolicLink() || info4.size > 65536) throw new InitError("PATH_CONFLICT", t2("config.fileShape"));
|
|
24677
25202
|
const bytes = await readFile2(path3);
|
|
24678
25203
|
const after = await fileInfo(path3);
|
|
24679
25204
|
await configDirectory(root);
|
|
24680
25205
|
if (!after || after.ino !== info4.ino || after.dev !== info4.dev || after.mtimeMs !== info4.mtimeMs || bytes.length > 65536) {
|
|
24681
|
-
throw new InitError("INPUT_CHANGED", "
|
|
25206
|
+
throw new InitError("INPUT_CHANGED", t2("config.changedWhileReading"));
|
|
24682
25207
|
}
|
|
24683
25208
|
try {
|
|
24684
25209
|
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
24685
25210
|
} catch {
|
|
24686
|
-
throw new InitError("INVALID_CONFIG", "
|
|
25211
|
+
throw new InitError("INVALID_CONFIG", t2("config.notUtf8Json"));
|
|
24687
25212
|
}
|
|
24688
25213
|
}
|
|
24689
25214
|
async function publishConfig(root, text2, recheck, beforePublish) {
|
|
@@ -24697,7 +25222,7 @@ async function publishConfig(root, text2, recheck, beforePublish) {
|
|
|
24697
25222
|
const unchanged = async () => {
|
|
24698
25223
|
const current = await configDirectory(root);
|
|
24699
25224
|
if (!owner || !current || current.ino !== owner.ino || current.dev !== owner.dev || await realpath(directory) !== canonical) {
|
|
24700
|
-
throw new InitError("INPUT_CHANGED", "
|
|
25225
|
+
throw new InitError("INPUT_CHANGED", t2("config.directoryChanged"));
|
|
24701
25226
|
}
|
|
24702
25227
|
};
|
|
24703
25228
|
const temporary = join2(directory, ".init-" + randomUUID3() + ".tmp");
|
|
@@ -24715,7 +25240,7 @@ async function publishConfig(root, text2, recheck, beforePublish) {
|
|
|
24715
25240
|
await recheck();
|
|
24716
25241
|
await unchanged();
|
|
24717
25242
|
const bytes = await readFile2(temporary, "utf8");
|
|
24718
|
-
if (bytes !== text2) throw new InitError("INPUT_CHANGED", "
|
|
25243
|
+
if (bytes !== text2) throw new InitError("INPUT_CHANGED", t2("config.temporaryChanged"));
|
|
24719
25244
|
parseManagedConfig(bytes);
|
|
24720
25245
|
await link(temporary, join2(directory, "config.json"));
|
|
24721
25246
|
} finally {
|
|
@@ -24736,7 +25261,7 @@ var info = async (path3) => lstat2(path3).catch((e) => {
|
|
|
24736
25261
|
var digest = (value) => createHash2("sha256").update(value).digest("hex");
|
|
24737
25262
|
var LEGACY_LOCKS = ["tryce-spec-preview.lock", "tryce-spec-commit.lock"];
|
|
24738
25263
|
async function failOnLegacyLock(gitDir) {
|
|
24739
|
-
for (const name of LEGACY_LOCKS) if (await info(join3(gitDir, name))) fail4("
|
|
25264
|
+
for (const name of LEGACY_LOCKS) if (await info(join3(gitDir, name))) fail4(t2("store.legacyLock", { path: join3(gitDir, name) }));
|
|
24740
25265
|
}
|
|
24741
25266
|
var decode3 = (bytes) => new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
24742
25267
|
var generatePreviewId = (prefix) => prefix + "-" + [...randomBytes(10)].map((n) => "abcdefghijklmnopqrstuvwxyz234567"[n & 31]).join("");
|
|
@@ -24747,26 +25272,26 @@ async function snapshot2(root) {
|
|
|
24747
25272
|
let count = 0;
|
|
24748
25273
|
let bytes = 0;
|
|
24749
25274
|
const parent = await info(join3(root, ".gitifact"));
|
|
24750
|
-
if (parent && (!parent.isDirectory() || parent.isSymbolicLink())) fail4(".
|
|
24751
|
-
if (!parent && await info(join3(root, ".tryce"))) fail4(".
|
|
25275
|
+
if (parent && (!parent.isDirectory() || parent.isSymbolicLink())) fail4(t2("store.storeNotDirectory"));
|
|
25276
|
+
if (!parent && await info(join3(root, ".tryce"))) fail4(t2("store.migrateFirst"));
|
|
24752
25277
|
const config2 = await readConfigFile(root);
|
|
24753
|
-
if (config2 !== void 0 && !("schemaVersion" in parseManagedConfig(config2)) || await info(join3(root, "specs"))) fail4("
|
|
25278
|
+
if (config2 !== void 0 && !("schemaVersion" in parseManagedConfig(config2)) || await info(join3(root, "specs"))) fail4(t2("store.legacyProject"));
|
|
24754
25279
|
async function visit2(path3, depth, documents) {
|
|
24755
25280
|
const stat3 = await info(join3(root, path3));
|
|
24756
25281
|
if (!stat3) return;
|
|
24757
|
-
if (stat3.isSymbolicLink() || !stat3.isDirectory() && !stat3.isFile()) fail4("
|
|
24758
|
-
if (++count > 4e3) fail4("
|
|
25282
|
+
if (stat3.isSymbolicLink() || !stat3.isDirectory() && !stat3.isFile()) fail4(t2("store.linkOrSpecial", { path: path3 }));
|
|
25283
|
+
if (++count > 4e3) fail4(t2("store.tooManyFiles"));
|
|
24759
25284
|
if (stat3.isDirectory()) {
|
|
24760
|
-
if (depth > (documents ? 8 : 1)) fail4("
|
|
25285
|
+
if (depth > (documents ? 8 : 1)) fail4(t2("store.tooDeep", { path: path3 }));
|
|
24761
25286
|
for (const name of (await readdir2(join3(root, path3))).sort()) await visit2(path3 + "/" + name, depth + 1, documents);
|
|
24762
25287
|
} else {
|
|
24763
|
-
if (path3.endsWith("/tryce.json")) fail4("
|
|
25288
|
+
if (path3.endsWith("/tryce.json")) fail4(t2("store.legacyJson"));
|
|
24764
25289
|
if (documents ? !(path3.endsWith(".md") || depth === 1 && path3.endsWith("/history.jsonl")) : !/\/(requirements\.md|design\.md|history\.jsonl)$/.test(path3)) return;
|
|
24765
|
-
if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/")) fail4("
|
|
24766
|
-
if (stat3.nlink !== 1 || stat3.size > 1024 * 1024) fail4("
|
|
25290
|
+
if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/")) fail4(t2("store.unsupportedPath", { path: path3 }));
|
|
25291
|
+
if (stat3.nlink !== 1 || stat3.size > 1024 * 1024) fail4(t2("store.hardLinkOrSize"));
|
|
24767
25292
|
const raw = await readFile3(join3(root, path3));
|
|
24768
25293
|
bytes += raw.length;
|
|
24769
|
-
if (raw.length > 1024 * 1024 || bytes > 16 * 1024 * 1024) fail4("
|
|
25294
|
+
if (raw.length > 1024 * 1024 || bytes > 16 * 1024 * 1024) fail4(t2("store.sizeLimit"));
|
|
24770
25295
|
files.set(path3, decode3(raw));
|
|
24771
25296
|
}
|
|
24772
25297
|
}
|
|
@@ -24778,11 +25303,11 @@ async function snapshot2(root) {
|
|
|
24778
25303
|
async function readWorkingPreviewState(cwd) {
|
|
24779
25304
|
const { root, gitDir } = await specPreviewReader(cwd).location();
|
|
24780
25305
|
await failOnLegacyLock(gitDir);
|
|
24781
|
-
if (await info(join3(gitDir, "gitifact-spec-preview.lock"))) fail4("
|
|
25306
|
+
if (await info(join3(gitDir, "gitifact-spec-preview.lock"))) fail4(t2("store.locked"));
|
|
24782
25307
|
const first = await snapshot2(root);
|
|
24783
25308
|
const second = await snapshot2(root);
|
|
24784
|
-
if (first.stamp !== second.stamp) fail4("
|
|
24785
|
-
if (await info(join3(gitDir, "gitifact-spec-preview.lock"))) fail4("
|
|
25309
|
+
if (first.stamp !== second.stamp) fail4(t2("store.changedWhileReading"));
|
|
25310
|
+
if (await info(join3(gitDir, "gitifact-spec-preview.lock"))) fail4(t2("store.lockedWhileReading"));
|
|
24786
25311
|
return first;
|
|
24787
25312
|
}
|
|
24788
25313
|
async function readWorkingPreview(cwd) {
|
|
@@ -24790,9 +25315,9 @@ async function readWorkingPreview(cwd) {
|
|
|
24790
25315
|
return { stamp, specs, documents, warnings: designReferenceWarnings(specs) };
|
|
24791
25316
|
}
|
|
24792
25317
|
async function saveWorkingPreview(cwd, input2, publish = rename) {
|
|
24793
|
-
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail4("
|
|
25318
|
+
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail4(t2("store.invalidInput"));
|
|
24794
25319
|
const request = input2;
|
|
24795
|
-
if (Object.keys(request).sort().join(",") !== "expected,operations" || typeof request.expected !== "string") fail4("
|
|
25320
|
+
if (Object.keys(request).sort().join(",") !== "expected,operations" || typeof request.expected !== "string") fail4(t2("store.expectedOperations"));
|
|
24796
25321
|
return previewTransaction(cwd, request.expected, async (before) => {
|
|
24797
25322
|
const result = editSpecPreview(before.bundle, request.operations, generatePreviewId);
|
|
24798
25323
|
const writes = /* @__PURE__ */ new Map();
|
|
@@ -24820,7 +25345,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename, after
|
|
|
24820
25345
|
try {
|
|
24821
25346
|
await mkdir2(lock);
|
|
24822
25347
|
} catch (e) {
|
|
24823
|
-
if (e.code === "EEXIST") fail4("
|
|
25348
|
+
if (e.code === "EEXIST") fail4(t2("store.locked"));
|
|
24824
25349
|
throw e;
|
|
24825
25350
|
}
|
|
24826
25351
|
const createdDirs = [];
|
|
@@ -24831,7 +25356,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename, after
|
|
|
24831
25356
|
async function directory(path3) {
|
|
24832
25357
|
const stat3 = await info(path3);
|
|
24833
25358
|
if (stat3) {
|
|
24834
|
-
if (!stat3.isDirectory() || stat3.isSymbolicLink()) fail4("
|
|
25359
|
+
if (!stat3.isDirectory() || stat3.isSymbolicLink()) fail4(t2("store.notDirectory", { path: path3 }));
|
|
24835
25360
|
return;
|
|
24836
25361
|
}
|
|
24837
25362
|
await directory(dirname(path3));
|
|
@@ -24840,11 +25365,11 @@ async function previewTransaction(cwd, expected2, build, publish = rename, after
|
|
|
24840
25365
|
}
|
|
24841
25366
|
try {
|
|
24842
25367
|
const before = await snapshot2(root);
|
|
24843
|
-
if (before.stamp !== expected2) fail4("
|
|
25368
|
+
if (before.stamp !== expected2) fail4(t2("store.staleExpected"));
|
|
24844
25369
|
const result = await build(before);
|
|
24845
25370
|
for (const [path3, after2] of result.writes) {
|
|
24846
|
-
if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/") || path3.split("/").some((p) => p === ".." || p === "." || /[\\:\0]/.test(p))) fail4("
|
|
24847
|
-
if (after2 !== null && Buffer.byteLength(after2) > 1024 * 1024) fail4("
|
|
25371
|
+
if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/") || path3.split("/").some((p) => p === ".." || p === "." || /[\\:\0]/.test(p))) fail4(t2("store.unsupportedSavePath"));
|
|
25372
|
+
if (after2 !== null && Buffer.byteLength(after2) > 1024 * 1024) fail4(t2("store.fileSizeLimit"));
|
|
24848
25373
|
changed.push({ path: path3, before: before.files.get(path3) ?? null, after: after2 });
|
|
24849
25374
|
}
|
|
24850
25375
|
const finalFiles = new Map(before.files);
|
|
@@ -24852,7 +25377,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename, after
|
|
|
24852
25377
|
if (c.after === null) finalFiles.delete(c.path);
|
|
24853
25378
|
else finalFiles.set(c.path, c.after);
|
|
24854
25379
|
}
|
|
24855
|
-
if (finalFiles.size > 2e3 || [...finalFiles.values()].reduce((n, s) => n + Buffer.byteLength(s), 0) > 16 * 1024 * 1024) fail4("
|
|
25380
|
+
if (finalFiles.size > 2e3 || [...finalFiles.values()].reduce((n, s) => n + Buffer.byteLength(s), 0) > 16 * 1024 * 1024) fail4(t2("store.totalLimit"));
|
|
24856
25381
|
await writeFile(join3(lock, "recovery.json"), JSON.stringify({ root, changed }), { flag: "wx" });
|
|
24857
25382
|
for (const c of changed) {
|
|
24858
25383
|
if (c.after === null) {
|
|
@@ -24864,19 +25389,19 @@ async function previewTransaction(cwd, expected2, build, publish = rename, after
|
|
|
24864
25389
|
await writeFile(temp, c.after, { flag: "wx" });
|
|
24865
25390
|
temporary.push(temp);
|
|
24866
25391
|
}
|
|
24867
|
-
if ((await snapshot2(root)).stamp !== before.stamp) fail4("
|
|
25392
|
+
if ((await snapshot2(root)).stamp !== before.stamp) fail4(t2("store.changedPreparing"));
|
|
24868
25393
|
await result.recheck?.();
|
|
24869
25394
|
for (let i = 0; i < changed.length; i++) {
|
|
24870
25395
|
const c = changed[i];
|
|
24871
25396
|
const path3 = join3(root, c.path);
|
|
24872
25397
|
const stat3 = await info(path3);
|
|
24873
|
-
if (stat3?.isSymbolicLink() || stat3 && !stat3.isFile() || (stat3 ? decode3(await readFile3(path3)) : null) !== c.before) fail4("
|
|
25398
|
+
if (stat3?.isSymbolicLink() || stat3 && !stat3.isFile() || (stat3 ? decode3(await readFile3(path3)) : null) !== c.before) fail4(t2("store.changedBeforeWrite"));
|
|
24874
25399
|
if (c.after === null) await unlink2(path3);
|
|
24875
25400
|
else await publish(temporary[i], path3);
|
|
24876
25401
|
published.push(c);
|
|
24877
25402
|
}
|
|
24878
25403
|
const after = await snapshot2(root);
|
|
24879
|
-
if (after.stamp !== digest(JSON.stringify([...finalFiles].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) + (before.config ?? ""))) fail4("
|
|
25404
|
+
if (after.stamp !== digest(JSON.stringify([...finalFiles].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) + (before.config ?? ""))) fail4(t2("store.changedWhileWriting"));
|
|
24880
25405
|
await result.recheck?.();
|
|
24881
25406
|
await afterPublish?.(after);
|
|
24882
25407
|
return { ...result.data, stamp: after.stamp, paths: changed.map((c) => c.path), specs: after.specs, documents: after.documents, warnings: designReferenceWarnings(after.specs) };
|
|
@@ -24904,7 +25429,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename, after
|
|
|
24904
25429
|
keepRecovery = true;
|
|
24905
25430
|
}
|
|
24906
25431
|
}
|
|
24907
|
-
if (keepRecovery) fail4("
|
|
25432
|
+
if (keepRecovery) fail4(t2("store.recoveryIncomplete", { path: lock }));
|
|
24908
25433
|
throw error62;
|
|
24909
25434
|
} finally {
|
|
24910
25435
|
for (const path3 of temporary.filter(Boolean)) await unlink2(path3).catch((e) => {
|
|
@@ -24929,7 +25454,7 @@ function createSpecBrowserReader(root, sessionId, inherited = process.env) {
|
|
|
24929
25454
|
const git = async (args, acceptedExitCodes = [0]) => (await runner(["--no-optional-locks", ...args], { cwd: root, env, timeoutMs: 15e3, maxBytes: 16 * 1024 * 1024, acceptedExitCodes })).toString("utf8");
|
|
24930
25455
|
const readHead = async () => {
|
|
24931
25456
|
const head = (await git(["rev-parse", "--verify", "--quiet", "HEAD"], [0, 1])).trim();
|
|
24932
|
-
if (head && !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) throw new SpecPreviewError("
|
|
25457
|
+
if (head && !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) throw new SpecPreviewError(t2("specReader.headUnreadable"));
|
|
24933
25458
|
if (!head) await reader.baseline();
|
|
24934
25459
|
return head || null;
|
|
24935
25460
|
};
|
|
@@ -24950,9 +25475,9 @@ function createSpecBrowserReader(root, sessionId, inherited = process.env) {
|
|
|
24950
25475
|
const pending = /* @__PURE__ */ new Map();
|
|
24951
25476
|
async function read(cursor, expectedHead) {
|
|
24952
25477
|
const raw = await readConfigFile(root);
|
|
24953
|
-
if (!raw || !("schemaVersion" in parseManagedConfig(raw))) throw new SpecPreviewError("
|
|
25478
|
+
if (!raw || !("schemaVersion" in parseManagedConfig(raw))) throw new SpecPreviewError(t2("specReader.schemaRequired"));
|
|
24954
25479
|
const base = { head: await readHead() };
|
|
24955
|
-
if (cursor > 0 && expectedHead !== base.head) throw new SpecPreviewError("
|
|
25480
|
+
if (cursor > 0 && expectedHead !== base.head) throw new SpecPreviewError(t2("specReader.historyChanged"));
|
|
24956
25481
|
const current = await readWorkingPreviewState(root);
|
|
24957
25482
|
const bare = current.specs.map(({ history: _history, ...s }) => ({ ...s, contributors: [], updatedAt: null }));
|
|
24958
25483
|
const bareDocuments = current.documents.flatMap((set2) => set2.documents).map((d) => ({ ...d, updatedAt: null }));
|
|
@@ -24964,7 +25489,7 @@ function createSpecBrowserReader(root, sessionId, inherited = process.env) {
|
|
|
24964
25489
|
const people = /* @__PURE__ */ new Map();
|
|
24965
25490
|
for (const line of lines) {
|
|
24966
25491
|
const [name, email3, latest] = line.split("\0");
|
|
24967
|
-
if (!name || !email3 || !latest) throw new SpecPreviewError("
|
|
25492
|
+
if (!name || !email3 || !latest) throw new SpecPreviewError(t2("specReader.authorUnreadable"));
|
|
24968
25493
|
const person = people.get(email3);
|
|
24969
25494
|
if (person) person.commits++;
|
|
24970
25495
|
else people.set(email3, { name, email: email3, latest, commits: 1 });
|
|
@@ -24993,7 +25518,7 @@ function createSpecBrowserReader(root, sessionId, inherited = process.env) {
|
|
|
24993
25518
|
const lines = (await git(["log", "--format=%aN%x00%aE%x00%aI", "--max-count=10001", head])).trim().split("\n").filter(Boolean);
|
|
24994
25519
|
for (const line of lines.slice(0, 1e4)) {
|
|
24995
25520
|
const [name, email3, latest] = line.split("\0");
|
|
24996
|
-
if (!name || !email3 || !latest) throw new SpecPreviewError("
|
|
25521
|
+
if (!name || !email3 || !latest) throw new SpecPreviewError(t2("specReader.authorUnreadable"));
|
|
24997
25522
|
const person = people.get(email3);
|
|
24998
25523
|
if (person) person.commits++;
|
|
24999
25524
|
else people.set(email3, { name, email: email3, latest, commits: 1 });
|
|
@@ -25004,7 +25529,7 @@ function createSpecBrowserReader(root, sessionId, inherited = process.env) {
|
|
|
25004
25529
|
let boundary = false;
|
|
25005
25530
|
const groups = await Promise.all(commits.slice(0, 10).map(async (row) => {
|
|
25006
25531
|
const [commit, parents, author, email3, date5, committer, message] = row.split("\0");
|
|
25007
|
-
if (!commit || author === void 0 || email3 === void 0 || !date5 || committer === void 0 || message === void 0) throw new SpecPreviewError("
|
|
25532
|
+
if (!commit || author === void 0 || email3 === void 0 || !date5 || committer === void 0 || message === void 0) throw new SpecPreviewError(t2("specReader.historyUnreadable"));
|
|
25008
25533
|
const after = await snapshot3(commit);
|
|
25009
25534
|
let before = { specs: [], documents: [{ kind: "product", documents: [], history: [] }, { kind: "guide", documents: [], history: [] }] };
|
|
25010
25535
|
const parent = parents?.split(" ")[0];
|
|
@@ -25012,7 +25537,7 @@ function createSpecBrowserReader(root, sessionId, inherited = process.env) {
|
|
|
25012
25537
|
try {
|
|
25013
25538
|
before = await snapshot3(parent);
|
|
25014
25539
|
} catch (error62) {
|
|
25015
|
-
if (error62 instanceof
|
|
25540
|
+
if (error62 instanceof LegacyBaselineError) boundary = true;
|
|
25016
25541
|
else throw error62;
|
|
25017
25542
|
}
|
|
25018
25543
|
}
|
|
@@ -25032,7 +25557,7 @@ function createSpecBrowserReader(root, sessionId, inherited = process.env) {
|
|
|
25032
25557
|
reasons: c.reasons.map((r) => r.reason)
|
|
25033
25558
|
}));
|
|
25034
25559
|
}));
|
|
25035
|
-
if (await readHead() !== head || (await readWorkingPreviewState(root)).stamp !== current.stamp) throw new SpecPreviewError("
|
|
25560
|
+
if (await readHead() !== head || (await readWorkingPreviewState(root)).stamp !== current.stamp) throw new SpecPreviewError(t2("specReader.projectChanged"));
|
|
25036
25561
|
return browserSpecsV1.parse({
|
|
25037
25562
|
contract: "browser-specs",
|
|
25038
25563
|
version: 1,
|
|
@@ -25061,6 +25586,10 @@ function createSpecBrowserReader(root, sessionId, inherited = process.env) {
|
|
|
25061
25586
|
}
|
|
25062
25587
|
|
|
25063
25588
|
// src/server/browser-server.ts
|
|
25589
|
+
var readBundledChangelog = (language) => readFile4(new URL("./i18n/" + language + "/changelog.md", import.meta.url), "utf8").catch((error62) => {
|
|
25590
|
+
if (error62.code === "ENOENT") return null;
|
|
25591
|
+
throw error62;
|
|
25592
|
+
});
|
|
25064
25593
|
async function startBrowserServer(options) {
|
|
25065
25594
|
const controller = new AbortController();
|
|
25066
25595
|
const onAbort = () => controller.abort();
|
|
@@ -25080,11 +25609,13 @@ async function startBrowserServer(options) {
|
|
|
25080
25609
|
options.signal?.removeEventListener("abort", onAbort);
|
|
25081
25610
|
throw error62;
|
|
25082
25611
|
}
|
|
25083
|
-
const store = createStatusSession(initial, () => read(controller.signal));
|
|
25084
|
-
const
|
|
25612
|
+
const store = createStatusSession(initial, () => read(controller.signal), options.cliVersion);
|
|
25613
|
+
const sessionId = store.session.sessionId;
|
|
25614
|
+
const readChangelog = options.readChangelog ?? readBundledChangelog;
|
|
25615
|
+
let updatePending;
|
|
25085
25616
|
let closing = false;
|
|
25086
25617
|
let origin = "";
|
|
25087
|
-
const readSpecs = createSpecBrowserReader(initial.repository.rootPath,
|
|
25618
|
+
const readSpecs = createSpecBrowserReader(initial.repository.rootPath, sessionId, options.env);
|
|
25088
25619
|
function json2(response, status, value) {
|
|
25089
25620
|
response.writeHead(status, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store" });
|
|
25090
25621
|
response.end(JSON.stringify(value) + "\n");
|
|
@@ -25097,74 +25628,87 @@ async function startBrowserServer(options) {
|
|
|
25097
25628
|
response.setHeader("X-Frame-Options", "DENY");
|
|
25098
25629
|
response.setHeader("Referrer-Policy", "no-referrer");
|
|
25099
25630
|
response.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; base-uri 'none'; frame-ancestors 'none'");
|
|
25100
|
-
if (closing) return fail8(response, 503, "SERVER_CLOSING", "
|
|
25101
|
-
if (request.headers.host !== new URL(origin).host) return fail8(response, 403, "FORBIDDEN", "
|
|
25631
|
+
if (closing) return fail8(response, 503, "SERVER_CLOSING", t2("server.closing"));
|
|
25632
|
+
if (request.headers.host !== new URL(origin).host) return fail8(response, 403, "FORBIDDEN", t2("server.forbiddenHost"));
|
|
25102
25633
|
const requestOrigin = request.headers.origin;
|
|
25103
25634
|
const allowedOrigin = requestOrigin === origin || options.dev && requestOrigin === "http://127.0.0.1:5173";
|
|
25104
|
-
if (requestOrigin && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", "
|
|
25635
|
+
if (requestOrigin && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", t2("server.forbiddenOrigin"));
|
|
25105
25636
|
const raw = request.url ?? "/";
|
|
25106
|
-
if (!raw.startsWith("/") || raw.startsWith("//") || raw.includes("\\")) return fail8(response, 400, "BAD_REQUEST", "
|
|
25637
|
+
if (!raw.startsWith("/") || raw.startsWith("//") || raw.includes("\\")) return fail8(response, 400, "BAD_REQUEST", t2("server.badPath"));
|
|
25107
25638
|
let url2;
|
|
25108
25639
|
let path3;
|
|
25109
25640
|
try {
|
|
25110
25641
|
url2 = new URL(raw, origin);
|
|
25111
25642
|
path3 = decodeURIComponent(url2.pathname);
|
|
25112
25643
|
} catch {
|
|
25113
|
-
return fail8(response, 400, "BAD_REQUEST", "
|
|
25644
|
+
return fail8(response, 400, "BAD_REQUEST", t2("server.badPath"));
|
|
25114
25645
|
}
|
|
25115
25646
|
if (path3.includes("\0") || path3.includes("\\") || path3.split("/").some((part) => part === ".." || part === ".")) {
|
|
25116
|
-
return fail8(response, 400, "BAD_REQUEST", "
|
|
25647
|
+
return fail8(response, 400, "BAD_REQUEST", t2("server.badPath"));
|
|
25117
25648
|
}
|
|
25118
25649
|
if (request.headers["transfer-encoding"] || request.headers["content-length"] && request.headers["content-length"] !== "0") {
|
|
25119
25650
|
request.resume();
|
|
25120
|
-
return fail8(response, 400, "BAD_REQUEST", "
|
|
25651
|
+
return fail8(response, 400, "BAD_REQUEST", t2("server.noBody"));
|
|
25121
25652
|
}
|
|
25122
25653
|
const api = path3 === "/api" || path3.startsWith("/api/");
|
|
25123
25654
|
if (api) {
|
|
25124
|
-
if (request.headers["sec-fetch-site"] === "cross-site" && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", "
|
|
25125
|
-
if (url2.search && path3 !== "/api/v1/specs") return fail8(response, 400, "BAD_REQUEST", "
|
|
25655
|
+
if (request.headers["sec-fetch-site"] === "cross-site" && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", t2("server.crossSite"));
|
|
25656
|
+
if (url2.search && path3 !== "/api/v1/specs" && path3 !== "/api/v1/changelog") return fail8(response, 400, "BAD_REQUEST", t2("server.noQuery"));
|
|
25126
25657
|
if (path3.startsWith("/api/v1/product/assets/")) {
|
|
25127
25658
|
const name = path3.slice("/api/v1/product/assets/".length);
|
|
25128
25659
|
if (request.method !== "GET") {
|
|
25129
25660
|
response.setHeader("Allow", "GET");
|
|
25130
|
-
return fail8(response, 405, "METHOD_NOT_ALLOWED", "
|
|
25661
|
+
return fail8(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
|
|
25131
25662
|
}
|
|
25132
|
-
if (!isProductAssetPath(".gitifact/product/" + name)) return fail8(response, 404, "NOT_FOUND", "
|
|
25663
|
+
if (!isProductAssetPath(".gitifact/product/" + name)) return fail8(response, 404, "NOT_FOUND", t2("server.productImageNotFound"));
|
|
25133
25664
|
const file2 = join4(initial.repository.rootPath, ".gitifact", "product", name);
|
|
25134
25665
|
const stat3 = await lstat3(file2).catch(() => void 0);
|
|
25135
|
-
if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > 5 * 1024 * 1024) return fail8(response, 404, "NOT_FOUND", "
|
|
25666
|
+
if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > 5 * 1024 * 1024) return fail8(response, 404, "NOT_FOUND", t2("server.productImageNotFound"));
|
|
25136
25667
|
const bytes = await readFile4(file2);
|
|
25137
25668
|
response.writeHead(200, { "Content-Type": contentType(name.toLowerCase()), "Cache-Control": "no-cache", "Content-Length": bytes.length });
|
|
25138
25669
|
response.end(bytes);
|
|
25139
25670
|
return;
|
|
25140
25671
|
}
|
|
25141
25672
|
const method = path3 === "/api/v1/status/refresh" ? "POST" : "GET";
|
|
25142
|
-
if (!["/api/v1/session", "/api/v1/status", "/api/v1/status/refresh", "/api/v1/specs"].includes(path3)) return fail8(response, 404, "NOT_FOUND", "
|
|
25673
|
+
if (!["/api/v1/session", "/api/v1/status", "/api/v1/status/refresh", "/api/v1/specs", "/api/v1/changelog"].includes(path3)) return fail8(response, 404, "NOT_FOUND", t2("server.apiNotFound"));
|
|
25143
25674
|
if (request.method !== method) {
|
|
25144
25675
|
response.setHeader("Allow", method);
|
|
25145
|
-
return fail8(response, 405, "METHOD_NOT_ALLOWED", "
|
|
25676
|
+
return fail8(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
|
|
25146
25677
|
}
|
|
25147
|
-
if (path3 === "/api/v1/session") return json2(response, 200, session);
|
|
25148
|
-
if (request.headers["x-gitifact-session"] !==
|
|
25678
|
+
if (path3 === "/api/v1/session") return json2(response, 200, store.session);
|
|
25679
|
+
if (request.headers["x-gitifact-session"] !== sessionId) return fail8(response, 409, "SESSION_CHANGED", t2("server.sessionChanged"));
|
|
25149
25680
|
if (path3 === "/api/v1/specs") {
|
|
25150
25681
|
const cursor = url2.searchParams.get("cursor") ?? "0";
|
|
25151
25682
|
const head = url2.searchParams.get("head");
|
|
25152
|
-
if ([...url2.searchParams.keys()].some((k) => !["cursor", "head"].includes(k)) || url2.searchParams.getAll("cursor").length > 1 || url2.searchParams.getAll("head").length > 1 || !/^(0|[1-9]\d{0,5})$/.test(cursor) || head !== null && !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) return fail8(response, 400, "BAD_REQUEST", "
|
|
25683
|
+
if ([...url2.searchParams.keys()].some((k) => !["cursor", "head"].includes(k)) || url2.searchParams.getAll("cursor").length > 1 || url2.searchParams.getAll("head").length > 1 || !/^(0|[1-9]\d{0,5})$/.test(cursor) || head !== null && !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) return fail8(response, 400, "BAD_REQUEST", t2("server.badRange"));
|
|
25153
25684
|
try {
|
|
25154
25685
|
json2(response, 200, await readSpecs(Number(cursor), head ?? void 0));
|
|
25155
25686
|
} catch (error62) {
|
|
25156
|
-
fail8(response, 503, "INTERNAL_ERROR", error62 instanceof Error ? error62.message : "
|
|
25687
|
+
fail8(response, 503, "INTERNAL_ERROR", error62 instanceof Error ? error62.message : t2("server.specsUnreadable"));
|
|
25157
25688
|
}
|
|
25158
25689
|
return;
|
|
25159
25690
|
}
|
|
25160
|
-
if (
|
|
25691
|
+
if (path3 === "/api/v1/changelog") {
|
|
25692
|
+
const language = url2.searchParams.get("lang") ?? defaultLanguage2;
|
|
25693
|
+
if ([...url2.searchParams.keys()].some((key) => key !== "lang") || url2.searchParams.getAll("lang").length > 1 || !/^[a-z]{2}(?:-[A-Z]{2})?$/.test(language)) return fail8(response, 400, "BAD_REQUEST", t2("server.badLanguage"));
|
|
25694
|
+
try {
|
|
25695
|
+
const own2 = await readChangelog(language);
|
|
25696
|
+
const text2 = own2 ?? (language === defaultLanguage2 ? null : await readChangelog(defaultLanguage2));
|
|
25697
|
+
if (text2 === null) return fail8(response, 404, "NOT_FOUND", t2("server.changelogNotFound"));
|
|
25698
|
+
json2(response, 200, changelogV1.parse({ contract: "changelog", version: 1, language: own2 === null ? defaultLanguage2 : language, fallback: own2 === null, entries: parseChangelog(text2) }));
|
|
25699
|
+
} catch (error62) {
|
|
25700
|
+
fail8(response, 503, "INTERNAL_ERROR", error62 instanceof Error ? error62.message : t2("server.changelogUnreadable"));
|
|
25701
|
+
}
|
|
25702
|
+
return;
|
|
25703
|
+
}
|
|
25704
|
+
if (method === "POST" && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", t2("server.refreshOrigin"));
|
|
25161
25705
|
const value = method === "POST" ? await store.refresh() : store.latest;
|
|
25162
25706
|
if (!response.destroyed) json2(response, value.ok ? 200 : 503, value);
|
|
25163
25707
|
return;
|
|
25164
25708
|
}
|
|
25165
25709
|
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
25166
25710
|
response.setHeader("Allow", "GET, HEAD");
|
|
25167
|
-
return fail8(response, 405, "METHOD_NOT_ALLOWED", "
|
|
25711
|
+
return fail8(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
|
|
25168
25712
|
}
|
|
25169
25713
|
let asset = assets.get(path3 === "/" ? "/index.html" : path3);
|
|
25170
25714
|
let assetPath = path3 === "/" ? "/index.html" : path3;
|
|
@@ -25172,13 +25716,13 @@ async function startBrowserServer(options) {
|
|
|
25172
25716
|
asset = assets.get("/index.html");
|
|
25173
25717
|
assetPath = "/index.html";
|
|
25174
25718
|
}
|
|
25175
|
-
if (!asset) return fail8(response, 404, "NOT_FOUND", "
|
|
25719
|
+
if (!asset) return fail8(response, 404, "NOT_FOUND", t2("server.fileNotFound"));
|
|
25176
25720
|
response.writeHead(200, { "Content-Type": contentType(assetPath), "Cache-Control": "no-cache", "Content-Length": asset.length });
|
|
25177
25721
|
response.end(request.method === "HEAD" ? void 0 : asset);
|
|
25178
25722
|
}
|
|
25179
25723
|
const server = createServer({ requestTimeout: 5e3, headersTimeout: 5e3, maxHeaderSize: 8192 }, (request, response) => {
|
|
25180
25724
|
void handle(request, response).catch(() => {
|
|
25181
|
-
if (!response.headersSent && !response.destroyed) fail8(response, 500, "INTERNAL_ERROR", "
|
|
25725
|
+
if (!response.headersSent && !response.destroyed) fail8(response, 500, "INTERNAL_ERROR", t2("server.internal"));
|
|
25182
25726
|
else response.destroy();
|
|
25183
25727
|
});
|
|
25184
25728
|
});
|
|
@@ -25196,12 +25740,18 @@ async function startBrowserServer(options) {
|
|
|
25196
25740
|
} catch (error62) {
|
|
25197
25741
|
options.signal?.removeEventListener("abort", onAbort);
|
|
25198
25742
|
controller.abort();
|
|
25199
|
-
if (error62.code === "EADDRINUSE") throw new Error("
|
|
25743
|
+
if (error62.code === "EADDRINUSE") throw new Error(t2("server.portInUse"));
|
|
25200
25744
|
throw error62;
|
|
25201
25745
|
}
|
|
25202
25746
|
const address = server.address();
|
|
25203
|
-
if (!address || typeof address === "string") throw new Error("
|
|
25747
|
+
if (!address || typeof address === "string") throw new Error(t2("server.addressUnknown"));
|
|
25204
25748
|
origin = "http://127.0.0.1:" + address.port;
|
|
25749
|
+
if (options.fetchLatest) {
|
|
25750
|
+
store.setUpdate(checkingUpdate);
|
|
25751
|
+
updatePending = resolveUpdate(store.session.cliVersion, options.fetchLatest, controller.signal, options.updateCheckTimeoutMs).then((state) => {
|
|
25752
|
+
store.setUpdate(state);
|
|
25753
|
+
});
|
|
25754
|
+
}
|
|
25205
25755
|
let resolveClosed;
|
|
25206
25756
|
const closed = new Promise((resolve) => {
|
|
25207
25757
|
resolveClosed = resolve;
|
|
@@ -25217,6 +25767,7 @@ async function startBrowserServer(options) {
|
|
|
25217
25767
|
server.closeAllConnections();
|
|
25218
25768
|
});
|
|
25219
25769
|
await store.pending;
|
|
25770
|
+
await updatePending;
|
|
25220
25771
|
options.signal?.removeEventListener("abort", onAbort);
|
|
25221
25772
|
options.signal?.removeEventListener("abort", closeOnAbort);
|
|
25222
25773
|
resolveClosed();
|
|
@@ -25228,15 +25779,28 @@ async function startBrowserServer(options) {
|
|
|
25228
25779
|
};
|
|
25229
25780
|
options.signal?.addEventListener("abort", closeOnAbort, { once: true });
|
|
25230
25781
|
if (options.signal?.aborted) void close();
|
|
25231
|
-
return { url: origin, session
|
|
25782
|
+
return { url: origin, get session() {
|
|
25783
|
+
return store.session;
|
|
25784
|
+
}, close, closed };
|
|
25232
25785
|
}
|
|
25233
25786
|
|
|
25787
|
+
// src/adapters/registry/latest-version.ts
|
|
25788
|
+
var manifestUrl = "https://registry.npmjs.org/gitifact";
|
|
25789
|
+
var fetchLatestVersion = async (signal) => {
|
|
25790
|
+
const response = await fetch(manifestUrl, { signal, redirect: "error", headers: { Accept: "application/vnd.npm.install-v1+json" } });
|
|
25791
|
+
if (!response.ok) throw new Error("registry status " + response.status);
|
|
25792
|
+
const manifest = await response.json();
|
|
25793
|
+
const latest = manifest["dist-tags"]?.latest;
|
|
25794
|
+
if (typeof latest !== "string") throw new Error("registry answer has no latest tag");
|
|
25795
|
+
return latest;
|
|
25796
|
+
};
|
|
25797
|
+
|
|
25234
25798
|
// src/commands/browser.ts
|
|
25235
25799
|
function parsePort(value) {
|
|
25236
|
-
if (!/^\d+$/.test(value) || Number(value) > 65535) throw new InvalidArgumentError("
|
|
25800
|
+
if (!/^\d+$/.test(value) || Number(value) > 65535) throw new InvalidArgumentError(t2("browser.invalidPort"));
|
|
25237
25801
|
return Number(value);
|
|
25238
25802
|
}
|
|
25239
|
-
async function runBrowser(options) {
|
|
25803
|
+
async function runBrowser(options, version2) {
|
|
25240
25804
|
const controller = new AbortController();
|
|
25241
25805
|
const stop = () => controller.abort();
|
|
25242
25806
|
process.once("SIGINT", stop);
|
|
@@ -25246,13 +25810,16 @@ async function runBrowser(options) {
|
|
|
25246
25810
|
cwd: process.cwd(),
|
|
25247
25811
|
port: options.port,
|
|
25248
25812
|
dev: options.dev ?? false,
|
|
25249
|
-
signal: controller.signal
|
|
25813
|
+
signal: controller.signal,
|
|
25814
|
+
cliVersion: version2,
|
|
25815
|
+
// --no-update-check or GITIFACT_NO_UPDATE_CHECK keeps the server from contacting the npm registry.
|
|
25816
|
+
...updateCheckDisabled(process.env, options.updateCheck === false) ? {} : { fetchLatest: fetchLatestVersion }
|
|
25250
25817
|
});
|
|
25251
25818
|
if (!controller.signal.aborted) process.stdout.write(server.url + "/\n");
|
|
25252
25819
|
await server.closed;
|
|
25253
25820
|
} catch (error62) {
|
|
25254
25821
|
if (!controller.signal.aborted) {
|
|
25255
|
-
process.stderr.write((error62 instanceof Error ? error62.message : "
|
|
25822
|
+
process.stderr.write((error62 instanceof Error ? error62.message : t2("browser.failed")) + "\n");
|
|
25256
25823
|
process.exitCode = 1;
|
|
25257
25824
|
}
|
|
25258
25825
|
} finally {
|
|
@@ -25288,9 +25855,9 @@ function initRepository(cwd, inherited = process.env) {
|
|
|
25288
25855
|
const gitDir = locations.length === 2 ? locations[0] : decodeGitLine(await git(["rev-parse", "--absolute-git-dir"], root));
|
|
25289
25856
|
const indexPath = locations.length === 2 ? locations[1] : decodeGitLine(await git(["rev-parse", "--path-format=absolute", "--git-path", "index"], root));
|
|
25290
25857
|
for (const marker2 of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"]) {
|
|
25291
|
-
if (await fileInfo(join5(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", "
|
|
25858
|
+
if (await fileInfo(join5(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
|
|
25292
25859
|
}
|
|
25293
|
-
if (state.changes.some((change2) => change2.kind === "unmerged")) throw new InitError("GIT_OPERATION_IN_PROGRESS", "
|
|
25860
|
+
if (state.changes.some((change2) => change2.kind === "unmerged")) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
25294
25861
|
const index = await readFile5(indexPath).catch((error62) => {
|
|
25295
25862
|
if (error62.code === "ENOENT") return Buffer.alloc(0);
|
|
25296
25863
|
throw error62;
|
|
@@ -25308,17 +25875,17 @@ function initRepository(cwd, inherited = process.env) {
|
|
|
25308
25875
|
async checkIgnore(root, path3 = ".gitifact/config.json") {
|
|
25309
25876
|
const output2 = (await git(["check-ignore", "--no-index", "-v", "-z", "--stdin"], root, [0, 1], Buffer.from(path3 + "\0"))).toString("utf8");
|
|
25310
25877
|
const fields2 = output2.split("\0");
|
|
25311
|
-
if (output2 && fields2[2] && !fields2[2].startsWith("!")) throw new InitError("CONFIG_IGNORED", "
|
|
25878
|
+
if (output2 && fields2[2] && !fields2[2].startsWith("!")) throw new InitError("CONFIG_IGNORED", t2("initRepo.configIgnored", { rule: fields2[0] + ":" + fields2[1] + " " + fields2[2] }));
|
|
25312
25879
|
},
|
|
25313
25880
|
async validateBaseline(config2, root, commit, format) {
|
|
25314
25881
|
if (config2.baseline.kind === "empty") return;
|
|
25315
25882
|
const baseline = config2.baseline;
|
|
25316
|
-
if (!commit || baseline.objectFormat !== format) throw new InitError("BASELINE_UNAVAILABLE", "
|
|
25883
|
+
if (!commit || baseline.objectFormat !== format) throw new InitError("BASELINE_UNAVAILABLE", t2("initRepo.baselineMismatch"));
|
|
25317
25884
|
try {
|
|
25318
25885
|
if (decodeGitLine(await git(["cat-file", "-t", baseline.commit], root)) !== "commit") throw new Error("not a commit");
|
|
25319
25886
|
await git(["merge-base", "--is-ancestor", baseline.commit, commit], root);
|
|
25320
25887
|
} catch {
|
|
25321
|
-
throw new InitError("BASELINE_UNAVAILABLE", "
|
|
25888
|
+
throw new InitError("BASELINE_UNAVAILABLE", t2("initRepo.baselineUnverified"));
|
|
25322
25889
|
}
|
|
25323
25890
|
}
|
|
25324
25891
|
};
|
|
@@ -25342,7 +25909,7 @@ async function managedPath(root, path3, create = false) {
|
|
|
25342
25909
|
info4 = await fileInfo(full);
|
|
25343
25910
|
}
|
|
25344
25911
|
if (info4 && (info4.isSymbolicLink() || (i < parts.length - 1 ? !info4.isDirectory() : !info4.isFile()))) {
|
|
25345
|
-
throw new InitError("PATH_CONFLICT", "
|
|
25912
|
+
throw new InitError("PATH_CONFLICT", t2("managedFile.notRegularPath", { path: path3 }));
|
|
25346
25913
|
}
|
|
25347
25914
|
}
|
|
25348
25915
|
return full;
|
|
@@ -25351,17 +25918,17 @@ async function managedRead(root, path3, limit = DEFAULT_LIMIT) {
|
|
|
25351
25918
|
const full = await managedPath(root, path3);
|
|
25352
25919
|
const before = await fileInfo(full);
|
|
25353
25920
|
if (!before) return null;
|
|
25354
|
-
if (before.size > limit) throw new InitError("FILE_TOO_LARGE", limit / 1024
|
|
25921
|
+
if (before.size > limit) throw new InitError("FILE_TOO_LARGE", t2("managedFile.tooLarge", { kib: limit / 1024, path: path3 }));
|
|
25355
25922
|
const bytes = await readFile6(full);
|
|
25356
25923
|
await managedPath(root, path3);
|
|
25357
25924
|
const after = await fileInfo(full);
|
|
25358
25925
|
if (!after || before.ino !== after.ino || before.dev !== after.dev || before.mtimeMs !== after.mtimeMs || bytes.length > limit) {
|
|
25359
|
-
throw new InitError("INPUT_CHANGED", "
|
|
25926
|
+
throw new InitError("INPUT_CHANGED", t2("managedFile.changedWhileReading", { path: path3 }));
|
|
25360
25927
|
}
|
|
25361
25928
|
try {
|
|
25362
25929
|
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
25363
25930
|
} catch {
|
|
25364
|
-
throw new InitError("INVALID_UTF8", "
|
|
25931
|
+
throw new InitError("INVALID_UTF8", t2("managedFile.notUtf8", { path: path3 }));
|
|
25365
25932
|
}
|
|
25366
25933
|
}
|
|
25367
25934
|
async function managedWrite(root, path3, previous, next, recheck) {
|
|
@@ -25372,12 +25939,12 @@ async function managedWrite(root, path3, previous, next, recheck) {
|
|
|
25372
25939
|
const unchanged = async () => {
|
|
25373
25940
|
await managedPath(root, path3);
|
|
25374
25941
|
const now = await fileInfo(directory);
|
|
25375
|
-
if (now?.ino !== owner?.ino || now?.dev !== owner?.dev || await realpath2(directory) !== canonical) throw new InitError("INPUT_CHANGED", "
|
|
25942
|
+
if (now?.ino !== owner?.ino || now?.dev !== owner?.dev || await realpath2(directory) !== canonical) throw new InitError("INPUT_CHANGED", t2("managedFile.targetChanged", { path: path3 }));
|
|
25376
25943
|
};
|
|
25377
25944
|
if (next === null) {
|
|
25378
25945
|
await recheck();
|
|
25379
25946
|
await unchanged();
|
|
25380
|
-
if (await managedRead(root, path3) !== previous) throw new InitError("INPUT_CHANGED", "
|
|
25947
|
+
if (await managedRead(root, path3) !== previous) throw new InitError("INPUT_CHANGED", t2("managedFile.removeTargetChanged", { path: path3 }));
|
|
25381
25948
|
if (previous !== null) await unlink3(full);
|
|
25382
25949
|
return;
|
|
25383
25950
|
}
|
|
@@ -25393,7 +25960,7 @@ async function managedWrite(root, path3, previous, next, recheck) {
|
|
|
25393
25960
|
}
|
|
25394
25961
|
await recheck();
|
|
25395
25962
|
await unchanged();
|
|
25396
|
-
if (await managedRead(root, path3) !== previous || await readFile6(temp, "utf8") !== next) throw new InitError("INPUT_CHANGED", "
|
|
25963
|
+
if (await managedRead(root, path3) !== previous || await readFile6(temp, "utf8") !== next) throw new InitError("INPUT_CHANGED", t2("managedFile.publishTargetChanged", { path: path3 }));
|
|
25397
25964
|
if (previous === null) await link2(temp, full);
|
|
25398
25965
|
else await rename2(temp, full);
|
|
25399
25966
|
} finally {
|
|
@@ -25403,21 +25970,17 @@ async function managedWrite(root, path3, previous, next, recheck) {
|
|
|
25403
25970
|
}
|
|
25404
25971
|
}
|
|
25405
25972
|
|
|
25973
|
+
// src/commands/agent-block.ts
|
|
25974
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
25975
|
+
|
|
25406
25976
|
// src/commands/docs.ts
|
|
25407
25977
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
25408
25978
|
var docTopics = ["workflow", "spec", "design", "product", "commit"];
|
|
25409
|
-
var summaries = {
|
|
25410
|
-
workflow: "\uC2DC\uC791 \uC2DC \uD655\uC778\uD560 \uAC83, \uC694\uAD6C\uC0AC\uD56D\uC73C\uB85C \uB0A8\uAE38 \uC694\uCCAD\uC758 \uAD6C\uBD84, \uB9C8\uBB34\uB9AC \uBCF4\uACE0",
|
|
25411
|
-
spec: "\uC0AC\uC6A9\uC790 \uC2A4\uD1A0\uB9AC\xB7\uC218\uC6A9 \uC870\uAC74 \uD615\uC2DD, ID \uADDC\uCE59, spec save \uC785\uB825",
|
|
25412
|
-
design: "design.md \uBAA9\uCC28, \uCC38\uC870 \uC8FC\uC11D, \uAC1C\uC815 \uBC29\uC2DD",
|
|
25413
|
-
product: "PRODUCT.md\uC640 guides \uBB38\uC11C\uC758 \uC5ED\uD560\uACFC \uC800\uC7A5 \uBA85\uB839",
|
|
25414
|
-
commit: "spec commit \uC785\uB825, \uC774\uC720 \uAE30\uB85D, \uC2E4\uD328 \uD6C4 \uBCF5\uAD6C"
|
|
25415
|
-
};
|
|
25416
25979
|
var isDocTopic = (value) => docTopics.includes(value);
|
|
25417
|
-
var readBundled = (topic) => readFile7(new URL("./docs/" + topic + ".md", import.meta.url), "utf8");
|
|
25418
|
-
function listDocTopics() {
|
|
25980
|
+
var readBundled = (topic, lang) => readFile7(new URL("./i18n/" + lang + "/docs/" + topic + ".md", import.meta.url), "utf8");
|
|
25981
|
+
function listDocTopics(lang = defaultLanguage2) {
|
|
25419
25982
|
const width = Math.max(...docTopics.map((topic) => topic.length));
|
|
25420
|
-
return docTopics.map((topic) => topic.padEnd(width) + " " +
|
|
25983
|
+
return docTopics.map((topic) => topic.padEnd(width) + " " + t2(`docs.summary.${topic}`, {}, lang)).join("\n") + "\n";
|
|
25421
25984
|
}
|
|
25422
25985
|
async function runDocs(topic, controls = {}) {
|
|
25423
25986
|
if (topic === void 0) {
|
|
@@ -25425,12 +25988,12 @@ async function runDocs(topic, controls = {}) {
|
|
|
25425
25988
|
return;
|
|
25426
25989
|
}
|
|
25427
25990
|
if (!isDocTopic(topic)) {
|
|
25428
|
-
const failure2 = { contract: "docs", version: 1, ok: false, error: { code: "UNKNOWN_TOPIC", message: "
|
|
25991
|
+
const failure2 = { contract: "docs", version: 1, ok: false, error: { code: "UNKNOWN_TOPIC", message: t2("docs.unknownTopic", { topic, topics: docTopics.join(", ") }) } };
|
|
25429
25992
|
process.stderr.write(JSON.stringify(failure2) + "\n");
|
|
25430
25993
|
process.exitCode = 1;
|
|
25431
25994
|
return;
|
|
25432
25995
|
}
|
|
25433
|
-
process.stdout.write(await (controls.readDoc ?? readBundled)(topic));
|
|
25996
|
+
process.stdout.write(await (controls.readDoc ?? readBundled)(topic, defaultLanguage2));
|
|
25434
25997
|
}
|
|
25435
25998
|
|
|
25436
25999
|
// src/commands/agent-block.ts
|
|
@@ -25448,52 +26011,21 @@ function boilerplateFor(path3) {
|
|
|
25448
26011
|
const name = path3 === "AGENTS.md" ? path3 : path3.split("/").pop().replace(/^\./, "").replace(/\.md$/, "");
|
|
25449
26012
|
return "# " + name + "\n\nProject-specific guidance for AI coding agents.\n";
|
|
25450
26013
|
}
|
|
25451
|
-
|
|
25452
|
-
|
|
25453
|
-
|
|
25454
|
-
|
|
25455
|
-
|
|
25456
|
-
"",
|
|
25457
|
-
"\uC2DC\uC791\uD560 \uB54C:",
|
|
25458
|
-
"- `gitifact spec working`\uC73C\uB85C \uC81C\uD488 \uC124\uBA85\xB7\uC9C0\uCE68\xB7\uAE30\uB2A5 \uBA85\uC138\uB97C \uC77D\uACE0 git status\uC640 \uAE30\uC874 staging\uC744 \uD655\uC778\uD55C\uB2E4.",
|
|
25459
|
-
"- \uC774 \uBE14\uB85D\uC740 \uC694\uC57D\uC774\uB2E4. \uC0C1\uC138 \uD615\uC2DD\uC740 `gitifact docs <topic>`\uC73C\uB85C \uC77D\uACE0 \uAE30\uC5B5\uC73C\uB85C \uCC44\uC6B0\uC9C0 \uC54A\uB294\uB2E4.",
|
|
25460
|
-
"",
|
|
25461
|
-
"\uBB34\uC5C7\uC744 \uC694\uAD6C\uC0AC\uD56D\uC73C\uB85C \uB0A8\uAE30\uB294\uAC00 (\uC81C\uD488 \uB3D9\uC791\uACFC \uC720\uC9C0\uD560 \uC81C\uC57D\uB9CC):",
|
|
25462
|
-
"| \uC694\uCCAD | \uCC98\uB9AC |",
|
|
25463
|
-
"| --- | --- |",
|
|
25464
|
-
"| \uAC8C\uC2DC\uBB3C\uC744 \uC0AD\uC81C\uD560 \uC218 \uC788\uAC8C \uD574\uC8FC\uC138\uC694 | \uC694\uAD6C\uC0AC\uD56D\uC73C\uB85C \uC815\uB9AC\uD55C\uB2E4 |",
|
|
25465
|
-
"| \uC774 \uB0B4\uBD80 \uD568\uC218 \uC774\uB984\uC744 \uBC14\uAFD4\uC8FC\uC138\uC694 | \uC77C\uBC18 \uAD6C\uD604 \uBCC0\uACBD\uC774\uB2E4 |",
|
|
25466
|
-
"| \uC9C0\uAE08 \uD478\uC2DC\uD574\uC8FC\uC138\uC694 | \uC791\uC5C5 \uC9C0\uC2DC\uB2E4. \uB4F1\uB85D\uD558\uC9C0 \uC54A\uB294\uB2E4 |",
|
|
25467
|
-
"| \uC678\uBD80 \uC11C\uBE44\uC2A4 \uC5C6\uC774 \uB3D9\uC791\uD574\uC57C \uD569\uB2C8\uB2E4 | \uC81C\uD488 \uC81C\uC57D\uC73C\uB85C \uBA85\uC138\uC5D0 \uBC18\uC601\uD55C\uB2E4 |",
|
|
25468
|
-
"",
|
|
25469
|
-
"\uADDC\uCE59:",
|
|
25470
|
-
"- \uBA85\uC138\uB97C \uC800\uC7A5\uD558\uAE30 \uC804\uC5D0 `gitifact docs spec`\uC744 \uC77D\uB294\uB2E4. ID\uB294 CLI\uAC00 \uBC1C\uAE09\uD55C \uAC12\uB9CC \uC4F4\uB2E4.",
|
|
25471
|
-
"- \uC0C8 \uAE30\uB2A5\uC740 requirements.md\uC640 design.md\uB97C \uD568\uAED8 \uC815\uB9AC\uD55C\uB2E4(`gitifact docs design`). \uC694\uAD6C\uC0AC\uD56D\uB9CC \uC694\uCCAD\uBC1B\uC73C\uBA74 \uB530\uB978\uB2E4.",
|
|
25472
|
-
"- \uCEE4\uBC0B \uC694\uCCAD\uC744 \uBC1B\uC73C\uBA74 `gitifact docs commit`\uC744 \uC77D\uACE0 \uBA85\uC138\xB7\uC774\uC720\xB7\uCF54\uB4DC\xB7\uD14C\uC2A4\uD2B8\uB97C \uD568\uAED8 \uCEE4\uBC0B\uD55C\uB2E4.",
|
|
25473
|
-
"- \uC790\uB3D9 \uAE30\uB85D\uC740 \uCEE4\uBC0B \uAD8C\uD55C\uC774 \uC544\uB2C8\uB2E4. \uC0AC\uC6A9\uC790 \uC694\uCCAD\uC774\uB098 \uBA85\uC2DC\uC801 \uD504\uB85C\uC81D\uD2B8 \uC815\uCC45\uC774 \uC788\uC744 \uB54C\uB9CC \uCEE4\uBC0B\uD558\uACE0 \uD478\uC2DC\uB294 \uBCC4\uB3C4 \uC694\uCCAD\uC744 \uB530\uB978\uB2E4.",
|
|
25474
|
-
"- \uBD88\uBA85\uD655\uD55C \uC81C\uD488 \uB3D9\uC791\uB9CC \uC9C8\uBB38\uD558\uACE0 \uB3C5\uB9BD\uC801\uC778 \uC791\uC5C5\uC740 \uC9C4\uD589\uD55C\uB2E4. \uAE30\uC874 \uAE30\uB2A5 \uC804\uCCB4 \uB3C4\uCD9C\uC740 \uC694\uCCAD\uBC1B\uC558\uC744 \uB54C \uD55C\uB2E4.",
|
|
25475
|
-
"- SELF-CHECK: save\xB7commit \uC785\uB825\uC744 \uB9CC\uB4E4\uAE30 \uC804\uC5D0 \uD574\uB2F9 docs\uB97C \uB2E4\uC2DC \uC77D\uACE0 \uD615\uC2DD\uC744 \uB300\uC870\uD55C\uB2E4. \uD655\uC2E4\uD558\uC9C0 \uC54A\uC73C\uBA74 \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 `gitifact docs <topic>`\uC744 \uC2E4\uD589\uD55C\uB2E4.",
|
|
25476
|
-
"",
|
|
25477
|
-
"MORE CLI:",
|
|
25478
|
-
" docs <topic> " + docTopics.join(", "),
|
|
25479
|
-
" spec working \uD604\uC7AC \uBA85\uC138\xB7\uC81C\uD488\xB7\uC9C0\uCE68 \uC804\uCCB4\uC640 stamp",
|
|
25480
|
-
" spec save --file <json>: \uC694\uAD6C\uC0AC\uD56D\xB7\uC124\uACC4\xB7\uBB38\uC11C \uC800\uC7A5",
|
|
25481
|
-
" spec commit --file <json>: \uBCC0\uACBD \uC774\uC720 \uAE30\uB85D\uACFC \uCEE4\uBC0B\uC744 \uD55C \uBC88\uC5D0",
|
|
25482
|
-
" browser \uC77D\uAE30 \uC804\uC6A9 \uBE0C\uB77C\uC6B0\uC800 \uC5F4\uAE30",
|
|
25483
|
-
" init \uB2E4\uC2DC \uC2E4\uD589\uD558\uBA74 \uC774 \uBE14\uB85D\uC744 \uAC31\uC2E0\uD55C\uB2E4",
|
|
25484
|
-
AGENT_END
|
|
25485
|
-
];
|
|
25486
|
-
return lines.join("\n");
|
|
26014
|
+
var readBundledBlock = (lang) => readFile8(new URL("./i18n/" + lang + "/block.md", import.meta.url), "utf8");
|
|
26015
|
+
async function renderAgentBlock(version2, controls = {}, lang = defaultLanguage2) {
|
|
26016
|
+
const body = await (controls.readBlock ?? readBundledBlock)(lang);
|
|
26017
|
+
const filled = body.trimEnd().replace(/\{(version|language|topics)\}/g, (_whole, name) => name === "version" ? version2 : name === "language" ? lang : docTopics.join(", "));
|
|
26018
|
+
return AGENT_START + "\n" + filled + "\n" + AGENT_END;
|
|
25487
26019
|
}
|
|
25488
26020
|
function findBlock(text2) {
|
|
25489
26021
|
const start = text2.indexOf(AGENT_START);
|
|
25490
26022
|
if (start === -1) {
|
|
25491
|
-
if (text2.includes(AGENT_END)) throw new InitError("AGENT_DOCS_MALFORMED", "
|
|
26023
|
+
if (text2.includes(AGENT_END)) throw new InitError("AGENT_DOCS_MALFORMED", t2("agentBlock.endWithoutStart"));
|
|
25492
26024
|
return null;
|
|
25493
26025
|
}
|
|
25494
26026
|
const end = text2.indexOf(AGENT_END, start + AGENT_START.length);
|
|
25495
|
-
if (end === -1) throw new InitError("AGENT_DOCS_MALFORMED", "
|
|
25496
|
-
if (text2.indexOf(AGENT_START, start + AGENT_START.length) !== -1) throw new InitError("AGENT_DOCS_MALFORMED", "
|
|
26027
|
+
if (end === -1) throw new InitError("AGENT_DOCS_MALFORMED", t2("agentBlock.startWithoutEnd"));
|
|
26028
|
+
if (text2.indexOf(AGENT_START, start + AGENT_START.length) !== -1) throw new InitError("AGENT_DOCS_MALFORMED", t2("agentBlock.duplicateStart"));
|
|
25497
26029
|
return { start, end: end + AGENT_END.length };
|
|
25498
26030
|
}
|
|
25499
26031
|
function isWrapperFile(text2) {
|
|
@@ -25555,8 +26087,8 @@ async function planAgentDocs(root, options) {
|
|
|
25555
26087
|
}
|
|
25556
26088
|
return { mode: "remove", paths: paths2, writes };
|
|
25557
26089
|
}
|
|
25558
|
-
const block = renderAgentBlock(options.version);
|
|
25559
|
-
const { inject, create } = resolveAgentPaths(options.agent, existing);
|
|
26090
|
+
const block = await renderAgentBlock(options.version, options);
|
|
26091
|
+
const { inject, create } = options.onlyExisting ? { inject: candidatePaths.filter((path3) => existing.has(path3) && findBlock(existing.get(path3)) && !isWrapperFile(existing.get(path3))), create: null } : resolveAgentPaths(options.agent, existing);
|
|
25560
26092
|
for (const path3 of inject) {
|
|
25561
26093
|
const previous = existing.get(path3);
|
|
25562
26094
|
const next = injectBlock(previous, block, boilerplateFor(path3));
|
|
@@ -25597,10 +26129,10 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
|
|
|
25597
26129
|
});
|
|
25598
26130
|
const existing = async (text3) => {
|
|
25599
26131
|
const config3 = parseManagedConfig(text3);
|
|
25600
|
-
if (!("schemaVersion" in config3)) throw new InitError("MIGRATION_REQUIRED", "
|
|
26132
|
+
if (!("schemaVersion" in config3)) throw new InitError("MIGRATION_REQUIRED", t2("init.migrationRequired"));
|
|
25601
26133
|
await repo.validateBaseline(config3, root, first.state.head.commit, first.state.repository.objectFormat);
|
|
25602
26134
|
const unchanged = async () => {
|
|
25603
|
-
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !== text3) throw new InitError("INPUT_CHANGED", "
|
|
26135
|
+
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !== text3) throw new InitError("INPUT_CHANGED", t2("init.inputChanged"));
|
|
25604
26136
|
};
|
|
25605
26137
|
await unchanged();
|
|
25606
26138
|
if (!dryRun) await applyAgentDocs(root, docsPlan, unchanged);
|
|
@@ -25608,22 +26140,22 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
|
|
|
25608
26140
|
};
|
|
25609
26141
|
const old = await readConfigFile(root);
|
|
25610
26142
|
if (old !== void 0) return existing(old);
|
|
25611
|
-
if (first.trackedConfig) throw new InitError("CONFIG_DELETED", "
|
|
26143
|
+
if (first.trackedConfig) throw new InitError("CONFIG_DELETED", t2("init.configDeleted"));
|
|
25612
26144
|
const checkRecords = async () => {
|
|
25613
|
-
if (await fileInfo(join7(root, "specs"))) throw new InitError("EXISTING_RECORDS", "
|
|
26145
|
+
if (await fileInfo(join7(root, "specs"))) throw new InitError("EXISTING_RECORDS", t2("init.existingSpecs"));
|
|
25614
26146
|
const entries = await readdir3(join7(root, ".gitifact")).catch((e) => {
|
|
25615
26147
|
if (e.code === "ENOENT") return [];
|
|
25616
26148
|
throw e;
|
|
25617
26149
|
});
|
|
25618
|
-
if (entries.some((name) => !/^\.init-[a-f0-9-]+\.tmp$/.test(name))) throw new InitError("EXISTING_RECORDS", "
|
|
26150
|
+
if (entries.some((name) => !/^\.init-[a-f0-9-]+\.tmp$/.test(name))) throw new InitError("EXISTING_RECORDS", t2("init.orphanStore"));
|
|
25619
26151
|
};
|
|
25620
26152
|
const config2 = { schemaVersion: 1, baseline: first.state.head.commit ? { kind: "commit", objectFormat: first.state.repository.objectFormat, commit: first.state.head.commit } : { kind: "empty" } };
|
|
25621
26153
|
const text2 = JSON.stringify(config2, null, 2) + "\n";
|
|
25622
26154
|
const recheck = async () => {
|
|
25623
26155
|
await checkRecords();
|
|
25624
26156
|
await repo.checkIgnore(root);
|
|
25625
|
-
if ((await repo.inspect()).stamp !== first.stamp) throw new InitError("INPUT_CHANGED", "
|
|
25626
|
-
if (await readConfigFile(root) !== void 0) throw new InitError("CONFIG_APPEARED", "
|
|
26157
|
+
if ((await repo.inspect()).stamp !== first.stamp) throw new InitError("INPUT_CHANGED", t2("init.headOrIndexChanged"));
|
|
26158
|
+
if (await readConfigFile(root) !== void 0) throw new InitError("CONFIG_APPEARED", t2("init.configAppeared"));
|
|
25627
26159
|
};
|
|
25628
26160
|
await recheck();
|
|
25629
26161
|
if (dryRun) return result(config2, "planned");
|
|
@@ -25637,7 +26169,7 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
|
|
|
25637
26169
|
throw error62;
|
|
25638
26170
|
}
|
|
25639
26171
|
const published = async () => {
|
|
25640
|
-
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !== text2) throw new InitError("INPUT_CHANGED_AFTER_WRITE", "
|
|
26172
|
+
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !== text2) throw new InitError("INPUT_CHANGED_AFTER_WRITE", t2("init.changedAfterWrite"));
|
|
25641
26173
|
};
|
|
25642
26174
|
await published();
|
|
25643
26175
|
await applyAgentDocs(root, docsPlan, published);
|
|
@@ -25655,22 +26187,80 @@ async function runInit(options, version2) {
|
|
|
25655
26187
|
{ version: version2, agent: options.agent, remove: options.removeAgents, skip: options.skipAgents }
|
|
25656
26188
|
);
|
|
25657
26189
|
if (!dto.ok) throw new Error("unreachable");
|
|
25658
|
-
const docs = dto.agentDocs.mode === "skip" ? "
|
|
26190
|
+
const docs = dto.agentDocs.mode === "skip" ? t2("init.text.skipped") : dto.agentDocs.paths.join(", ") + (dto.agentDocs.mode === "remove" ? " (" + t2("init.text.blockRemoved") + ")" : dto.outcome === "planned" ? " (" + t2("init.text.blockPlanned") + ")" : " (" + t2("init.text.blockUpdated") + ")");
|
|
25659
26191
|
process.stdout.write(options.format === "text" ? `${dto.outcome}: ${dto.rootPath}/.gitifact/config.json
|
|
25660
|
-
|
|
25661
|
-
|
|
26192
|
+
${t2("init.text.storage")}: schemaVersion 1
|
|
26193
|
+
${t2("init.text.agentDocs")}: ${docs}
|
|
25662
26194
|
` : JSON.stringify(dto) + "\n");
|
|
25663
26195
|
} catch (error62) {
|
|
25664
26196
|
const known = error62 instanceof InitError || error62 instanceof RepositoryReadError;
|
|
25665
|
-
const failure2 = { code: known ? error62.code : "INIT_FAILED", message: known ? error62.message : "
|
|
26197
|
+
const failure2 = { code: known ? error62.code : "INIT_FAILED", message: known ? error62.message : t2("init.failed") };
|
|
25666
26198
|
process.stderr.write(options.format === "text" ? failure2.code + ": " + failure2.message + "\n" : JSON.stringify(projectInitV4.parse({ contract: "project-init", version: 4, ok: false, error: failure2 })) + "\n");
|
|
25667
26199
|
process.exitCode = 1;
|
|
25668
26200
|
}
|
|
25669
26201
|
}
|
|
25670
26202
|
|
|
26203
|
+
// src/commands/update.ts
|
|
26204
|
+
async function refreshBlocks(cwd, version2, env, controls) {
|
|
26205
|
+
const repo = initRepository(cwd, env);
|
|
26206
|
+
let first;
|
|
26207
|
+
let config2;
|
|
26208
|
+
try {
|
|
26209
|
+
first = await repo.inspect();
|
|
26210
|
+
config2 = await readConfigFile(first.state.repository.rootPath);
|
|
26211
|
+
} catch (error62) {
|
|
26212
|
+
if (error62 instanceof RepositoryReadError && error62.code === "NOT_A_REPOSITORY" || error62 instanceof InitError && error62.code === "MIGRATION_REQUIRED") return { state: "not-initialized", paths: [] };
|
|
26213
|
+
throw error62;
|
|
26214
|
+
}
|
|
26215
|
+
if (config2 === void 0) return { state: "not-initialized", paths: [] };
|
|
26216
|
+
const root = first.state.repository.rootPath;
|
|
26217
|
+
const plan = await planAgentDocs(root, { version: version2, onlyExisting: true, ...controls });
|
|
26218
|
+
if (plan.paths.length === 0) return { state: "no-block", paths: [] };
|
|
26219
|
+
if (plan.writes.length === 0) return { state: "current", paths: plan.paths };
|
|
26220
|
+
const unchanged = async () => {
|
|
26221
|
+
if ((await repo.inspect()).stamp !== first.stamp || await readConfigFile(root) !== config2) throw new InitError("INPUT_CHANGED", t2("init.inputChanged"));
|
|
26222
|
+
};
|
|
26223
|
+
return { state: "refreshed", paths: await applyAgentDocs(root, plan, unchanged) };
|
|
26224
|
+
}
|
|
26225
|
+
async function updateCommand(cwd, version2, env = process.env, controls = {}) {
|
|
26226
|
+
const [update, agentDocs] = await Promise.all([
|
|
26227
|
+
updateCheckDisabled(env) ? disabledUpdate : resolveUpdate(version2, controls.fetchLatest ?? fetchLatestVersion, void 0, controls.timeoutMs),
|
|
26228
|
+
refreshBlocks(cwd, version2, env, controls)
|
|
26229
|
+
]);
|
|
26230
|
+
return updateV1.parse({
|
|
26231
|
+
contract: "update",
|
|
26232
|
+
version: 1,
|
|
26233
|
+
ok: true,
|
|
26234
|
+
cliVersion: version2,
|
|
26235
|
+
update,
|
|
26236
|
+
install: update.status === "available" ? { npmGlobal: npmGlobalInstall(update.latestVersion) } : null,
|
|
26237
|
+
agentDocs
|
|
26238
|
+
});
|
|
26239
|
+
}
|
|
26240
|
+
async function runUpdate(options, version2) {
|
|
26241
|
+
try {
|
|
26242
|
+
const dto = await updateCommand(process.cwd(), version2);
|
|
26243
|
+
if (!dto.ok) throw new Error("unreachable");
|
|
26244
|
+
if (options.format !== "text") {
|
|
26245
|
+
process.stdout.write(JSON.stringify(dto) + "\n");
|
|
26246
|
+
return;
|
|
26247
|
+
}
|
|
26248
|
+
const lines = [t2("update.text.current", { version: dto.cliVersion })];
|
|
26249
|
+
lines.push(dto.update.status === "available" ? t2("update.text.available", { version: dto.update.latestVersion }) : dto.update.status === "up-to-date" ? t2("update.text.upToDate") : dto.update.status === "disabled" ? t2("update.text.disabled") : t2("update.text.unavailable"));
|
|
26250
|
+
if (dto.install) lines.push(t2("update.text.install", { command: dto.install.npmGlobal }), t2("update.text.afterInstall"));
|
|
26251
|
+
lines.push(dto.agentDocs.state === "refreshed" ? t2("update.text.blockRefreshed", { paths: dto.agentDocs.paths.join(", ") }) : dto.agentDocs.state === "current" ? t2("update.text.blockCurrent", { paths: dto.agentDocs.paths.join(", ") }) : dto.agentDocs.state === "no-block" ? t2("update.text.noBlock") : t2("update.text.notInitialized"));
|
|
26252
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
26253
|
+
} catch (error62) {
|
|
26254
|
+
const known = error62 instanceof InitError || error62 instanceof RepositoryReadError;
|
|
26255
|
+
const failure2 = { code: known ? error62.code : "UPDATE_FAILED", message: known ? error62.message : t2("update.failed") };
|
|
26256
|
+
process.stderr.write(options.format === "text" ? failure2.code + ": " + failure2.message + "\n" : JSON.stringify(updateV1.parse({ contract: "update", version: 1, ok: false, error: failure2 })) + "\n");
|
|
26257
|
+
process.exitCode = 1;
|
|
26258
|
+
}
|
|
26259
|
+
}
|
|
26260
|
+
|
|
25671
26261
|
// src/commands/spec-preview.ts
|
|
25672
26262
|
import { join as join12 } from "node:path";
|
|
25673
|
-
import { readFile as
|
|
26263
|
+
import { readFile as readFile12, stat as stat2 } from "node:fs/promises";
|
|
25674
26264
|
|
|
25675
26265
|
// src/adapters/filesystem/spec-preview-prepare.ts
|
|
25676
26266
|
import { lstat as lstat4 } from "node:fs/promises";
|
|
@@ -25691,7 +26281,7 @@ async function readPreviewContext(cwd) {
|
|
|
25691
26281
|
if (e.code === "ENOENT") return void 0;
|
|
25692
26282
|
throw e;
|
|
25693
26283
|
});
|
|
25694
|
-
if (exists) fail5("
|
|
26284
|
+
if (exists) fail5(t2("prepare.integrationInProgress"));
|
|
25695
26285
|
}
|
|
25696
26286
|
};
|
|
25697
26287
|
await checkOperation();
|
|
@@ -25702,7 +26292,7 @@ async function readPreviewContext(cwd) {
|
|
|
25702
26292
|
const specs = bundle.specs;
|
|
25703
26293
|
const recheck = async () => {
|
|
25704
26294
|
await checkOperation();
|
|
25705
|
-
if (!same(base, await reader.baseline())) fail5("
|
|
26295
|
+
if (!same(base, await reader.baseline())) fail5(t2("prepare.headChanged"));
|
|
25706
26296
|
};
|
|
25707
26297
|
return { reader, base, files, specs, bundle, recheck, working };
|
|
25708
26298
|
}
|
|
@@ -25716,12 +26306,12 @@ async function readFinalPreviewChanges(cwd) {
|
|
|
25716
26306
|
return { base: c.base, expected: expected(c.base, current.stamp), stamp: current.stamp, pendingReasons, ...delta };
|
|
25717
26307
|
}
|
|
25718
26308
|
async function prepareWorkingPreview(cwd, input2, publish) {
|
|
25719
|
-
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail5("
|
|
26309
|
+
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail5(t2("prepare.invalidInput"));
|
|
25720
26310
|
const request = input2;
|
|
25721
|
-
if (Object.keys(request).sort().join(",") !== "expected,reasons" || typeof request.expected !== "string") fail5("
|
|
26311
|
+
if (Object.keys(request).sort().join(",") !== "expected,reasons" || typeof request.expected !== "string") fail5(t2("prepare.expectedReasons"));
|
|
25722
26312
|
const c = await context(cwd);
|
|
25723
26313
|
const current = await readWorkingPreviewState(cwd);
|
|
25724
|
-
if (request.expected !== expected(c.base, current.stamp)) fail5("
|
|
26314
|
+
if (request.expected !== expected(c.base, current.stamp)) fail5(t2("prepare.staleInput"));
|
|
25725
26315
|
const result = await previewTransaction(cwd, current.stamp, async (before) => {
|
|
25726
26316
|
await c.recheck();
|
|
25727
26317
|
const prepared = prepareSpecPreview(c.bundle, before.bundle, c.files, before.files, request.reasons, () => generatePreviewId("H"));
|
|
@@ -25730,44 +26320,44 @@ async function prepareWorkingPreview(cwd, input2, publish) {
|
|
|
25730
26320
|
return { ...result, base: c.base, expected: expected(c.base, result.stamp), verification: { base: c.base, stamp: result.stamp } };
|
|
25731
26321
|
}
|
|
25732
26322
|
async function verifyPreparedPreview(cwd, input2, staged) {
|
|
25733
|
-
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail5("
|
|
26323
|
+
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail5(t2("prepare.invalidVerifyInput"));
|
|
25734
26324
|
const request = input2;
|
|
25735
|
-
if (Object.keys(request).sort().join(",") !== "base,stamp" || typeof request.stamp !== "string") fail5("prepare
|
|
26325
|
+
if (Object.keys(request).sort().join(",") !== "base,stamp" || typeof request.stamp !== "string") fail5(t2("prepare.verificationRequired"));
|
|
25736
26326
|
const c = await context(cwd);
|
|
25737
26327
|
const current = await readWorkingPreviewState(cwd);
|
|
25738
|
-
if (!same(request.base, c.base) || request.stamp !== current.stamp) fail5("
|
|
26328
|
+
if (!same(request.base, c.base) || request.stamp !== current.stamp) fail5(t2("prepare.changedAfterPrepare"));
|
|
25739
26329
|
finalSpecPreviewChanges(c.bundle, current.bundle);
|
|
25740
26330
|
comparePreviewBundles(c.bundle, current.bundle);
|
|
25741
26331
|
if (staged) {
|
|
25742
26332
|
const index = await c.reader.index();
|
|
25743
|
-
if (index.size !== current.files.size) fail5("
|
|
26333
|
+
if (index.size !== current.files.size) fail5(t2("prepare.stagingScope"));
|
|
25744
26334
|
for (const [path3, source] of current.files) {
|
|
25745
26335
|
const oid2 = index.get(path3);
|
|
25746
26336
|
const bytes = Buffer.from(source);
|
|
25747
26337
|
const hash3 = createHash4(oid2?.length === 64 ? "sha256" : "sha1").update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
|
|
25748
|
-
if (oid2 !== hash3) fail5("
|
|
26338
|
+
if (oid2 !== hash3) fail5(t2("prepare.stagingContent", { path: path3 }));
|
|
25749
26339
|
}
|
|
25750
|
-
if (!same([...index], [...await c.reader.index()])) fail5("
|
|
26340
|
+
if (!same([...index], [...await c.reader.index()])) fail5(t2("prepare.stagingChanged"));
|
|
25751
26341
|
}
|
|
25752
|
-
if ((await readWorkingPreviewState(cwd)).stamp !== current.stamp) fail5("
|
|
26342
|
+
if ((await readWorkingPreviewState(cwd)).stamp !== current.stamp) fail5(t2("prepare.specsChanged"));
|
|
25753
26343
|
await c.recheck();
|
|
25754
26344
|
return { verified: true, scope: staged ? "staged" : "working", base: c.base, stamp: current.stamp };
|
|
25755
26345
|
}
|
|
25756
26346
|
|
|
25757
26347
|
// src/commands/spec-preview-commit.ts
|
|
25758
26348
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
25759
|
-
import { readFile as
|
|
26349
|
+
import { readFile as readFile10, mkdir as mkdir4, open as open4, rename as rename3, unlink as unlink4, rmdir as rmdir2, writeFile as writeFile2 } from "node:fs/promises";
|
|
25760
26350
|
import { join as join10 } from "node:path";
|
|
25761
26351
|
|
|
25762
26352
|
// src/commands/spec-commit-files.ts
|
|
25763
26353
|
import { createHash as createHash5 } from "node:crypto";
|
|
25764
|
-
import { lstat as lstat5, readFile as
|
|
26354
|
+
import { lstat as lstat5, readFile as readFile9 } from "node:fs/promises";
|
|
25765
26355
|
import { join as join9 } from "node:path";
|
|
25766
26356
|
var fail6 = (message) => {
|
|
25767
26357
|
throw new SpecPreviewError(message);
|
|
25768
26358
|
};
|
|
25769
26359
|
var hash2 = (value) => createHash5("sha256").update(value).digest("hex");
|
|
25770
|
-
var optional2 = (path3) =>
|
|
26360
|
+
var optional2 = (path3) => readFile9(path3).catch((e) => {
|
|
25771
26361
|
if (e.code === "ENOENT") return null;
|
|
25772
26362
|
throw e;
|
|
25773
26363
|
});
|
|
@@ -25777,7 +26367,7 @@ var info2 = (path3) => lstat5(path3).catch((e) => {
|
|
|
25777
26367
|
});
|
|
25778
26368
|
var record2 = (path3) => recordPathPattern.test(path3);
|
|
25779
26369
|
function validPath2(path3) {
|
|
25780
|
-
if (typeof path3 !== "string" || path3.length > 1e3 || /[\\:\x00-\x1f\x7f]/.test(path3) || path3.split("/").some((p) => !p || p === "." || p === ".." || p.toLowerCase() === ".git")) fail6("
|
|
26370
|
+
if (typeof path3 !== "string" || path3.length > 1e3 || /[\\:\x00-\x1f\x7f]/.test(path3) || path3.split("/").some((p) => !p || p === "." || p === ".." || p.toLowerCase() === ".git")) fail6(t2("commitFiles.relativePath"));
|
|
25781
26371
|
}
|
|
25782
26372
|
async function fingerprint(root, path3) {
|
|
25783
26373
|
validPath2(path3);
|
|
@@ -25786,25 +26376,25 @@ async function fingerprint(root, path3) {
|
|
|
25786
26376
|
const target = join9(root, ...parts.slice(0, i));
|
|
25787
26377
|
const stat3 = await info2(target);
|
|
25788
26378
|
if (!stat3) return null;
|
|
25789
|
-
if (stat3.isSymbolicLink() || (i < parts.length ? !stat3.isDirectory() : !stat3.isFile())) fail6("
|
|
25790
|
-
if (i < parts.length && await info2(join9(target, ".git"))) fail6("
|
|
26379
|
+
if (stat3.isSymbolicLink() || (i < parts.length ? !stat3.isDirectory() : !stat3.isFile())) fail6(t2("commitFiles.linkOrDirectory"));
|
|
26380
|
+
if (i < parts.length && await info2(join9(target, ".git"))) fail6(t2("commitFiles.nestedRepository"));
|
|
25791
26381
|
if (i === parts.length) {
|
|
25792
|
-
if (stat3.nlink !== 1 || stat3.size > 16 * 1024 * 1024) fail6("
|
|
25793
|
-
return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await
|
|
26382
|
+
if (stat3.nlink !== 1 || stat3.size > 16 * 1024 * 1024) fail6(t2("commitFiles.hardLinkOrSize"));
|
|
26383
|
+
return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await readFile9(target)]));
|
|
25794
26384
|
}
|
|
25795
26385
|
}
|
|
25796
26386
|
return null;
|
|
25797
26387
|
}
|
|
25798
26388
|
function object3(input2) {
|
|
25799
|
-
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) return fail6("
|
|
26389
|
+
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) return fail6(t2("commitFiles.invalidInput"));
|
|
25800
26390
|
return input2;
|
|
25801
26391
|
}
|
|
25802
26392
|
function text(value, limit) {
|
|
25803
|
-
if (typeof value !== "string" || !value.trim() || value.length > limit || value.includes("\0")) return fail6("
|
|
26393
|
+
if (typeof value !== "string" || !value.trim() || value.length > limit || value.includes("\0")) return fail6(t2("commitFiles.emptyOrTooLong"));
|
|
25804
26394
|
return value;
|
|
25805
26395
|
}
|
|
25806
26396
|
function paths(value, limit = 128) {
|
|
25807
|
-
if (!Array.isArray(value) || !value.length || value.length > limit || value.some((p) => typeof p !== "string")) return fail6("
|
|
26397
|
+
if (!Array.isArray(value) || !value.length || value.length > limit || value.some((p) => typeof p !== "string")) return fail6(t2("commitFiles.invalidPaths"));
|
|
25808
26398
|
const list = [...new Set(value)].sort();
|
|
25809
26399
|
list.forEach(validPath2);
|
|
25810
26400
|
return list;
|
|
@@ -25821,10 +26411,10 @@ async function checkLegacySelection(root, selected) {
|
|
|
25821
26411
|
const legacyJson = /^\.(?:gitifact|tryce)\/(?:spec\/[^/]+\/tryce\.json|notes\/N-[a-f0-9-]+\.json|mode-[a-f0-9-]+\.json|config\.(?:init-1|prototype-1)\.[a-f0-9]+\.json)$/;
|
|
25822
26412
|
for (const p of selected.filter((p2) => p2.startsWith(".gitifact/") && !record2(p2) && p2 !== ".gitifact/config.json")) {
|
|
25823
26413
|
if (isProductAssetPath(p)) continue;
|
|
25824
|
-
if (!legacyJson.test(p) || await fingerprint(root, p) !== null) fail6(".
|
|
26414
|
+
if (!legacyJson.test(p) || await fingerprint(root, p) !== null) fail6(t2("commitFiles.legacyDeleteOnly", { path: p }));
|
|
25825
26415
|
}
|
|
25826
26416
|
for (const p of selected.filter((p2) => p2.startsWith(".tryce/"))) {
|
|
25827
|
-
if (!(record2(p) || p === ".tryce/config.json" || legacyJson.test(p)) || await fingerprint(root, p) !== null) fail6(".
|
|
26417
|
+
if (!(record2(p) || p === ".tryce/config.json" || legacyJson.test(p)) || await fingerprint(root, p) !== null) fail6(t2("commitFiles.tryceDeleteOnly", { path: p }));
|
|
25828
26418
|
}
|
|
25829
26419
|
}
|
|
25830
26420
|
|
|
@@ -25854,30 +26444,30 @@ async function previewCommit(cwd, action, input2) {
|
|
|
25854
26444
|
const indexPath = (await git(["rev-parse", "--path-format=absolute", "--git-path", "index"])).toString("utf8").trim();
|
|
25855
26445
|
const staged = async (index) => (await git(["diff", "--cached", "--ita-visible-in-index", "--name-only", "--no-renames", "-z"], index)).toString("utf8").split("\0").filter(Boolean).sort();
|
|
25856
26446
|
const busy = join10(gitDir, "gitifact-spec-commit.lock");
|
|
25857
|
-
if (await info2(busy)) fail6("
|
|
25858
|
-
if ((await staged()).length) fail6("
|
|
26447
|
+
if (await info2(busy)) fail6(t2("commit.busy", { path: busy }));
|
|
26448
|
+
if ((await staged()).length) fail6(t2("commit.existingStagingPlan"));
|
|
25859
26449
|
const request = object3(input2);
|
|
25860
26450
|
let plan;
|
|
25861
26451
|
if (action === "plan") {
|
|
25862
|
-
if (Object.keys(request).some((k) => !["verification", "paths", "message", "requirements", "authorization", "policyFiles"].includes(k))) fail6("
|
|
26452
|
+
if (Object.keys(request).some((k) => !["verification", "paths", "message", "requirements", "authorization", "policyFiles"].includes(k))) fail6(t2("commit.unknownField"));
|
|
25863
26453
|
await verifyPreparedPreview(cwd, request.verification, false);
|
|
25864
26454
|
const selected2 = paths(request.paths);
|
|
25865
26455
|
const authorization = object3(request.authorization);
|
|
25866
26456
|
await checkLegacySelection(root, selected2);
|
|
25867
|
-
if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis))) fail6("
|
|
26457
|
+
if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis))) fail6(t2("commit.authorizationRequired"));
|
|
25868
26458
|
const message = text(request.message, 4e3);
|
|
25869
|
-
if (/^\s*Gitifact-/im.test(message)) fail6("
|
|
26459
|
+
if (/^\s*Gitifact-/im.test(message)) fail6(t2("commit.trailerInMessage"));
|
|
25870
26460
|
const state = await readWorkingPreviewState(cwd);
|
|
25871
26461
|
const base = await reader.baseline();
|
|
25872
26462
|
const previous = base.head ? await reader.files(base.head, state.config !== void 0) : /* @__PURE__ */ new Map();
|
|
25873
26463
|
const pending = [.../* @__PURE__ */ new Set([...previous.keys(), ...state.files.keys()])].filter((p) => previous.get(p) !== state.files.get(p));
|
|
25874
|
-
if (pending.some((p) => !selected2.includes(p))) fail6("
|
|
26464
|
+
if (pending.some((p) => !selected2.includes(p))) fail6(t2("commit.selectPending"));
|
|
25875
26465
|
const delta = await readFinalPreviewChanges(cwd);
|
|
25876
26466
|
const references = request.requirements ?? [];
|
|
25877
|
-
if (!Array.isArray(references) || references.length > 1e3 || references.some((r) => typeof r !== "string")) fail6("
|
|
25878
|
-
if (delta.changes.some((c) => c.kind === "design")) fail6("
|
|
26467
|
+
if (!Array.isArray(references) || references.length > 1e3 || references.some((r) => typeof r !== "string")) fail6(t2("commit.invalidReferences"));
|
|
26468
|
+
if (delta.changes.some((c) => c.kind === "design")) fail6(t2("commit.designUseSpecCommit"));
|
|
25879
26469
|
const known = /* @__PURE__ */ new Set([...state.specs.flatMap((s) => s.requirements.map((r) => r.id)), ...delta.changes.map((c) => c.id)]);
|
|
25880
|
-
if (references.some((r) => !known.has(r))) fail6("
|
|
26470
|
+
if (references.some((r) => !known.has(r))) fail6(t2("commit.unknownRequirement"));
|
|
25881
26471
|
const extra = request.policyFiles === void 0 ? [] : paths(request.policyFiles, 1024);
|
|
25882
26472
|
const contents = async (list) => Promise.all(list.map(async (path3) => ({ path: path3, hash: await fingerprint(root, path3) })));
|
|
25883
26473
|
const data2 = {
|
|
@@ -25892,13 +26482,13 @@ async function previewCommit(cwd, action, input2) {
|
|
|
25892
26482
|
authorization: { basis: String(authorization.basis), evidence: text(authorization.evidence, 2e3) }
|
|
25893
26483
|
};
|
|
25894
26484
|
await verifyPreparedPreview(cwd, request.verification, false);
|
|
25895
|
-
if (data2.index !== hash2(await optional2(indexPath) ?? Buffer.alloc(0)) || (await staged()).length) fail6("
|
|
26485
|
+
if (data2.index !== hash2(await optional2(indexPath) ?? Buffer.alloc(0)) || (await staged()).length) fail6(t2("commit.indexChangedPlanning"));
|
|
25896
26486
|
return { outcome: "planned", plan: { ...data2, digest: seal(data2) }, committed: false };
|
|
25897
26487
|
}
|
|
25898
26488
|
const { digest: digest2, ...data } = request;
|
|
25899
|
-
if (request.kind !== "spec-preview-commit" || typeof digest2 !== "string" || digest2 !== seal(data)) fail6("
|
|
26489
|
+
if (request.kind !== "spec-preview-commit" || typeof digest2 !== "string" || digest2 !== seal(data)) fail6(t2("commit.planCorrupted"));
|
|
25900
26490
|
plan = request;
|
|
25901
|
-
if (plan.root !== root || !Array.isArray(plan.files) || !Array.isArray(plan.context)) fail6("
|
|
26491
|
+
if (plan.root !== root || !Array.isArray(plan.files) || !Array.isArray(plan.context)) fail6(t2("commit.planScope"));
|
|
25902
26492
|
const selected = paths(plan.files.map((f) => f.path));
|
|
25903
26493
|
const refreshed = await previewCommit(cwd, "plan", {
|
|
25904
26494
|
verification: plan.verification,
|
|
@@ -25908,7 +26498,7 @@ async function previewCommit(cwd, action, input2) {
|
|
|
25908
26498
|
authorization: plan.authorization,
|
|
25909
26499
|
policyFiles: plan.context.map((f) => f.path)
|
|
25910
26500
|
});
|
|
25911
|
-
if (!("plan" in refreshed) || refreshed.plan.digest !== plan.digest) fail6("
|
|
26501
|
+
if (!("plan" in refreshed) || refreshed.plan.digest !== plan.digest) fail6(t2("commit.planStale"));
|
|
25912
26502
|
const before = await reader.baseline();
|
|
25913
26503
|
const original = await optional2(indexPath);
|
|
25914
26504
|
await mkdir4(busy);
|
|
@@ -25919,28 +26509,28 @@ async function previewCommit(cwd, action, input2) {
|
|
|
25919
26509
|
let commitStarted = false;
|
|
25920
26510
|
const temporary = join10(gitDir, "gitifact-commit-index-" + randomUUID6());
|
|
25921
26511
|
const checkFiles = async () => {
|
|
25922
|
-
for (const f of [...plan.files, ...plan.context]) if (f.hash !== await fingerprint(root, f.path)) fail6("
|
|
25923
|
-
if ((await readLockedPreviewState(root)).stamp !== object3(plan.verification).stamp) fail6("
|
|
25924
|
-
for (const name of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"]) if (await info2(join10(gitDir, name))) fail6("
|
|
26512
|
+
for (const f of [...plan.files, ...plan.context]) if (f.hash !== await fingerprint(root, f.path)) fail6(t2("commit.fileChangedPreparing", { path: f.path }));
|
|
26513
|
+
if ((await readLockedPreviewState(root)).stamp !== object3(plan.verification).stamp) fail6(t2("commit.specsChangedPreparing"));
|
|
26514
|
+
for (const name of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"]) if (await info2(join10(gitDir, name))) fail6(t2("commit.integrationStarted"));
|
|
25925
26515
|
};
|
|
25926
26516
|
try {
|
|
25927
26517
|
await verifyPreparedPreview(cwd, plan.verification, false);
|
|
25928
26518
|
await mkdir4(draftLock);
|
|
25929
26519
|
draftOwned = true;
|
|
25930
26520
|
indexLock = await open4(indexPath + ".lock", "wx", 384);
|
|
25931
|
-
if (plan.index !== hash2(await optional2(indexPath) ?? Buffer.alloc(0)) || (await staged()).length) fail6("
|
|
26521
|
+
if (plan.index !== hash2(await optional2(indexPath) ?? Buffer.alloc(0)) || (await staged()).length) fail6(t2("commit.indexChangedLocked"));
|
|
25932
26522
|
await writeFile2(join10(busy, "recovery.json"), JSON.stringify({ before, originalIndex: original?.toString("base64") ?? null, temporary, plan }));
|
|
25933
26523
|
if (original) await writeFile2(temporary, original, { flag: "wx" });
|
|
25934
26524
|
else await git(["read-tree", "--empty"], temporary);
|
|
25935
26525
|
await git(["add", "--", ...selected], temporary);
|
|
25936
26526
|
const actual = await staged(temporary);
|
|
25937
|
-
if (!actual.length || actual.some((p) => !selected.includes(p))) fail6("
|
|
26527
|
+
if (!actual.length || actual.some((p) => !selected.includes(p))) fail6(t2("commit.unexpectedFiles"));
|
|
25938
26528
|
for (const file2 of plan.files.filter((f) => record2(f.path) && f.hash !== null)) {
|
|
25939
26529
|
const stagedBytes = await git(["show", ":" + file2.path], temporary);
|
|
25940
|
-
if (!stagedBytes.equals(await
|
|
26530
|
+
if (!stagedBytes.equals(await readFile10(join10(root, file2.path)))) fail6(t2("commit.filterChanged"));
|
|
25941
26531
|
}
|
|
25942
26532
|
await checkFiles();
|
|
25943
|
-
if (JSON.stringify(before) !== JSON.stringify(await reader.baseline())) fail6("
|
|
26533
|
+
if (JSON.stringify(before) !== JSON.stringify(await reader.baseline())) fail6(t2("commit.headChanged"));
|
|
25944
26534
|
const tree = (await git(["write-tree"], temporary)).toString("utf8").trim();
|
|
25945
26535
|
const trailers = plan.requirements.map((id) => "Gitifact-Req: " + id);
|
|
25946
26536
|
commitStarted = true;
|
|
@@ -25949,10 +26539,10 @@ async function previewCommit(cwd, action, input2) {
|
|
|
25949
26539
|
const actualTree = (await git(["rev-parse", "HEAD^{tree}"])).toString("utf8").trim();
|
|
25950
26540
|
const parents = (await git(["rev-list", "--parents", "-n", "1", "HEAD"])).toString("utf8").trim().split(" ").slice(1);
|
|
25951
26541
|
const message = (await git(["log", "-1", "--format=%B"])).toString("utf8");
|
|
25952
|
-
if (actualTree !== tree || after.branch !== before.branch || JSON.stringify(parents) !== JSON.stringify(before.head ? [before.head] : []) || trailers.some((
|
|
25953
|
-
if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== plan.index) fail6("
|
|
25954
|
-
if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail6("
|
|
25955
|
-
await indexLock.writeFile(await
|
|
26542
|
+
if (actualTree !== tree || after.branch !== before.branch || JSON.stringify(parents) !== JSON.stringify(before.head ? [before.head] : []) || trailers.some((t3) => !message.split(/\r?\n/).includes(t3))) fail6(t2("commit.resultAltered"));
|
|
26543
|
+
if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== plan.index) fail6(t2("commit.indexChangedAfter"));
|
|
26544
|
+
if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail6(t2("commit.hookChangedStaging"));
|
|
26545
|
+
await indexLock.writeFile(await readFile10(temporary));
|
|
25956
26546
|
await indexLock.sync();
|
|
25957
26547
|
await indexLock.close();
|
|
25958
26548
|
await rename3(indexPath + ".lock", indexPath);
|
|
@@ -25966,7 +26556,7 @@ async function previewCommit(cwd, action, input2) {
|
|
|
25966
26556
|
uncertain = true;
|
|
25967
26557
|
}
|
|
25968
26558
|
}
|
|
25969
|
-
if (uncertain) fail6("
|
|
26559
|
+
if (uncertain) fail6(t2("commit.uncertain", { path: busy }));
|
|
25970
26560
|
throw error62;
|
|
25971
26561
|
} finally {
|
|
25972
26562
|
await indexLock?.close().catch(() => {
|
|
@@ -25986,24 +26576,24 @@ async function previewCommit(cwd, action, input2) {
|
|
|
25986
26576
|
|
|
25987
26577
|
// src/commands/spec-commit.ts
|
|
25988
26578
|
import { createHash as createHash7, randomUUID as randomUUID7 } from "node:crypto";
|
|
25989
|
-
import { mkdir as mkdir5, open as open5, readFile as
|
|
26579
|
+
import { mkdir as mkdir5, open as open5, readFile as readFile11, rename as rename4, rmdir as rmdir3, unlink as unlink5, writeFile as writeFile3 } from "node:fs/promises";
|
|
25990
26580
|
import { join as join11 } from "node:path";
|
|
25991
26581
|
var fields = ["reasons", "paths", "message", "authorization", "requirements", "policyFiles", "expected"];
|
|
25992
26582
|
var integration = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"];
|
|
25993
26583
|
var same2 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
25994
26584
|
async function specCommit(cwd, input2, dryRun) {
|
|
25995
26585
|
const request = object3(input2);
|
|
25996
|
-
if (Object.keys(request).some((k) => !fields.includes(k))) fail6("
|
|
26586
|
+
if (Object.keys(request).some((k) => !fields.includes(k))) fail6(t2("commit.unknownField"));
|
|
25997
26587
|
const selected = paths(request.paths);
|
|
25998
26588
|
const authorization = object3(request.authorization);
|
|
25999
|
-
if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis))) fail6("
|
|
26589
|
+
if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis))) fail6(t2("commit.authorizationRequired"));
|
|
26000
26590
|
text(authorization.evidence, 2e3);
|
|
26001
26591
|
const message = text(request.message, 4e3);
|
|
26002
|
-
if (/^\s*Gitifact-/im.test(message)) fail6("
|
|
26592
|
+
if (/^\s*Gitifact-/im.test(message)) fail6(t2("commit.trailerInMessage"));
|
|
26003
26593
|
const references = request.requirements ?? [];
|
|
26004
|
-
if (!Array.isArray(references) || references.length > 1e3 || references.some((r) => typeof r !== "string")) fail6("
|
|
26594
|
+
if (!Array.isArray(references) || references.length > 1e3 || references.some((r) => typeof r !== "string")) fail6(t2("commit.invalidReferences"));
|
|
26005
26595
|
const extra = request.policyFiles === void 0 ? [] : paths(request.policyFiles, 1024);
|
|
26006
|
-
if (request.expected !== void 0 && typeof request.expected !== "string") fail6("
|
|
26596
|
+
if (request.expected !== void 0 && typeof request.expected !== "string") fail6(t2("commit.expectedType"));
|
|
26007
26597
|
const c = await readPreviewContext(cwd);
|
|
26008
26598
|
const { root, gitDir, indexPath, objectFormat } = await c.reader.location();
|
|
26009
26599
|
const runner = createGitRunner();
|
|
@@ -26028,11 +26618,11 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26028
26618
|
const staged = async (index) => (await git(["diff", "--cached", "--ita-visible-in-index", "--name-only", "--no-renames", "-z"], index)).toString("utf8").split("\0").filter(Boolean).sort();
|
|
26029
26619
|
const busy = join11(gitDir, "gitifact-spec-commit.lock");
|
|
26030
26620
|
await failOnLegacyLock(gitDir);
|
|
26031
|
-
if (await info2(busy)) fail6("
|
|
26032
|
-
if ((await staged()).length) fail6("
|
|
26621
|
+
if (await info2(busy)) fail6(t2("commit.busy", { path: busy }));
|
|
26622
|
+
if ((await staged()).length) fail6(t2("commit.existingStaging"));
|
|
26033
26623
|
const indexHash = hash2(await optional2(indexPath) ?? Buffer.alloc(0));
|
|
26034
26624
|
const current = c.working;
|
|
26035
|
-
if (request.expected !== void 0 && request.expected !== previewExpected(c.base, current.stamp)) fail6("
|
|
26625
|
+
if (request.expected !== void 0 && request.expected !== previewExpected(c.base, current.stamp)) fail6(t2("commit.staleInput"));
|
|
26036
26626
|
const reasons = request.reasons ?? pendingPreviewReasons(c.bundle, current.bundle).map((h) => ({ requirements: h.requirements, ...h.designs ? { designs: h.designs } : {}, ...h.documents ? { documents: h.documents } : {}, reason: h.reason }));
|
|
26037
26627
|
const prepared = prepareSpecPreview(c.bundle, current.bundle, c.files, current.files, reasons, () => generatePreviewId("H"));
|
|
26038
26628
|
const blobId = (text2) => {
|
|
@@ -26040,14 +26630,14 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26040
26630
|
return createHash7(objectFormat).update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
|
|
26041
26631
|
};
|
|
26042
26632
|
const present = [...current.files.keys()];
|
|
26043
|
-
if (present.some((p) => p.includes("\n"))) fail6("
|
|
26633
|
+
if (present.some((p) => p.includes("\n"))) fail6(t2("commit.newlinePath"));
|
|
26044
26634
|
const stored = present.length ? (await git(["hash-object", "--stdin-paths"], void 0, Buffer.from(present.join("\n") + "\n"))).toString("utf8").split("\n") : [""];
|
|
26045
|
-
if (stored.length !== present.length + 1) fail6("
|
|
26635
|
+
if (stored.length !== present.length + 1) fail6(t2("commit.storedShape"));
|
|
26046
26636
|
const workingIds = new Map(present.map((p, i) => [p, stored[i]]));
|
|
26047
26637
|
const writes = new Map([...prepared.writes].filter(([p, next]) => next === null || workingIds.get(p) !== blobId(next)));
|
|
26048
26638
|
const finalId = (p) => writes.has(p) ? writes.get(p) === null ? void 0 : blobId(writes.get(p)) : workingIds.get(p);
|
|
26049
26639
|
const pending = [.../* @__PURE__ */ new Set([...c.files.keys(), ...present, ...writes.keys()])].filter((p) => (c.files.has(p) ? blobId(c.files.get(p)) : void 0) !== finalId(p));
|
|
26050
|
-
if (pending.some((p) => !selected.includes(p))) fail6("
|
|
26640
|
+
if (pending.some((p) => !selected.includes(p))) fail6(t2("commit.selectPending"));
|
|
26051
26641
|
const finalFiles = new Map(current.files);
|
|
26052
26642
|
for (const [path3, next] of writes) {
|
|
26053
26643
|
if (next === null) finalFiles.delete(path3);
|
|
@@ -26056,7 +26646,7 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26056
26646
|
await checkLegacySelection(root, selected);
|
|
26057
26647
|
const stageable = selected.filter((p) => !record2(p) || finalFiles.has(p) || c.files.has(p));
|
|
26058
26648
|
const known = /* @__PURE__ */ new Set([...current.specs.flatMap((s) => s.requirements.map((r) => r.id)), ...prepared.changes.filter((x) => x.kind === "requirement").map((x) => x.id)]);
|
|
26059
|
-
if (references.some((r) => !known.has(r))) fail6("
|
|
26649
|
+
if (references.some((r) => !known.has(r))) fail6(t2("commit.unknownRequirement"));
|
|
26060
26650
|
const requirements = [.../* @__PURE__ */ new Set([...references, ...prepared.changes.filter((x) => x.kind === "requirement").map((x) => x.id)])].sort();
|
|
26061
26651
|
const contextPaths = [.../* @__PURE__ */ new Set([...policyPaths(selected), ...extra])].sort();
|
|
26062
26652
|
const hashes = async (list) => new Map(await Promise.all(list.map(async (p) => [p, await fingerprint(root, p)])));
|
|
@@ -26090,7 +26680,7 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26090
26680
|
await mkdir5(busy);
|
|
26091
26681
|
owned = true;
|
|
26092
26682
|
} catch (e) {
|
|
26093
|
-
if (e.code === "EEXIST") fail6("
|
|
26683
|
+
if (e.code === "EEXIST") fail6(t2("commit.busy", { path: busy }));
|
|
26094
26684
|
throw e;
|
|
26095
26685
|
}
|
|
26096
26686
|
await previewTransaction(cwd, current.stamp, async () => ({ writes, data: {}, recheck: c.recheck }), rename4, async (published) => {
|
|
@@ -26098,15 +26688,15 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26098
26688
|
try {
|
|
26099
26689
|
const lock = indexLock = await open5(indexPath + ".lock", "wx", 384);
|
|
26100
26690
|
const original = await optional2(indexPath);
|
|
26101
|
-
if (hash2(original ?? Buffer.alloc(0)) !== indexHash || (await staged()).length) fail6("
|
|
26691
|
+
if (hash2(original ?? Buffer.alloc(0)) !== indexHash || (await staged()).length) fail6(t2("commit.indexChanged"));
|
|
26102
26692
|
const locked = await hashes([.../* @__PURE__ */ new Set([...selected, ...contextPaths])]);
|
|
26103
|
-
for (const [path3, value] of started) if (locked.get(path3) !== value) fail6("
|
|
26693
|
+
for (const [path3, value] of started) if (locked.get(path3) !== value) fail6(t2("commit.fileChangedRunning", { path: path3 }));
|
|
26104
26694
|
await writeFile3(join11(busy, "recovery.json"), JSON.stringify({ before: c.base, originalIndex: original?.toString("base64") ?? null, temporary, paths: selected, message, requirements }));
|
|
26105
26695
|
if (original) await writeFile3(temporary, original, { flag: "wx" });
|
|
26106
26696
|
else await git(["read-tree", "--empty"], temporary);
|
|
26107
26697
|
await git(["add", "--", ...stageable], temporary);
|
|
26108
26698
|
const actual = await staged(temporary);
|
|
26109
|
-
if (!actual.length || actual.some((p) => !selected.includes(p))) fail6("
|
|
26699
|
+
if (!actual.length || actual.some((p) => !selected.includes(p))) fail6(t2("commit.unexpectedFiles"));
|
|
26110
26700
|
const records = selected.filter((p) => record2(p) && locked.get(p) !== null);
|
|
26111
26701
|
if (records.length) {
|
|
26112
26702
|
const output2 = await git(["cat-file", "--batch"], temporary, Buffer.from(records.map((p) => ":" + p).join("\n") + "\n"));
|
|
@@ -26115,32 +26705,32 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26115
26705
|
const end = output2.indexOf(10, offset);
|
|
26116
26706
|
const header = output2.subarray(offset, end).toString("utf8").split(" ");
|
|
26117
26707
|
const size = Number(header[2]);
|
|
26118
|
-
if (end < 0 || header[1] !== "blob" || !Number.isSafeInteger(size) || output2[end + 1 + size] !== 10) fail6("
|
|
26708
|
+
if (end < 0 || header[1] !== "blob" || !Number.isSafeInteger(size) || output2[end + 1 + size] !== 10) fail6(t2("commit.stagedUnreadable", { path: path3 }));
|
|
26119
26709
|
const staged2 = output2.subarray(end + 1, end + 1 + size);
|
|
26120
|
-
const file2 = await
|
|
26121
|
-
if (!staged2.equals(file2) && !staged2.equals(Buffer.from(file2.toString("latin1").replace(/\r\n/g, "\n"), "latin1"))) fail6("
|
|
26710
|
+
const file2 = await readFile11(join11(root, path3));
|
|
26711
|
+
if (!staged2.equals(file2) && !staged2.equals(Buffer.from(file2.toString("latin1").replace(/\r\n/g, "\n"), "latin1"))) fail6(t2("commit.filterChanged"));
|
|
26122
26712
|
offset = end + size + 2;
|
|
26123
26713
|
}
|
|
26124
26714
|
}
|
|
26125
26715
|
const again = await hashes([...locked.keys()]);
|
|
26126
|
-
for (const [path3, value] of locked) if (again.get(path3) !== value) fail6("
|
|
26127
|
-
if ((await readLockedPreviewState(root)).stamp !== published.stamp) fail6("
|
|
26128
|
-
for (const name of integration) if (await info2(join11(gitDir, name))) fail6("
|
|
26129
|
-
if (!same2(c.base, await c.reader.baseline())) fail6("
|
|
26716
|
+
for (const [path3, value] of locked) if (again.get(path3) !== value) fail6(t2("commit.fileChangedPreparing", { path: path3 }));
|
|
26717
|
+
if ((await readLockedPreviewState(root)).stamp !== published.stamp) fail6(t2("commit.specsChangedPreparing"));
|
|
26718
|
+
for (const name of integration) if (await info2(join11(gitDir, name))) fail6(t2("commit.integrationStarted"));
|
|
26719
|
+
if (!same2(c.base, await c.reader.baseline())) fail6(t2("commit.headChanged"));
|
|
26130
26720
|
const tree = (await git(["write-tree"], temporary)).toString("utf8").trim();
|
|
26131
26721
|
commitStarted = true;
|
|
26132
26722
|
await git(["commit", "-m", message.trim() + (trailers.length ? "\n\n" + trailers.join("\n") : "")], temporary);
|
|
26133
26723
|
const after = await c.reader.baseline();
|
|
26134
|
-
if (!after.head) return fail6("
|
|
26724
|
+
if (!after.head) return fail6(t2("commit.resultUnknown"));
|
|
26135
26725
|
const raw = (await git(["cat-file", "commit", after.head])).toString("utf8");
|
|
26136
26726
|
const split = raw.indexOf("\n\n");
|
|
26137
26727
|
const headers = raw.slice(0, split < 0 ? raw.length : split).split("\n");
|
|
26138
26728
|
const body = split < 0 ? "" : raw.slice(split + 2);
|
|
26139
26729
|
const parents = headers.filter((h) => h.startsWith("parent ")).map((h) => h.slice(7));
|
|
26140
|
-
if (headers[0] !== "tree " + tree || after.branch !== c.base.branch || !same2(parents, c.base.head ? [c.base.head] : []) || trailers.some((
|
|
26141
|
-
if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== indexHash) fail6("
|
|
26142
|
-
if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail6("
|
|
26143
|
-
await lock.writeFile(await
|
|
26730
|
+
if (headers[0] !== "tree " + tree || after.branch !== c.base.branch || !same2(parents, c.base.head ? [c.base.head] : []) || trailers.some((t3) => !body.split(/\r?\n/).includes(t3))) fail6(t2("commit.resultAltered"));
|
|
26731
|
+
if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== indexHash) fail6(t2("commit.indexChangedAfter"));
|
|
26732
|
+
if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail6(t2("commit.hookChangedStaging"));
|
|
26733
|
+
await lock.writeFile(await readFile11(temporary));
|
|
26144
26734
|
await lock.sync();
|
|
26145
26735
|
await lock.close();
|
|
26146
26736
|
await rename4(indexPath + ".lock", indexPath);
|
|
@@ -26154,7 +26744,7 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26154
26744
|
uncertain = true;
|
|
26155
26745
|
}
|
|
26156
26746
|
}
|
|
26157
|
-
if (uncertain) throw new PreservedPreviewError("
|
|
26747
|
+
if (uncertain) throw new PreservedPreviewError(t2("commit.uncertain", { path: busy }));
|
|
26158
26748
|
throw error62;
|
|
26159
26749
|
}
|
|
26160
26750
|
});
|
|
@@ -26184,12 +26774,12 @@ async function execute(action, options) {
|
|
|
26184
26774
|
try {
|
|
26185
26775
|
const guard = specPreviewReader(process.cwd());
|
|
26186
26776
|
const { root, gitDir, objectFormat } = await guard.location();
|
|
26187
|
-
for (const marker2 of operations) if (await fileInfo(join12(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", "
|
|
26188
|
-
if (await guard.hasUnmerged()) throw new InitError("GIT_OPERATION_IN_PROGRESS", "
|
|
26777
|
+
for (const marker2 of operations) if (await fileInfo(join12(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
|
|
26778
|
+
if (await guard.hasUnmerged()) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
26189
26779
|
const raw = await readConfigFile(root);
|
|
26190
|
-
if (raw === void 0) throw new SpecPreviewError("
|
|
26780
|
+
if (raw === void 0) throw new SpecPreviewError(t2("preview.notInitialized"));
|
|
26191
26781
|
const config2 = parseManagedConfig(raw);
|
|
26192
|
-
if (!("schemaVersion" in config2)) throw new SpecPreviewError("
|
|
26782
|
+
if (!("schemaVersion" in config2)) throw new SpecPreviewError(t2("preview.legacyProject"));
|
|
26193
26783
|
await initRepository(root).validateBaseline(config2, root, "HEAD", objectFormat);
|
|
26194
26784
|
if (["working", "save", "changes", "prepare", "verify", "commit-plan", "commit-apply", "commit"].includes(action)) {
|
|
26195
26785
|
let result;
|
|
@@ -26197,14 +26787,14 @@ async function execute(action, options) {
|
|
|
26197
26787
|
else if (action === "changes") result = await readFinalPreviewChanges(process.cwd());
|
|
26198
26788
|
else {
|
|
26199
26789
|
const source = await stat2(options.file);
|
|
26200
|
-
if (!source.isFile() || source.size > 1024 * 1024) throw new SpecPreviewError("
|
|
26201
|
-
const bytes = await
|
|
26202
|
-
if (bytes.length > 1024 * 1024) throw new SpecPreviewError("
|
|
26790
|
+
if (!source.isFile() || source.size > 1024 * 1024) throw new SpecPreviewError(t2("preview.inputFile"));
|
|
26791
|
+
const bytes = await readFile12(options.file);
|
|
26792
|
+
if (bytes.length > 1024 * 1024) throw new SpecPreviewError(t2("preview.inputSize"));
|
|
26203
26793
|
let input2;
|
|
26204
26794
|
try {
|
|
26205
26795
|
input2 = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
26206
26796
|
} catch {
|
|
26207
|
-
throw new SpecPreviewError("
|
|
26797
|
+
throw new SpecPreviewError(t2("preview.inputJson"));
|
|
26208
26798
|
}
|
|
26209
26799
|
result = action === "commit" ? await specCommit(process.cwd(), input2, !!options.dryRun) : action === "commit-plan" || action === "commit-apply" ? await previewCommit(process.cwd(), action === "commit-plan" ? "plan" : "apply", input2) : action === "prepare" ? await prepareWorkingPreview(process.cwd(), input2) : action === "verify" ? await verifyPreparedPreview(process.cwd(), input2, !!options.staged) : await saveWorkingPreview(process.cwd(), input2);
|
|
26210
26800
|
}
|
|
@@ -26223,13 +26813,13 @@ async function execute(action, options) {
|
|
|
26223
26813
|
}
|
|
26224
26814
|
} catch (error62) {
|
|
26225
26815
|
const known = error62 instanceof SpecPreviewError || error62 instanceof RepositoryReadError || error62 instanceof InitError;
|
|
26226
|
-
process.stderr.write(JSON.stringify({ ...envelope, ok: false, error: { code: known ? error62.code : "SPEC_PREVIEW_FAILED", message: known ? error62.message : "
|
|
26816
|
+
process.stderr.write(JSON.stringify({ ...envelope, ok: false, error: { code: known ? error62.code : "SPEC_PREVIEW_FAILED", message: known ? error62.message : t2("preview.failed") } }) + "\n");
|
|
26227
26817
|
process.exitCode = 1;
|
|
26228
26818
|
}
|
|
26229
26819
|
}
|
|
26230
26820
|
|
|
26231
26821
|
// src/commands/migrate.ts
|
|
26232
|
-
import { lstat as lstat7, readdir as readdir4, readFile as
|
|
26822
|
+
import { lstat as lstat7, readdir as readdir4, readFile as readFile13, rename as rename5, writeFile as writeFile4, unlink as unlink6 } from "node:fs/promises";
|
|
26233
26823
|
import { join as join13 } from "node:path";
|
|
26234
26824
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
26235
26825
|
var operations2 = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"];
|
|
@@ -26244,21 +26834,21 @@ var fail7 = (code, message) => {
|
|
|
26244
26834
|
async function migrateStore(cwd, dryRun = false) {
|
|
26245
26835
|
const reader = specPreviewReader(cwd);
|
|
26246
26836
|
const { root, gitDir } = await reader.location();
|
|
26247
|
-
for (const marker3 of operations2) if (await info3(join13(gitDir, marker3))) fail7("GIT_OPERATION_IN_PROGRESS", "
|
|
26248
|
-
if (await reader.hasUnmerged()) fail7("GIT_OPERATION_IN_PROGRESS", "
|
|
26249
|
-
for (const name of [...LEGACY_LOCKS, "gitifact-spec-preview.lock", "gitifact-spec-commit.lock"]) if (await info3(join13(gitDir, name))) fail7("LOCKED", "
|
|
26837
|
+
for (const marker3 of operations2) if (await info3(join13(gitDir, marker3))) fail7("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker3 }));
|
|
26838
|
+
if (await reader.hasUnmerged()) fail7("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
26839
|
+
for (const name of [...LEGACY_LOCKS, "gitifact-spec-preview.lock", "gitifact-spec-commit.lock"]) if (await info3(join13(gitDir, name))) fail7("LOCKED", t2("migrate.locked", { path: join13(gitDir, name) }));
|
|
26250
26840
|
const from = join13(root, ".tryce");
|
|
26251
26841
|
const to = join13(root, ".gitifact");
|
|
26252
26842
|
const fromInfo = await info3(from);
|
|
26253
|
-
if (await info3(to)) fail7("ALREADY_MIGRATED", ".
|
|
26254
|
-
if (!fromInfo) return fail7("NOTHING_TO_MIGRATE", ".
|
|
26255
|
-
if (!fromInfo.isDirectory() || fromInfo.isSymbolicLink()) fail7("PATH_CONFLICT", ".
|
|
26843
|
+
if (await info3(to)) fail7("ALREADY_MIGRATED", t2("migrate.alreadyMigrated"));
|
|
26844
|
+
if (!fromInfo) return fail7("NOTHING_TO_MIGRATE", t2("migrate.nothingToMigrate"));
|
|
26845
|
+
if (!fromInfo.isDirectory() || fromInfo.isSymbolicLink()) fail7("PATH_CONFLICT", t2("migrate.notDirectory"));
|
|
26256
26846
|
const configInfo = await info3(join13(from, "config.json"));
|
|
26257
|
-
if (!configInfo?.isFile() || configInfo.isSymbolicLink()) fail7("NOT_INITIALIZED", ".
|
|
26258
|
-
const config2 = parseManagedConfig(decode4(await
|
|
26259
|
-
if (!("schemaVersion" in config2)) fail7("UNSUPPORTED_FORMAT", "
|
|
26847
|
+
if (!configInfo?.isFile() || configInfo.isSymbolicLink()) fail7("NOT_INITIALIZED", t2("migrate.noConfig"));
|
|
26848
|
+
const config2 = parseManagedConfig(decode4(await readFile13(join13(from, "config.json"))));
|
|
26849
|
+
if (!("schemaVersion" in config2)) fail7("UNSUPPORTED_FORMAT", t2("migrate.legacyJson"));
|
|
26260
26850
|
const top = (await readdir4(from)).sort();
|
|
26261
|
-
if (top.some((name) => name !== "config.json" && name !== "spec")) fail7("UNSUPPORTED_FORMAT", ".
|
|
26851
|
+
if (top.some((name) => name !== "config.json" && name !== "spec")) fail7("UNSUPPORTED_FORMAT", t2("migrate.extraEntries"));
|
|
26262
26852
|
const files = /* @__PURE__ */ new Map();
|
|
26263
26853
|
const rewrites = [];
|
|
26264
26854
|
const legacyRecords = [];
|
|
@@ -26267,17 +26857,17 @@ async function migrateStore(cwd, dryRun = false) {
|
|
|
26267
26857
|
for (const feature2 of (await readdir4(join13(from, "spec"))).sort()) {
|
|
26268
26858
|
const dir = join13(from, "spec", feature2);
|
|
26269
26859
|
const stat3 = await info3(dir);
|
|
26270
|
-
if (!stat3?.isDirectory() || stat3.isSymbolicLink()) fail7("UNSUPPORTED_FORMAT", "
|
|
26860
|
+
if (!stat3?.isDirectory() || stat3.isSymbolicLink()) fail7("UNSUPPORTED_FORMAT", t2("migrate.notSpecFolder", { feature: feature2 }));
|
|
26271
26861
|
for (const name of (await readdir4(dir)).sort()) {
|
|
26272
|
-
if (!["requirements.md", "design.md", "history.jsonl", "tryce.json"].includes(name)) fail7("UNSUPPORTED_FORMAT", "
|
|
26862
|
+
if (!["requirements.md", "design.md", "history.jsonl", "tryce.json"].includes(name)) fail7("UNSUPPORTED_FORMAT", t2("migrate.unsupportedFile", { feature: feature2, name }));
|
|
26273
26863
|
const fileStat = await info3(join13(dir, name));
|
|
26274
|
-
if (!fileStat?.isFile() || fileStat.isSymbolicLink() || fileStat.nlink !== 1 || fileStat.size > 1024 * 1024) fail7("UNSUPPORTED_FORMAT", "
|
|
26864
|
+
if (!fileStat?.isFile() || fileStat.isSymbolicLink() || fileStat.nlink !== 1 || fileStat.size > 1024 * 1024) fail7("UNSUPPORTED_FORMAT", t2("migrate.fileTooLarge", { name }));
|
|
26275
26865
|
const newPath = `.gitifact/spec/${feature2}/${name}`;
|
|
26276
26866
|
if (name === "tryce.json") {
|
|
26277
26867
|
legacyRecords.push(newPath);
|
|
26278
26868
|
continue;
|
|
26279
26869
|
}
|
|
26280
|
-
const text2 = decode4(await
|
|
26870
|
+
const text2 = decode4(await readFile13(join13(dir, name)));
|
|
26281
26871
|
if (name === "history.jsonl") {
|
|
26282
26872
|
files.set(newPath, text2);
|
|
26283
26873
|
continue;
|
|
@@ -26313,10 +26903,10 @@ async function migrateStore(cwd, dryRun = false) {
|
|
|
26313
26903
|
rewritten: rewrites.map((r) => r.path),
|
|
26314
26904
|
legacyRecords,
|
|
26315
26905
|
next: [
|
|
26316
|
-
"
|
|
26317
|
-
...legacyRecords.length ? ["
|
|
26318
|
-
".
|
|
26319
|
-
".
|
|
26906
|
+
t2("migrate.nextCommit"),
|
|
26907
|
+
...legacyRecords.length ? [t2("migrate.nextLegacyJson")] : [],
|
|
26908
|
+
t2("migrate.nextSkills"),
|
|
26909
|
+
t2("migrate.nextRename")
|
|
26320
26910
|
]
|
|
26321
26911
|
});
|
|
26322
26912
|
if (dryRun) return result("planned");
|
|
@@ -26340,31 +26930,32 @@ async function runMigrate(options) {
|
|
|
26340
26930
|
process.stdout.write(JSON.stringify(dto) + "\n");
|
|
26341
26931
|
} catch (error62) {
|
|
26342
26932
|
const known = error62 instanceof InitError || error62 instanceof SpecPreviewError || error62 instanceof RepositoryReadError;
|
|
26343
|
-
process.stderr.write(JSON.stringify({ contract: "migrate", version: 1, ok: false, error: { code: known ? error62.code : "MIGRATE_FAILED", message: known ? error62.message : "
|
|
26933
|
+
process.stderr.write(JSON.stringify({ contract: "migrate", version: 1, ok: false, error: { code: known ? error62.code : "MIGRATE_FAILED", message: known ? error62.message : t2("migrate.failed") } }) + "\n");
|
|
26344
26934
|
process.exitCode = 1;
|
|
26345
26935
|
}
|
|
26346
26936
|
}
|
|
26347
26937
|
|
|
26348
26938
|
// src/main.ts
|
|
26349
|
-
var program2 = new Command().name("gitifact").description("
|
|
26350
|
-
program2.command("status").description(
|
|
26939
|
+
var program2 = new Command().name("gitifact").description(t2("help.program")).version("0.4.0").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
|
|
26940
|
+
program2.command("status").description(t2("help.status")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action(async (options) => {
|
|
26351
26941
|
await runStatus(options.format);
|
|
26352
26942
|
});
|
|
26353
|
-
program2.command("browser").description("
|
|
26354
|
-
program2.command("init").description(
|
|
26355
|
-
program2.command("docs").description(
|
|
26943
|
+
program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).option("--no-update-check", t2("help.browserNoUpdateCheck")).action((options) => runBrowser(options, "0.4.0"));
|
|
26944
|
+
program2.command("init").description(t2("help.init")).allowExcessArguments(false).option("--dry-run", t2("help.initDryRun")).addOption(new Option("--agent <agent>", t2("help.initAgent")).choices([...agentPresetNames])).addOption(new Option("--remove-agents", t2("help.initRemoveAgents")).conflicts("skipAgents")).option("--skip-agents", t2("help.initSkipAgents")).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runInit(options, "0.4.0"));
|
|
26945
|
+
program2.command("docs").description(t2("help.docs")).argument("[topic]", t2("help.docsTopic")).allowExcessArguments(false).action(async (topic) => {
|
|
26356
26946
|
await runDocs(topic);
|
|
26357
26947
|
});
|
|
26358
|
-
program2.command("
|
|
26359
|
-
|
|
26360
|
-
var
|
|
26361
|
-
|
|
26362
|
-
|
|
26363
|
-
spec.command(
|
|
26364
|
-
spec.command("
|
|
26365
|
-
spec.command("
|
|
26366
|
-
spec.command("
|
|
26367
|
-
spec.command("
|
|
26368
|
-
spec.command("
|
|
26369
|
-
spec.command("
|
|
26948
|
+
program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runUpdate(options, "0.4.0"));
|
|
26949
|
+
program2.command("migrate").description(t2("help.migrate")).allowExcessArguments(false).option("--dry-run", t2("help.migrateDryRun")).action(runMigrate);
|
|
26950
|
+
var spec = program2.command("spec").description(t2("help.spec"));
|
|
26951
|
+
var replaced = t2("help.deprecated");
|
|
26952
|
+
spec.command("commit").description(t2("help.specCommit")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specCommitFile")).option("--dry-run", t2("help.specCommitDryRun")).action((o) => runSpecPreview("commit", o));
|
|
26953
|
+
for (const action of ["commit-plan", "commit-apply"]) spec.command(action).description(replaced).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specCommitPlanFile")).action((o) => runSpecPreview(action, o));
|
|
26954
|
+
spec.command("changes").description(t2("help.specChanges")).allowExcessArguments(false).action((o) => runSpecPreview("changes", o));
|
|
26955
|
+
spec.command("prepare").description(replaced).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specPrepareFile")).action((o) => runSpecPreview("prepare", o));
|
|
26956
|
+
spec.command("verify").description(replaced).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specVerifyFile")).option("--staged", t2("help.specVerifyStaged")).action((o) => runSpecPreview("verify", o));
|
|
26957
|
+
spec.command("working").description(t2("help.specWorking")).allowExcessArguments(false).action((o) => runSpecPreview("working", o));
|
|
26958
|
+
spec.command("save").description(t2("help.specSave")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specSaveFile")).action((o) => runSpecPreview("save", o));
|
|
26959
|
+
spec.command("read").description(t2("help.specRead")).allowExcessArguments(false).option("--ref <commit>", t2("help.specReadRef"), "HEAD").action((o) => runSpecPreview("read", o));
|
|
26960
|
+
spec.command("diff").description(t2("help.specDiff")).allowExcessArguments(false).requiredOption("--from <commit>", t2("help.specDiffFrom")).requiredOption("--to <commit>", t2("help.specDiffTo")).action((o) => runSpecPreview("diff", o));
|
|
26370
26961
|
await program2.parseAsync();
|