@rsaglobaltech/specgate 0.8.1 → 0.10.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.
Files changed (144) hide show
  1. package/CHANGELOG.md +196 -0
  2. package/README.md +17 -25
  3. package/bin/specgate.ts +23 -5
  4. package/dist/bin/specgate.js +19 -4
  5. package/dist/bin/specgate.js.map +1 -1
  6. package/dist/packages/core/src/application/GenerateAgentPromptUseCase.js +56 -0
  7. package/dist/packages/core/src/application/GenerateAgentPromptUseCase.js.map +1 -1
  8. package/dist/packages/core/src/application/ValidateProjectUseCase.js +54 -0
  9. package/dist/packages/core/src/application/ValidateProjectUseCase.js.map +1 -1
  10. package/dist/packages/core/src/domain/AdversarialProbe.js +75 -0
  11. package/dist/packages/core/src/domain/AdversarialProbe.js.map +1 -0
  12. package/dist/packages/core/src/domain/AgentPrompt.js +52 -3
  13. package/dist/packages/core/src/domain/AgentPrompt.js.map +1 -1
  14. package/dist/packages/core/src/domain/DeclaredArtifacts.js +25 -0
  15. package/dist/packages/core/src/domain/DeclaredArtifacts.js.map +1 -1
  16. package/dist/packages/core/src/domain/DoneVerification.js +89 -0
  17. package/dist/packages/core/src/domain/DoneVerification.js.map +1 -0
  18. package/dist/packages/core/src/domain/GateCommandIntegrity.js +139 -0
  19. package/dist/packages/core/src/domain/GateCommandIntegrity.js.map +1 -0
  20. package/dist/packages/core/src/domain/GherkinQuality.js +19 -3
  21. package/dist/packages/core/src/domain/GherkinQuality.js.map +1 -1
  22. package/dist/packages/core/src/domain/HarnessConfig.js +6 -0
  23. package/dist/packages/core/src/domain/HarnessConfig.js.map +1 -1
  24. package/dist/packages/core/src/domain/MultiStack.js +96 -0
  25. package/dist/packages/core/src/domain/MultiStack.js.map +1 -0
  26. package/dist/packages/core/src/domain/NewRequirement.js +46 -0
  27. package/dist/packages/core/src/domain/NewRequirement.js.map +1 -0
  28. package/dist/packages/core/src/domain/Precedents.js +96 -0
  29. package/dist/packages/core/src/domain/Precedents.js.map +1 -0
  30. package/dist/packages/core/src/domain/RequirementPlan.js +1 -0
  31. package/dist/packages/core/src/domain/RequirementPlan.js.map +1 -1
  32. package/dist/packages/core/src/domain/RequirementRemoval.js +161 -0
  33. package/dist/packages/core/src/domain/RequirementRemoval.js.map +1 -0
  34. package/dist/packages/core/src/domain/ScenarioCoverage.js +178 -0
  35. package/dist/packages/core/src/domain/ScenarioCoverage.js.map +1 -0
  36. package/dist/packages/core/src/domain/SpecSections.js +206 -0
  37. package/dist/packages/core/src/domain/SpecSections.js.map +1 -0
  38. package/dist/packages/core/src/domain/TestCommand.js +82 -0
  39. package/dist/packages/core/src/domain/TestCommand.js.map +1 -0
  40. package/dist/packages/core/src/domain/TraceabilityFormat.js +45 -2
  41. package/dist/packages/core/src/domain/TraceabilityFormat.js.map +1 -1
  42. package/dist/packages/core/src/infrastructure/HarnessConfigFile.js +31 -0
  43. package/dist/packages/core/src/infrastructure/HarnessConfigFile.js.map +1 -1
  44. package/dist/packages/core/test/unit/adversarial-probe.test.js +81 -0
  45. package/dist/packages/core/test/unit/adversarial-probe.test.js.map +1 -0
  46. package/dist/packages/core/test/unit/done-verification.test.js +84 -0
  47. package/dist/packages/core/test/unit/done-verification.test.js.map +1 -0
  48. package/dist/packages/core/test/unit/gate-command-integrity.test.js +114 -0
  49. package/dist/packages/core/test/unit/gate-command-integrity.test.js.map +1 -0
  50. package/dist/packages/core/test/unit/gherkin-quality.test.js +28 -0
  51. package/dist/packages/core/test/unit/gherkin-quality.test.js.map +1 -1
  52. package/dist/packages/core/test/unit/multi-stack.test.js +86 -0
  53. package/dist/packages/core/test/unit/multi-stack.test.js.map +1 -0
  54. package/dist/packages/core/test/unit/new-requirement.test.js +67 -0
  55. package/dist/packages/core/test/unit/new-requirement.test.js.map +1 -0
  56. package/dist/packages/core/test/unit/precedents.test.js +99 -0
  57. package/dist/packages/core/test/unit/precedents.test.js.map +1 -0
  58. package/dist/packages/core/test/unit/requirement-removal.test.js +124 -0
  59. package/dist/packages/core/test/unit/requirement-removal.test.js.map +1 -0
  60. package/dist/packages/core/test/unit/scenario-coverage.test.js +146 -0
  61. package/dist/packages/core/test/unit/scenario-coverage.test.js.map +1 -0
  62. package/dist/packages/core/test/unit/spec-sections.test.js +146 -0
  63. package/dist/packages/core/test/unit/spec-sections.test.js.map +1 -0
  64. package/dist/packages/core/test/unit/test-command.test.js +81 -0
  65. package/dist/packages/core/test/unit/test-command.test.js.map +1 -0
  66. package/dist/packages/core/test/unit/validate-project.test.js +21 -0
  67. package/dist/packages/core/test/unit/validate-project.test.js.map +1 -1
  68. package/dist/scripts/agents/commands.js +1 -1
  69. package/dist/scripts/agents/commands.js.map +1 -1
  70. package/dist/scripts/agents/init.js +59 -15
  71. package/dist/scripts/agents/init.js.map +1 -1
  72. package/dist/scripts/change/instructions.js +2 -2
  73. package/dist/scripts/change/instructions.js.map +1 -1
  74. package/dist/scripts/check.js +10 -0
  75. package/dist/scripts/check.js.map +1 -0
  76. package/dist/scripts/cli/commands/change/ChangeCommand.js +2 -2
  77. package/dist/scripts/cli/commands/change/ChangeCommand.js.map +1 -1
  78. package/dist/scripts/cli/commands/config/CiInitCommand.js +1 -1
  79. package/dist/scripts/cli/commands/config/CiInitCommand.js.map +1 -1
  80. package/dist/scripts/cli/commands/harness/RunCommand.js +214 -9
  81. package/dist/scripts/cli/commands/harness/RunCommand.js.map +1 -1
  82. package/dist/scripts/cli/commands/pack/InferPackCommand.js +331 -31
  83. package/dist/scripts/cli/commands/pack/InferPackCommand.js.map +1 -1
  84. package/dist/scripts/cli/commands/project/AdoptCommand.js +86 -9
  85. package/dist/scripts/cli/commands/project/AdoptCommand.js.map +1 -1
  86. package/dist/scripts/cli/commands/project/InitProjectCommand.js +286 -45
  87. package/dist/scripts/cli/commands/project/InitProjectCommand.js.map +1 -1
  88. package/dist/scripts/cli/commands/project/UpdateCommand.js +118 -8
  89. package/dist/scripts/cli/commands/project/UpdateCommand.js.map +1 -1
  90. package/dist/scripts/cli/commands/quality/CheckCommand.js +184 -0
  91. package/dist/scripts/cli/commands/quality/CheckCommand.js.map +1 -0
  92. package/dist/scripts/cli/commands/quality/DoctorCommand.js +20 -2
  93. package/dist/scripts/cli/commands/quality/DoctorCommand.js.map +1 -1
  94. package/dist/scripts/cli/commands/quality/FixCommand.js +1 -1
  95. package/dist/scripts/cli/commands/quality/FixCommand.js.map +1 -1
  96. package/dist/scripts/cli/commands/quality/ReportCommand.js +1 -1
  97. package/dist/scripts/cli/commands/quality/ReportCommand.js.map +1 -1
  98. package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js +406 -24
  99. package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js.map +1 -1
  100. package/dist/scripts/cli/commands/spec/DoneCommand.js +108 -0
  101. package/dist/scripts/cli/commands/spec/DoneCommand.js.map +1 -1
  102. package/dist/scripts/cli/commands/spec/NewCommand.js +178 -0
  103. package/dist/scripts/cli/commands/spec/NewCommand.js.map +1 -0
  104. package/dist/scripts/cli/commands/spec/PlanCommand.js +8 -2
  105. package/dist/scripts/cli/commands/spec/PlanCommand.js.map +1 -1
  106. package/dist/scripts/cli/commands/spec/ReqCommand.js +124 -4
  107. package/dist/scripts/cli/commands/spec/ReqCommand.js.map +1 -1
  108. package/dist/scripts/cli/commands/spec/StatusCommand.js +84 -32
  109. package/dist/scripts/cli/commands/spec/StatusCommand.js.map +1 -1
  110. package/dist/scripts/docs/build-site.js +145 -35
  111. package/dist/scripts/docs/build-site.js.map +1 -1
  112. package/dist/scripts/docs/components.js +208 -0
  113. package/dist/scripts/docs/components.js.map +1 -0
  114. package/dist/scripts/docs/highlight.js +180 -0
  115. package/dist/scripts/docs/highlight.js.map +1 -0
  116. package/dist/scripts/docs/icons.js +63 -0
  117. package/dist/scripts/docs/icons.js.map +1 -0
  118. package/dist/scripts/docs/nav.js +9 -3
  119. package/dist/scripts/docs/nav.js.map +1 -1
  120. package/dist/scripts/gen_mcp_tools.js +22 -2
  121. package/dist/scripts/gen_mcp_tools.js.map +1 -1
  122. package/dist/scripts/harness/init.js +101 -40
  123. package/dist/scripts/harness/init.js.map +1 -1
  124. package/dist/scripts/harness/worktree-lock.js +161 -0
  125. package/dist/scripts/harness/worktree-lock.js.map +1 -0
  126. package/dist/scripts/infer_pack.js +4 -1
  127. package/dist/scripts/infer_pack.js.map +1 -1
  128. package/dist/scripts/lib/surface.js +88 -38
  129. package/dist/scripts/lib/surface.js.map +1 -1
  130. package/dist/scripts/new.js +10 -0
  131. package/dist/scripts/new.js.map +1 -0
  132. package/dist/scripts/plugin/gate-hook.js +2 -2
  133. package/dist/scripts/plugin/gate-hook.js.map +1 -1
  134. package/package.json +5 -2
  135. package/templates/adopt/AI_RULES.md.tpl +1 -1
  136. package/templates/adopt/spec.md.tpl +4 -4
  137. package/templates/base/spec.md.tpl +12 -0
  138. package/templates/ci/azure.yml.tpl +2 -2
  139. package/templates/ci/github.yml.tpl +2 -2
  140. package/templates/ci/gitlab.yml.tpl +1 -1
  141. package/templates/ci/jenkins.tpl +1 -1
  142. package/templates/contracts/test-strategy.md.tpl +2 -2
  143. package/templates/harness/harness.config.yaml.tpl +3 -3
  144. package/templates/harness/prompt-prefix.md.tpl +2 -5
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ /**
3
+ * Fase 4.1: `req add` had no counterpart, so two cold adoptions repaired the
4
+ * matrix by hand with a script.
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const node_test_1 = require("node:test");
41
+ const assert = __importStar(require("node:assert/strict"));
42
+ const RequirementRemoval_1 = require("../../src/domain/RequirementRemoval");
43
+ const HEADER = "| Requirement | Scenario ID | Feature file | Use Case | Command/Query | Aggregate | Event | Technical artifact | Test artifact | Status |\n" +
44
+ "| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |";
45
+ const MATRIX = [
46
+ HEADER,
47
+ "| REQ-001 | SCN-001 | `features/core/health.feature` | UC-001 Health | - | - | - | src/h.js | tests/h.js | Verified |",
48
+ "| REQ-002 | SCN-002 | `features/billing/totals.feature` | UC-002 Totals | - | - | - | src/t.js | tests/t.js | Draft |",
49
+ "| REQ-003 | SCN-003 | `features/core/health.feature` | UC-003 Also health | - | - | - | src/x.js | tests/x.js | Draft |",
50
+ ].join("\n");
51
+ const SPEC = [
52
+ "# Spec",
53
+ "",
54
+ "## 8. Key requirements",
55
+ "",
56
+ "| ID | Requirement | Priority | Status |",
57
+ "|---|---|---|---|",
58
+ "| REQ-002 | Totals are rounded | Must | Draft |",
59
+ "",
60
+ "### REQ-002 — Totals are rounded",
61
+ "",
62
+ "The system MUST satisfy: Totals are rounded.",
63
+ "",
64
+ "### REQ-003 — Also health",
65
+ "",
66
+ "kept",
67
+ ].join("\n");
68
+ (0, node_test_1.test)("the plan names every row the id owns", () => {
69
+ const plan = (0, RequirementRemoval_1.planRemoval)(MATRIX, "REQ-002", SPEC);
70
+ assert.equal(plan.rows.length, 1);
71
+ assert.deepEqual(plan.statuses, ["Draft"]);
72
+ assert.equal(plan.hasProse, true);
73
+ });
74
+ (0, node_test_1.test)("a feature file another row still uses is not orphaned", () => {
75
+ // REQ-001 and REQ-003 share health.feature; removing one leaves it referenced.
76
+ assert.deepEqual((0, RequirementRemoval_1.planRemoval)(MATRIX, "REQ-001", SPEC).orphanedFeatures, []);
77
+ assert.deepEqual((0, RequirementRemoval_1.planRemoval)(MATRIX, "REQ-002", SPEC).orphanedFeatures, [
78
+ "features/billing/totals.feature",
79
+ ]);
80
+ });
81
+ (0, node_test_1.test)("a delivered requirement is flagged, a draft is not", () => {
82
+ // Removing an Implemented row deletes the record that something shipped.
83
+ assert.equal((0, RequirementRemoval_1.isDelivered)("Verified"), true);
84
+ assert.equal((0, RequirementRemoval_1.isDelivered)("Implemented"), true);
85
+ assert.equal((0, RequirementRemoval_1.isDelivered)("Draft"), false);
86
+ assert.equal((0, RequirementRemoval_1.isDelivered)(""), false);
87
+ assert.equal((0, RequirementRemoval_1.planRemoval)(MATRIX, "REQ-001", SPEC).statuses.some(RequirementRemoval_1.isDelivered), true);
88
+ });
89
+ (0, node_test_1.test)("removing takes the row and leaves the others alone", () => {
90
+ const after = (0, RequirementRemoval_1.removeMatrixRows)(MATRIX, "REQ-002");
91
+ assert.ok(!after.includes("REQ-002"));
92
+ assert.ok(after.includes("REQ-001"));
93
+ assert.ok(after.includes("REQ-003"));
94
+ assert.ok(after.includes("| Requirement | Scenario ID |"), "the header survives");
95
+ });
96
+ (0, node_test_1.test)("duplicate rows under one id all go", () => {
97
+ const withDupe = MATRIX + "\n| REQ-002 | SCN-009 | - | UC-002 again | - | - | - | - | - | Draft |";
98
+ assert.equal((0, RequirementRemoval_1.planRemoval)(withDupe, "REQ-002", SPEC).rows.length, 2);
99
+ assert.ok(!(0, RequirementRemoval_1.removeMatrixRows)(withDupe, "REQ-002").includes("REQ-002"));
100
+ });
101
+ (0, node_test_1.test)("the prose goes: both the section and the table row", () => {
102
+ const after = (0, RequirementRemoval_1.removeSpecProse)(SPEC, "REQ-002");
103
+ assert.ok(!after.includes("REQ-002"));
104
+ assert.ok(!after.includes("Totals are rounded"), "the section body goes with its heading");
105
+ assert.ok(after.includes("### REQ-003 — Also health"), "the next requirement survives");
106
+ assert.ok(after.includes("kept"));
107
+ assert.ok(after.includes("## 8. Key requirements"), "the enclosing section survives");
108
+ });
109
+ (0, node_test_1.test)("removing the last requirement does not eat the rest of the document", () => {
110
+ const spec = "## 8. Key requirements\n\n### REQ-002 — Gone\n\nbody\n\n## 9. Non-functional\n\nkept\n";
111
+ const after = (0, RequirementRemoval_1.removeSpecProse)(spec, "REQ-002");
112
+ assert.ok(!after.includes("REQ-002"));
113
+ assert.ok(after.includes("## 9. Non-functional"));
114
+ assert.ok(after.includes("kept"));
115
+ });
116
+ (0, node_test_1.test)("an id that is not there changes nothing", () => {
117
+ assert.equal((0, RequirementRemoval_1.removeMatrixRows)(MATRIX, "REQ-999"), MATRIX);
118
+ assert.equal((0, RequirementRemoval_1.planRemoval)(MATRIX, "REQ-999", SPEC).rows.length, 0);
119
+ });
120
+ (0, node_test_1.test)("REQ-01 does not match REQ-014", () => {
121
+ const m = HEADER + "\n| REQ-014 | - | - | UC | - | - | - | - | - | Draft |";
122
+ assert.equal((0, RequirementRemoval_1.removeMatrixRows)(m, "REQ-01"), m);
123
+ });
124
+ //# sourceMappingURL=requirement-removal.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirement-removal.test.js","sourceRoot":"","sources":["../../../../../packages/core/test/unit/requirement-removal.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ /**
3
+ * #168: a scenario declared in a feature file that nothing tests.
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const node_test_1 = require("node:test");
40
+ const assert = __importStar(require("node:assert/strict"));
41
+ const ScenarioCoverage_1 = require("../../src/domain/ScenarioCoverage");
42
+ const FEATURE = `Feature: Invoice totals
43
+
44
+ Scenario: SCN-010 subtotal is the sum of line amounts
45
+ Given two lines
46
+ When the invoice is totalled
47
+ Then the subtotal is their sum
48
+
49
+ Scenario: SCN-011 tax is applied per line
50
+ Given two rates
51
+ When the invoice is totalled
52
+ Then each line carries its own rate
53
+
54
+ Scenario: SCN-012 a fully discounted invoice carries no tax
55
+ Given a 100% discount
56
+ When the invoice is totalled
57
+ Then the tax is zero
58
+ `;
59
+ (0, node_test_1.test)("every scenario in the file is found, not just the one the row names", () => {
60
+ assert.deepEqual((0, ScenarioCoverage_1.scenariosIn)(FEATURE).map((s) => s.needles[0]), ["SCN-010", "SCN-011", "SCN-012"]);
61
+ });
62
+ (0, node_test_1.test)("the scenario nothing tests is the one reported", () => {
63
+ // The measured case: an agent wrote tests for the scenarios it could satisfy
64
+ // and skipped the one it could not.
65
+ const tests = [
66
+ `test("SCN-010 subtotal is the sum of line amounts", () => {});
67
+ test("SCN-011 tax is applied per line", () => {});`,
68
+ ];
69
+ const missing = (0, ScenarioCoverage_1.uncoveredScenarios)(FEATURE, tests);
70
+ assert.equal(missing.length, 1);
71
+ assert.match(missing[0].title, /fully discounted/);
72
+ });
73
+ (0, node_test_1.test)("a fully covered feature reports nothing", () => {
74
+ const tests = ["SCN-010 SCN-011 SCN-012"];
75
+ assert.deepEqual((0, ScenarioCoverage_1.uncoveredScenarios)(FEATURE, tests), []);
76
+ });
77
+ (0, node_test_1.test)("a tag identifies a scenario even after the title is reworded", () => {
78
+ // The one edit that otherwise defeats every link to a scenario.
79
+ const tagged = `Feature: F
80
+
81
+ @REQ-001 @SCN-042
82
+ Scenario: something else entirely now
83
+ Given a thing
84
+ When it happens
85
+ Then it holds
86
+ `;
87
+ assert.deepEqual((0, ScenarioCoverage_1.scenariosIn)(tagged)[0].needles, ["SCN-042"]);
88
+ assert.deepEqual((0, ScenarioCoverage_1.uncoveredScenarios)(tagged, ["covers @SCN-042 here"]), []);
89
+ });
90
+ (0, node_test_1.test)("without an id anywhere, the title is the identity", () => {
91
+ const untagged = `Feature: F
92
+
93
+ Scenario: the cart rejects a negative quantity
94
+ Given a cart
95
+ When a negative quantity is added
96
+ Then it is rejected
97
+ `;
98
+ assert.deepEqual((0, ScenarioCoverage_1.scenariosIn)(untagged)[0].needles, ["the cart rejects a negative quantity"]);
99
+ assert.deepEqual((0, ScenarioCoverage_1.uncoveredScenarios)(untagged, ['test("The cart rejects a negative quantity!", ...)']), [], "punctuation and case must not break a title match");
100
+ assert.equal((0, ScenarioCoverage_1.uncoveredScenarios)(untagged, ["something unrelated"]).length, 1);
101
+ });
102
+ (0, node_test_1.test)("a Scenario Outline counts — the widest scenarios must not be the unchecked ones", () => {
103
+ const outline = `Feature: F
104
+
105
+ Scenario Outline: SCN-050 rounding across currencies
106
+ Given <amount>
107
+ When it is rounded
108
+ Then it is <result>
109
+
110
+ Examples:
111
+ | amount | result |
112
+ | 1.005 | 1.01 |
113
+ `;
114
+ assert.equal((0, ScenarioCoverage_1.scenariosIn)(outline).length, 1);
115
+ assert.equal((0, ScenarioCoverage_1.uncoveredScenarios)(outline, ["nothing"]).length, 1);
116
+ });
117
+ (0, node_test_1.test)("a scenario proved in any of several test files is proved", () => {
118
+ const missing = (0, ScenarioCoverage_1.uncoveredScenarios)(FEATURE, ["SCN-010", "SCN-011", "SCN-012 over here"]);
119
+ assert.deepEqual(missing, []);
120
+ });
121
+ (0, node_test_1.test)("no test sources at all leaves every scenario uncovered", () => {
122
+ assert.equal((0, ScenarioCoverage_1.uncoveredScenarios)(FEATURE, []).length, 3);
123
+ });
124
+ (0, node_test_1.test)("normalise strips what should not decide a match", () => {
125
+ assert.equal((0, ScenarioCoverage_1.normalise)("SCN-010: Subtotal!"), (0, ScenarioCoverage_1.normalise)("scn010 subtotal"));
126
+ });
127
+ // ── Fase 1.2: a link that exists but lies ────────────────────────────────────
128
+ (0, node_test_1.test)("a test artifact naming the requirement is evidence enough", () => {
129
+ assert.equal((0, ScenarioCoverage_1.linkIsUnevidenced)("REQ-014", "", ['test("REQ-014 vets are listed")']), false);
130
+ });
131
+ (0, node_test_1.test)("a test artifact naming one of the requirement's scenarios is evidence", () => {
132
+ assert.equal((0, ScenarioCoverage_1.linkIsUnevidenced)("REQ-010", FEATURE, ["SCN-011 tax"]), false);
133
+ });
134
+ (0, node_test_1.test)("the measured lie: a seeded row pointed at somebody else's test", () => {
135
+ // A "Vet" requirement declaring PetValidatorTests.java as its proof. The row
136
+ // has no scenario, so there is nothing for the scenario check to match on —
137
+ // which is exactly why those rows lie most easily.
138
+ assert.equal((0, ScenarioCoverage_1.linkIsUnevidenced)("REQ-014", "", ["class PetTypeFormatterTests { void formatsAName() {} }"]), true);
139
+ });
140
+ (0, node_test_1.test)("no test sources at all is not evidence", () => {
141
+ assert.equal((0, ScenarioCoverage_1.linkIsUnevidenced)("REQ-014", FEATURE, []), true);
142
+ });
143
+ (0, node_test_1.test)("a row with no requirement id is not this check's business", () => {
144
+ assert.equal((0, ScenarioCoverage_1.linkIsUnevidenced)("", FEATURE, ["anything"]), false);
145
+ });
146
+ //# sourceMappingURL=scenario-coverage.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario-coverage.test.js","sourceRoot":"","sources":["../../../../../packages/core/test/unit/scenario-coverage.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ /**
3
+ * Fase 3.1: `req add` wrote a matrix row and no prose anywhere.
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const node_test_1 = require("node:test");
40
+ const assert = __importStar(require("node:assert/strict"));
41
+ const SpecSections_1 = require("../../src/domain/SpecSections");
42
+ (0, node_test_1.test)("the generated section carries an obligation keyword", () => {
43
+ // Otherwise the section fails --strict-requirements, and a project would be
44
+ // failing a gate over text the tool itself just wrote.
45
+ const section = (0, SpecSections_1.renderRequirementSection)("REQ-014", "Vets are listed alphabetically");
46
+ assert.match(section, /^## REQ-014 — Vets are listed alphabetically$/m);
47
+ assert.match(section, /\bMUST\b/);
48
+ });
49
+ (0, node_test_1.test)("the section says it is a draft, rather than pretending to be finished", () => {
50
+ assert.match((0, SpecSections_1.renderRequirementSection)("REQ-014", "Vets are listed"), /Replace this sentence/);
51
+ });
52
+ (0, node_test_1.test)("a title starting with an identifier still reads as a sentence", () => {
53
+ // `MUST res.redirect sets Location` is not English. `MUST satisfy:` is, for
54
+ // every title, without a heuristic that guesses at grammar.
55
+ assert.match((0, SpecSections_1.renderRequirementSection)("REQ-002", "res.redirect sets Location and status 302"), /MUST satisfy: res\.redirect sets Location and status 302\./);
56
+ assert.match((0, SpecSections_1.renderRequirementSection)("REQ-003", "HTTP caching is respected"), /MUST satisfy: HTTP caching is respected\./);
57
+ });
58
+ (0, node_test_1.test)("an existing section is found, and a different id is not", () => {
59
+ const spec = "# Spec\n\n## REQ-001 — One\n\ntext\n\n## REQ-014 — Fourteen\n\ntext\n";
60
+ assert.equal((0, SpecSections_1.hasRequirementSection)(spec, "REQ-014"), true);
61
+ assert.equal((0, SpecSections_1.hasRequirementSection)(spec, "REQ-01"), false, "REQ-01 must not match REQ-014");
62
+ assert.equal((0, SpecSections_1.hasRequirementSection)(spec, "REQ-999"), false);
63
+ assert.deepEqual((0, SpecSections_1.requirementSections)(spec), ["REQ-001", "REQ-014"]);
64
+ });
65
+ (0, node_test_1.test)("a mention in prose is not a section, but a nested heading is", () => {
66
+ // The shipped template puts requirements under "8. Key requirements", so
67
+ // insisting on top-level `##` would reject documents that are perfectly well
68
+ // organised. A sentence naming the id is still not a section.
69
+ assert.equal((0, SpecSections_1.hasRequirementSection)("# Spec\n\nSee REQ-014 for details.\n", "REQ-014"), false);
70
+ assert.equal((0, SpecSections_1.hasRequirementSection)("# Spec\n\n### REQ-014 — Nested\n\ntext\n", "REQ-014"), true);
71
+ assert.equal((0, SpecSections_1.hasRequirementSection)("# Spec\n\n##### REQ-014 — Too deep\n", "REQ-014"), false);
72
+ });
73
+ (0, node_test_1.test)("a nested section ends at the next heading of its own level", () => {
74
+ const spec = [
75
+ "## 8. Key requirements",
76
+ "",
77
+ "### REQ-001 — First",
78
+ "",
79
+ "The system MUST do the first thing.",
80
+ "",
81
+ "#### Notes",
82
+ "",
83
+ "still part of REQ-001",
84
+ "",
85
+ "### REQ-002 — Second",
86
+ "",
87
+ "not part of REQ-001",
88
+ ].join("\n");
89
+ const section = (0, SpecSections_1.extractRequirementSection)(spec, "REQ-001");
90
+ assert.match(section, /MUST do the first thing/);
91
+ assert.match(section, /still part of REQ-001/, "a deeper sub-heading stays inside");
92
+ assert.doesNotMatch(section, /not part of REQ-001/);
93
+ });
94
+ (0, node_test_1.test)("appending adds the section once and is idempotent", () => {
95
+ const before = "# Spec\n\n## REQ-001 — One\n\ntext\n";
96
+ const first = (0, SpecSections_1.appendRequirementSection)(before, "REQ-002", "Totals are rounded");
97
+ assert.equal(first.added, true);
98
+ assert.equal((0, SpecSections_1.hasRequirementSection)(first.content, "REQ-002"), true);
99
+ const second = (0, SpecSections_1.appendRequirementSection)(first.content, "REQ-002", "Totals are rounded");
100
+ assert.equal(second.added, false);
101
+ assert.equal(second.content, first.content, "running req add twice must not duplicate prose");
102
+ });
103
+ (0, node_test_1.test)("appending does not reorder what a person wrote", () => {
104
+ // spec.md is a document someone writes in. Sorting their prose to satisfy an
105
+ // id order is a worse surprise than a section at the end.
106
+ const before = "# Spec\n\n## REQ-050 — Later\n\ntext\n";
107
+ const after = (0, SpecSections_1.appendRequirementSection)(before, "REQ-002", "Earlier").content;
108
+ assert.ok(after.indexOf("REQ-050") < after.indexOf("REQ-002"));
109
+ });
110
+ (0, node_test_1.test)("an empty spec gets a section without a leading blank run", () => {
111
+ const { content } = (0, SpecSections_1.appendRequirementSection)("", "REQ-001", "First");
112
+ assert.ok(content.startsWith("## REQ-001"));
113
+ });
114
+ // ── The shapes real documents turned out to use ──────────────────────────────
115
+ (0, node_test_1.test)("a labelled heading declares its requirement", () => {
116
+ // `### Requirement: REQ-100 — title` is what capability specs use. Four
117
+ // shapes turned up before this stopped enumerating them.
118
+ const spec = "## Requirements\n\n### Requirement: REQ-100 — A change is a folder\n\ntext\n";
119
+ assert.equal((0, SpecSections_1.hasRequirementSection)(spec, "REQ-100"), true);
120
+ assert.match((0, SpecSections_1.extractRequirementSection)(spec, "REQ-100"), /A change is a folder/);
121
+ });
122
+ (0, node_test_1.test)("the §8 table counts as the requirement's text", () => {
123
+ // The original `init` template, and this repository's own spec.md. Outlawing
124
+ // it would have turned every project built from that template red on
125
+ // upgrade, over text that is right there in the document.
126
+ const spec = [
127
+ "## 8. Key requirements",
128
+ "",
129
+ "| ID | Requirement | Priority | Status |",
130
+ "|---|---|---|---|",
131
+ "| REQ-001 | `init` generates a valid project skeleton. | Must | Verified |",
132
+ "| REQ-002 | - | Must | Draft |",
133
+ ].join("\n");
134
+ assert.equal((0, SpecSections_1.hasRequirementSection)(spec, "REQ-001"), true);
135
+ assert.match((0, SpecSections_1.extractRequirementSection)(spec, "REQ-001"), /generates a valid project skeleton/);
136
+ // A row with no prose is an id with nothing behind it — the case worth catching.
137
+ assert.equal((0, SpecSections_1.hasRequirementSection)(spec, "REQ-002"), false);
138
+ assert.deepEqual((0, SpecSections_1.requirementSections)(spec), ["REQ-001"]);
139
+ });
140
+ (0, node_test_1.test)("a TBD or empty requirement cell is not text", () => {
141
+ for (const cell of ["TBD", "", " ", "-"]) {
142
+ const spec = `| ID | Requirement |\n|---|---|\n| REQ-005 | ${cell} |\n`;
143
+ assert.equal((0, SpecSections_1.hasRequirementSection)(spec, "REQ-005"), false, `'${cell}' should not count`);
144
+ }
145
+ });
146
+ //# sourceMappingURL=spec-sections.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-sections.test.js","sourceRoot":"","sources":["../../../../../packages/core/test/unit/spec-sections.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ /**
3
+ * Fase 2.3: two detectors disagreed on the same pom.xml.
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const node_test_1 = require("node:test");
40
+ const assert = __importStar(require("node:assert/strict"));
41
+ const TestCommand_1 = require("../../src/domain/TestCommand");
42
+ function files(map) {
43
+ return {
44
+ exists: (p) => Object.prototype.hasOwnProperty.call(map, p),
45
+ read: (p) => (typeof map[p] === "string" ? map[p] : null),
46
+ };
47
+ }
48
+ (0, node_test_1.test)("the wrapper wins, because the harness runs in a bare worktree", () => {
49
+ // `./mvnw` is checked in and works there; `mvn` depends on the machine.
50
+ // Getting this wrong burns one of the agent's three attempts on
51
+ // "command not found".
52
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "pom.xml": true, mvnw: true })), "./mvnw -B test");
53
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "build.gradle": true, gradlew: true })), "./gradlew test");
54
+ });
55
+ (0, node_test_1.test)("without a wrapper, the system tool is the only option", () => {
56
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "pom.xml": true })), "mvn -B test");
57
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "build.gradle.kts": true })), "gradle test");
58
+ });
59
+ (0, node_test_1.test)("a declared npm script is the project's own answer", () => {
60
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "package.json": '{"scripts":{"test":"vitest"}}' })), "npm test");
61
+ });
62
+ (0, node_test_1.test)("a malformed package.json does not crash the caller", () => {
63
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "package.json": "{ not json" })), "npm test");
64
+ });
65
+ (0, node_test_1.test)("the other ecosystems", () => {
66
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "Cargo.toml": true })), "cargo test");
67
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "go.mod": true })), "go test ./...");
68
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "pyproject.toml": true })), "pytest");
69
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "setup.py": true })), "pytest");
70
+ });
71
+ (0, node_test_1.test)("nothing recognisable returns null, and null is a real answer", () => {
72
+ // Guessing `npm test` into a Python repository is how AI_RULES.md ended up
73
+ // reading `Testing: unknown` two lines above `Test command: python -m pytest`.
74
+ assert.equal((0, TestCommand_1.detectTestCommand)(files({ "README.md": true })), null);
75
+ });
76
+ (0, node_test_1.test)("both callers would now agree on the same project", () => {
77
+ const project = files({ "pom.xml": true, mvnw: true });
78
+ assert.equal((0, TestCommand_1.detectTestCommand)(project), (0, TestCommand_1.detectTestCommand)(project));
79
+ assert.equal((0, TestCommand_1.detectTestCommand)(project), "./mvnw -B test");
80
+ });
81
+ //# sourceMappingURL=test-command.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-command.test.js","sourceRoot":"","sources":["../../../../../packages/core/test/unit/test-command.test.ts"],"names":[],"mappings":"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"}
@@ -96,6 +96,27 @@ const useCase = (content = null) => new ValidateProjectUseCase_1.ValidateProject
96
96
  assert.match(finding.message, /Shipped/);
97
97
  assert.ok(finding.fixLines?.[0].includes("Ready for Dev"));
98
98
  });
99
+ (0, node_test_1.test)("a repeated Requirement ID is an error — it is the primary key", () => {
100
+ // The state three cold adoptions reached through `adopt` then `req add`:
101
+ // two different requirements under one id, every gate green. `req link`
102
+ // writes every matching row, so linking one retargets the other.
103
+ const { report } = useCase().checkMatrix(richMatrix([
104
+ ["REQ-001", "SCN-001", "tests/a.test.ts", "Draft"],
105
+ ["REQ-002", "SCN-002", "tests/b.test.ts", "Draft"],
106
+ ["REQ-002", "SCN-003", "tests/c.test.ts", "Draft"],
107
+ ]));
108
+ const finding = report.errors.find((e) => e.code === "duplicate_requirement_id");
109
+ assert.ok(finding, "expected duplicate_requirement_id");
110
+ assert.match(finding.message, /REQ-002/);
111
+ assert.ok(finding.fixLines?.length, "a finding without a fix is not actionable");
112
+ });
113
+ (0, node_test_1.test)("distinct requirement ids are left alone", () => {
114
+ const { report } = useCase().checkMatrix(richMatrix([
115
+ ["REQ-001", "SCN-001", "tests/a.test.ts", "Draft"],
116
+ ["REQ-002", "SCN-002", "tests/b.test.ts", "Draft"],
117
+ ]));
118
+ assert.equal(report.errors.filter((e) => e.code === "duplicate_requirement_id").length, 0);
119
+ });
99
120
  (0, node_test_1.test)("a repeated Scenario ID is an error, but `-` is not an id", () => {
100
121
  const { report } = useCase().checkMatrix(richMatrix([
101
122
  ["REQ-001", "SCN-001", "tests/a.test.ts", "Draft"],
@@ -1 +1 @@
1
- {"version":3,"file":"validate-project.test.js","sourceRoot":"","sources":["../../../../../packages/core/test/unit/validate-project.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate-project.test.js","sourceRoot":"","sources":["../../../../../packages/core/test/unit/validate-project.test.ts"],"names":[],"mappings":"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"}
@@ -58,7 +58,7 @@ exports.STEPS = [
58
58
  run: ["specgate change instructions apply --json", "specgate plan --json"],
59
59
  guidance: [
60
60
  "One requirement at a time. `specgate plan` is the queue.",
61
- "Write the test first. Set the row's status to `In Dev` only once it exists, or `validate --strict-tdd` fails with `[TDD-1]`.",
61
+ "Write the test first. Set the row's status to `In Dev` only once it exists, or `validate --strict` fails with `[TDD-1]`.",
62
62
  "Never edit `docs/specs/traceability.md` by hand — `specgate req link` and `specgate done` write it.",
63
63
  ],
64
64
  },
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../scripts/agents/commands.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAEU,QAAA,KAAK,GAAG;IACnB;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,mDAAmD;QAC5D,IAAI,EAAE,wDAAwD;QAC9D,GAAG,EAAE,CAAC,wBAAwB,EAAE,sBAAsB,CAAC;QACvD,QAAQ,EAAE;YACR,kFAAkF;YAClF,2FAA2F;YAC3F,4EAA4E;SAC7E;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,iDAAiD;QAC1D,IAAI,EAAE,oDAAoD;QAC1D,GAAG,EAAE;YACH,iCAAiC;YACjC,8CAA8C;YAC9C,2CAA2C;SAC5C;QACD,QAAQ,EAAE;YACR,4JAA4J;YAC5J,iEAAiE;YACjE,mIAAmI;SACpI;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,4CAA4C;QACrD,IAAI,EAAE,oDAAoD;QAC1D,GAAG,EAAE,CAAC,iCAAiC,EAAE,4BAA4B,CAAC;QACtE,QAAQ,EAAE;YACR,kEAAkE;YAClE,kFAAkF;YAClF,gFAAgF;SACjF;KACF;IACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,+CAA+C;QACxD,IAAI,EAAE,qDAAqD;QAC3D,GAAG,EAAE,CAAC,2CAA2C,EAAE,sBAAsB,CAAC;QAC1E,QAAQ,EAAE;YACR,0DAA0D;YAC1D,8HAA8H;YAC9H,qGAAqG;SACtG;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,sCAAsC;QAC/C,IAAI,EAAE,6CAA6C;QACnD,GAAG,EAAE;YACH,6CAA6C;YAC7C,+CAA+C;YAC/C,4CAA4C;SAC7C;QACD,QAAQ,EAAE;YACR,oFAAoF;YACpF,oGAAoG;YACpG,yEAAyE;SAC1E;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,gEAAgE;QACzE,IAAI,EAAE,2CAA2C;QACjD,GAAG,EAAE,CAAC,gBAAgB,EAAE,wBAAwB,EAAE,4BAA4B,CAAC;QAC/E,QAAQ,EAAE;YACR,yEAAyE;YACzE,+FAA+F;YAC/F,qGAAqG;SACtG;KACF;CACF,CAAC;AAEF,0EAA0E;AAC7D,QAAA,aAAa,GAAG;IAC3B,qHAAqH;IACrH,2HAA2H;IAC3H,2GAA2G;IAC3G,iFAAiF;IACjF,2HAA2H;CAC5H,CAAC"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../scripts/agents/commands.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAEU,QAAA,KAAK,GAAG;IACnB;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,mDAAmD;QAC5D,IAAI,EAAE,wDAAwD;QAC9D,GAAG,EAAE,CAAC,wBAAwB,EAAE,sBAAsB,CAAC;QACvD,QAAQ,EAAE;YACR,kFAAkF;YAClF,2FAA2F;YAC3F,4EAA4E;SAC7E;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,iDAAiD;QAC1D,IAAI,EAAE,oDAAoD;QAC1D,GAAG,EAAE;YACH,iCAAiC;YACjC,8CAA8C;YAC9C,2CAA2C;SAC5C;QACD,QAAQ,EAAE;YACR,4JAA4J;YAC5J,iEAAiE;YACjE,mIAAmI;SACpI;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,4CAA4C;QACrD,IAAI,EAAE,oDAAoD;QAC1D,GAAG,EAAE,CAAC,iCAAiC,EAAE,4BAA4B,CAAC;QACtE,QAAQ,EAAE;YACR,kEAAkE;YAClE,kFAAkF;YAClF,gFAAgF;SACjF;KACF;IACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,+CAA+C;QACxD,IAAI,EAAE,qDAAqD;QAC3D,GAAG,EAAE,CAAC,2CAA2C,EAAE,sBAAsB,CAAC;QAC1E,QAAQ,EAAE;YACR,0DAA0D;YAC1D,0HAA0H;YAC1H,qGAAqG;SACtG;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,sCAAsC;QAC/C,IAAI,EAAE,6CAA6C;QACnD,GAAG,EAAE;YACH,6CAA6C;YAC7C,+CAA+C;YAC/C,4CAA4C;SAC7C;QACD,QAAQ,EAAE;YACR,oFAAoF;YACpF,oGAAoG;YACpG,yEAAyE;SAC1E;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,gEAAgE;QACzE,IAAI,EAAE,2CAA2C;QACjD,GAAG,EAAE,CAAC,gBAAgB,EAAE,wBAAwB,EAAE,4BAA4B,CAAC;QAC/E,QAAQ,EAAE;YACR,yEAAyE;YACzE,+FAA+F;YAC/F,qGAAqG;SACtG;KACF;CACF,CAAC;AAEF,0EAA0E;AAC7D,QAAA,aAAa,GAAG;IAC3B,qHAAqH;IACrH,2HAA2H;IAC3H,2GAA2G;IAC3G,iFAAiF;IACjF,2HAA2H;CAC5H,CAAC"}