@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.
- package/CHANGELOG.md +196 -0
- package/README.md +17 -25
- package/bin/specgate.ts +23 -5
- package/dist/bin/specgate.js +19 -4
- package/dist/bin/specgate.js.map +1 -1
- package/dist/packages/core/src/application/GenerateAgentPromptUseCase.js +56 -0
- package/dist/packages/core/src/application/GenerateAgentPromptUseCase.js.map +1 -1
- package/dist/packages/core/src/application/ValidateProjectUseCase.js +54 -0
- package/dist/packages/core/src/application/ValidateProjectUseCase.js.map +1 -1
- package/dist/packages/core/src/domain/AdversarialProbe.js +75 -0
- package/dist/packages/core/src/domain/AdversarialProbe.js.map +1 -0
- package/dist/packages/core/src/domain/AgentPrompt.js +52 -3
- package/dist/packages/core/src/domain/AgentPrompt.js.map +1 -1
- package/dist/packages/core/src/domain/DeclaredArtifacts.js +25 -0
- package/dist/packages/core/src/domain/DeclaredArtifacts.js.map +1 -1
- package/dist/packages/core/src/domain/DoneVerification.js +89 -0
- package/dist/packages/core/src/domain/DoneVerification.js.map +1 -0
- package/dist/packages/core/src/domain/GateCommandIntegrity.js +139 -0
- package/dist/packages/core/src/domain/GateCommandIntegrity.js.map +1 -0
- package/dist/packages/core/src/domain/GherkinQuality.js +19 -3
- package/dist/packages/core/src/domain/GherkinQuality.js.map +1 -1
- package/dist/packages/core/src/domain/HarnessConfig.js +6 -0
- package/dist/packages/core/src/domain/HarnessConfig.js.map +1 -1
- package/dist/packages/core/src/domain/MultiStack.js +96 -0
- package/dist/packages/core/src/domain/MultiStack.js.map +1 -0
- package/dist/packages/core/src/domain/NewRequirement.js +46 -0
- package/dist/packages/core/src/domain/NewRequirement.js.map +1 -0
- package/dist/packages/core/src/domain/Precedents.js +96 -0
- package/dist/packages/core/src/domain/Precedents.js.map +1 -0
- package/dist/packages/core/src/domain/RequirementPlan.js +1 -0
- package/dist/packages/core/src/domain/RequirementPlan.js.map +1 -1
- package/dist/packages/core/src/domain/RequirementRemoval.js +161 -0
- package/dist/packages/core/src/domain/RequirementRemoval.js.map +1 -0
- package/dist/packages/core/src/domain/ScenarioCoverage.js +178 -0
- package/dist/packages/core/src/domain/ScenarioCoverage.js.map +1 -0
- package/dist/packages/core/src/domain/SpecSections.js +206 -0
- package/dist/packages/core/src/domain/SpecSections.js.map +1 -0
- package/dist/packages/core/src/domain/TestCommand.js +82 -0
- package/dist/packages/core/src/domain/TestCommand.js.map +1 -0
- package/dist/packages/core/src/domain/TraceabilityFormat.js +45 -2
- package/dist/packages/core/src/domain/TraceabilityFormat.js.map +1 -1
- package/dist/packages/core/src/infrastructure/HarnessConfigFile.js +31 -0
- package/dist/packages/core/src/infrastructure/HarnessConfigFile.js.map +1 -1
- package/dist/packages/core/test/unit/adversarial-probe.test.js +81 -0
- package/dist/packages/core/test/unit/adversarial-probe.test.js.map +1 -0
- package/dist/packages/core/test/unit/done-verification.test.js +84 -0
- package/dist/packages/core/test/unit/done-verification.test.js.map +1 -0
- package/dist/packages/core/test/unit/gate-command-integrity.test.js +114 -0
- package/dist/packages/core/test/unit/gate-command-integrity.test.js.map +1 -0
- package/dist/packages/core/test/unit/gherkin-quality.test.js +28 -0
- package/dist/packages/core/test/unit/gherkin-quality.test.js.map +1 -1
- package/dist/packages/core/test/unit/multi-stack.test.js +86 -0
- package/dist/packages/core/test/unit/multi-stack.test.js.map +1 -0
- package/dist/packages/core/test/unit/new-requirement.test.js +67 -0
- package/dist/packages/core/test/unit/new-requirement.test.js.map +1 -0
- package/dist/packages/core/test/unit/precedents.test.js +99 -0
- package/dist/packages/core/test/unit/precedents.test.js.map +1 -0
- package/dist/packages/core/test/unit/requirement-removal.test.js +124 -0
- package/dist/packages/core/test/unit/requirement-removal.test.js.map +1 -0
- package/dist/packages/core/test/unit/scenario-coverage.test.js +146 -0
- package/dist/packages/core/test/unit/scenario-coverage.test.js.map +1 -0
- package/dist/packages/core/test/unit/spec-sections.test.js +146 -0
- package/dist/packages/core/test/unit/spec-sections.test.js.map +1 -0
- package/dist/packages/core/test/unit/test-command.test.js +81 -0
- package/dist/packages/core/test/unit/test-command.test.js.map +1 -0
- package/dist/packages/core/test/unit/validate-project.test.js +21 -0
- package/dist/packages/core/test/unit/validate-project.test.js.map +1 -1
- package/dist/scripts/agents/commands.js +1 -1
- package/dist/scripts/agents/commands.js.map +1 -1
- package/dist/scripts/agents/init.js +59 -15
- package/dist/scripts/agents/init.js.map +1 -1
- package/dist/scripts/change/instructions.js +2 -2
- package/dist/scripts/change/instructions.js.map +1 -1
- package/dist/scripts/check.js +10 -0
- package/dist/scripts/check.js.map +1 -0
- package/dist/scripts/cli/commands/change/ChangeCommand.js +2 -2
- package/dist/scripts/cli/commands/change/ChangeCommand.js.map +1 -1
- package/dist/scripts/cli/commands/config/CiInitCommand.js +1 -1
- package/dist/scripts/cli/commands/config/CiInitCommand.js.map +1 -1
- package/dist/scripts/cli/commands/harness/RunCommand.js +214 -9
- package/dist/scripts/cli/commands/harness/RunCommand.js.map +1 -1
- package/dist/scripts/cli/commands/pack/InferPackCommand.js +331 -31
- package/dist/scripts/cli/commands/pack/InferPackCommand.js.map +1 -1
- package/dist/scripts/cli/commands/project/AdoptCommand.js +86 -9
- package/dist/scripts/cli/commands/project/AdoptCommand.js.map +1 -1
- package/dist/scripts/cli/commands/project/InitProjectCommand.js +286 -45
- package/dist/scripts/cli/commands/project/InitProjectCommand.js.map +1 -1
- package/dist/scripts/cli/commands/project/UpdateCommand.js +118 -8
- package/dist/scripts/cli/commands/project/UpdateCommand.js.map +1 -1
- package/dist/scripts/cli/commands/quality/CheckCommand.js +184 -0
- package/dist/scripts/cli/commands/quality/CheckCommand.js.map +1 -0
- package/dist/scripts/cli/commands/quality/DoctorCommand.js +20 -2
- package/dist/scripts/cli/commands/quality/DoctorCommand.js.map +1 -1
- package/dist/scripts/cli/commands/quality/FixCommand.js +1 -1
- package/dist/scripts/cli/commands/quality/FixCommand.js.map +1 -1
- package/dist/scripts/cli/commands/quality/ReportCommand.js +1 -1
- package/dist/scripts/cli/commands/quality/ReportCommand.js.map +1 -1
- package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js +406 -24
- package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/DoneCommand.js +108 -0
- package/dist/scripts/cli/commands/spec/DoneCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/NewCommand.js +178 -0
- package/dist/scripts/cli/commands/spec/NewCommand.js.map +1 -0
- package/dist/scripts/cli/commands/spec/PlanCommand.js +8 -2
- package/dist/scripts/cli/commands/spec/PlanCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/ReqCommand.js +124 -4
- package/dist/scripts/cli/commands/spec/ReqCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/StatusCommand.js +84 -32
- package/dist/scripts/cli/commands/spec/StatusCommand.js.map +1 -1
- package/dist/scripts/docs/build-site.js +145 -35
- package/dist/scripts/docs/build-site.js.map +1 -1
- package/dist/scripts/docs/components.js +208 -0
- package/dist/scripts/docs/components.js.map +1 -0
- package/dist/scripts/docs/highlight.js +180 -0
- package/dist/scripts/docs/highlight.js.map +1 -0
- package/dist/scripts/docs/icons.js +63 -0
- package/dist/scripts/docs/icons.js.map +1 -0
- package/dist/scripts/docs/nav.js +9 -3
- package/dist/scripts/docs/nav.js.map +1 -1
- package/dist/scripts/gen_mcp_tools.js +22 -2
- package/dist/scripts/gen_mcp_tools.js.map +1 -1
- package/dist/scripts/harness/init.js +101 -40
- package/dist/scripts/harness/init.js.map +1 -1
- package/dist/scripts/harness/worktree-lock.js +161 -0
- package/dist/scripts/harness/worktree-lock.js.map +1 -0
- package/dist/scripts/infer_pack.js +4 -1
- package/dist/scripts/infer_pack.js.map +1 -1
- package/dist/scripts/lib/surface.js +88 -38
- package/dist/scripts/lib/surface.js.map +1 -1
- package/dist/scripts/new.js +10 -0
- package/dist/scripts/new.js.map +1 -0
- package/dist/scripts/plugin/gate-hook.js +2 -2
- package/dist/scripts/plugin/gate-hook.js.map +1 -1
- package/package.json +5 -2
- package/templates/adopt/AI_RULES.md.tpl +1 -1
- package/templates/adopt/spec.md.tpl +4 -4
- package/templates/base/spec.md.tpl +12 -0
- package/templates/ci/azure.yml.tpl +2 -2
- package/templates/ci/github.yml.tpl +2 -2
- package/templates/ci/gitlab.yml.tpl +1 -1
- package/templates/ci/jenkins.tpl +1 -1
- package/templates/contracts/test-strategy.md.tpl +2 -2
- package/templates/harness/harness.config.yaml.tpl +3 -3
- package/templates/harness/prompt-prefix.md.tpl +2 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidateProjectUseCase.js","sourceRoot":"","sources":["../../../../../packages/core/src/application/ValidateProjectUseCase.ts"],"names":[],"mappings":";;;AAAA,iEAA8D;AAE9D,qEASsC;
|
|
1
|
+
{"version":3,"file":"ValidateProjectUseCase.js","sourceRoot":"","sources":["../../../../../packages/core/src/application/ValidateProjectUseCase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The adversarial verification step (D3).
|
|
4
|
+
*
|
|
5
|
+
* ## What it is, and what the advisory reviewer is not
|
|
6
|
+
*
|
|
7
|
+
* The harness already has a reviewer: an advisory agent that reads the work and
|
|
8
|
+
* returns prose, which feeds the next prompt. It is useful and it is *opinion*.
|
|
9
|
+
*
|
|
10
|
+
* An adversary does something a reviewer cannot: it writes a **test**, and the
|
|
11
|
+
* test either fails or it does not. Where a reviewer says "this looks like it
|
|
12
|
+
* mishandles an empty list", an adversary writes the empty-list case and runs
|
|
13
|
+
* it. One is an argument, the other is evidence.
|
|
14
|
+
*
|
|
15
|
+
* ## The line this must not cross
|
|
16
|
+
*
|
|
17
|
+
* **The gate stays the only judge.** A green run stays green even when the
|
|
18
|
+
* probe fails, and that is deliberate rather than timid: an adversary can
|
|
19
|
+
* always write a test the requirement never promised to satisfy — asserting a
|
|
20
|
+
* behaviour nobody specified — and a failing probe would then block work that
|
|
21
|
+
* is correct. Letting it decide would turn the loop into a committee, which is
|
|
22
|
+
* the same reason the reviewer is advisory.
|
|
23
|
+
*
|
|
24
|
+
* What a failing probe *is*: a recorded finding, on the run and in the report,
|
|
25
|
+
* with the test it wrote. A human decides whether it found a defect or invented
|
|
26
|
+
* a requirement.
|
|
27
|
+
*
|
|
28
|
+
* ## Why the probe is discarded
|
|
29
|
+
*
|
|
30
|
+
* The branch must contain the implementer's work and nothing else, or a reviewer
|
|
31
|
+
* cannot tell who wrote what. The probe is preserved in the finding, so nothing
|
|
32
|
+
* is lost — it just does not arrive as a commit somebody has to untangle.
|
|
33
|
+
*/
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.NO_PROBE = void 0;
|
|
36
|
+
exports.shouldProbe = shouldProbe;
|
|
37
|
+
exports.probeFinding = probeFinding;
|
|
38
|
+
exports.NO_PROBE = Object.freeze({
|
|
39
|
+
ran: false,
|
|
40
|
+
broke: false,
|
|
41
|
+
detail: "",
|
|
42
|
+
wrote: Object.freeze([]),
|
|
43
|
+
});
|
|
44
|
+
/**
|
|
45
|
+
* Should the adversary run for this attempt?
|
|
46
|
+
*
|
|
47
|
+
* Only on a green gate, and only once per requirement: probing an
|
|
48
|
+
* implementation that already failed tells you nothing you did not know, and
|
|
49
|
+
* probing every retry multiplies the cost of the one thing in the loop that is
|
|
50
|
+
* pure insurance.
|
|
51
|
+
*/
|
|
52
|
+
function shouldProbe(opts) {
|
|
53
|
+
return Boolean(opts.profile) && opts.gatePassed && !opts.alreadyProbed;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The finding a failing probe produces, as a diagnostic.
|
|
57
|
+
*
|
|
58
|
+
* Severity is a warning and never an error. The wording matters: it has to say
|
|
59
|
+
* what happened without implying the requirement is wrong, because the probe
|
|
60
|
+
* may have asserted something nobody promised.
|
|
61
|
+
*/
|
|
62
|
+
function probeFinding(requirement, outcome) {
|
|
63
|
+
return {
|
|
64
|
+
severity: "warning",
|
|
65
|
+
code: "adversarial_probe_failed",
|
|
66
|
+
message: `The gate passed for ${requirement}, and an adversarial probe then made ` +
|
|
67
|
+
`the project's tests fail. That is either a defect the scenario does not ` +
|
|
68
|
+
`cover, or a test asserting something ${requirement} never promised.`,
|
|
69
|
+
target: outcome.wrote.join(", ") || requirement,
|
|
70
|
+
fix: `Read the probe in the run record. If it found a real gap, add a ` +
|
|
71
|
+
`scenario for it; if it invented a requirement, ignore it — the gate is ` +
|
|
72
|
+
`still the judge.`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=AdversarialProbe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdversarialProbe.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/AdversarialProbe.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;;;AA4BH,kCAMC;AASD,oCAcC;AA5CY,QAAA,QAAQ,GAAiB,MAAM,CAAC,MAAM,CAAC;IAClD,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAsB;CAC9C,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,SAAgB,WAAW,CAAC,IAI3B;IACC,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;AACzE,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAAC,WAAmB,EAAE,OAAqB;IACrE,OAAO;QACL,QAAQ,EAAE,SAAkB;QAC5B,IAAI,EAAE,0BAA0B;QAChC,OAAO,EACL,uBAAuB,WAAW,uCAAuC;YACzE,0EAA0E;YAC1E,wCAAwC,WAAW,kBAAkB;QACvE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,WAAW;QAC/C,GAAG,EACD,kEAAkE;YAClE,yEAAyE;YACzE,kBAAkB;KACrB,CAAC;AACJ,CAAC"}
|
|
@@ -25,13 +25,32 @@ class AgentPrompt {
|
|
|
25
25
|
`- Production artifact: ${field("technicalArtifact", "technical_artifact") || "(none declared)"}`,
|
|
26
26
|
`- Current status: ${req.status || "(none)"}`,
|
|
27
27
|
].join("\n");
|
|
28
|
+
// Before the facts, because it is the thing being implemented and the facts
|
|
29
|
+
// are only pointers to where it goes.
|
|
30
|
+
if (opts.requirementText && String(opts.requirementText).trim()) {
|
|
31
|
+
parts.push(AgentPrompt.section("The requirement (spec.md)", String(opts.requirementText).trimEnd()));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
parts.push(AgentPrompt.section("The requirement (spec.md)", `\`spec.md\` has no \`## ${req.requirement}\` section, so this prompt cannot ` +
|
|
35
|
+
`tell you what ${req.requirement} requires.\n\n` +
|
|
36
|
+
`Do not guess. Stop and report that the requirement has no text — an ` +
|
|
37
|
+
`implementation invented from a table row is worse than no implementation, ` +
|
|
38
|
+
`because the matrix will then claim it is covered.`));
|
|
39
|
+
}
|
|
28
40
|
parts.push(AgentPrompt.section("Requirement facts", facts));
|
|
29
41
|
if (opts.hint) {
|
|
30
42
|
parts.push(AgentPrompt.section("Suggested approach", opts.hint));
|
|
31
43
|
}
|
|
32
|
-
|
|
44
|
+
// `req add` writes `-` in the Feature file column by design, and this used
|
|
45
|
+
// to render it as a filename: "The feature file `-` does not exist yet.
|
|
46
|
+
// Create it." Every requirement made the documented way hit that, and an
|
|
47
|
+
// evaluator stopped rather than pay an agent to find out what a file named
|
|
48
|
+
// `-` was supposed to be.
|
|
49
|
+
const rawFeature = String(field("featureFile", "feature_file") || "")
|
|
33
50
|
.replace(/^`|`$/g, "")
|
|
34
51
|
.trim();
|
|
52
|
+
const featureRel = rawFeature === "-" ? "" : rawFeature;
|
|
53
|
+
const featureUndeclared = rawFeature === "" || rawFeature === "-";
|
|
35
54
|
if (featureRel) {
|
|
36
55
|
if (opts.featureContent) {
|
|
37
56
|
parts.push(AgentPrompt.section(`Gherkin scenario (${featureRel})`, "```gherkin\n" + opts.featureContent.trimEnd() + "\n```"));
|
|
@@ -41,9 +60,36 @@ class AgentPrompt {
|
|
|
41
60
|
`requirement before writing code.`));
|
|
42
61
|
}
|
|
43
62
|
}
|
|
63
|
+
else if (featureUndeclared) {
|
|
64
|
+
parts.push(AgentPrompt.section("Gherkin scenario", `This requirement declares no feature file — the matrix cell is empty.\n\n` +
|
|
65
|
+
`Write the scenario first, as \`features/<area>/<behaviour>.feature\`, tagged ` +
|
|
66
|
+
`\`@${req.requirement}\` and \`@${field("scenarioId", "scenario_id") || "SCN-NNN"}\` above its \`Scenario:\` line. Then record it:\n\n` +
|
|
67
|
+
` specgate req link ${req.requirement} --feature <path>\n\n` +
|
|
68
|
+
`Creating a file that does not exist is not editing the contract — the ` +
|
|
69
|
+
`rule below is about changing scenarios that are already there.`));
|
|
70
|
+
}
|
|
44
71
|
if (opts.aiRulesContent) {
|
|
45
72
|
parts.push(AgentPrompt.section("Project rules (AI_RULES.md — non-negotiable)", opts.aiRulesContent.trimEnd()));
|
|
46
73
|
}
|
|
74
|
+
if (opts.precedent && (opts.precedent.testExcerpt || opts.precedent.technicalExcerpt)) {
|
|
75
|
+
const p = opts.precedent;
|
|
76
|
+
const body = [
|
|
77
|
+
`${p.requirementId} was accepted in this same bounded context. Match its ` +
|
|
78
|
+
`structure, naming and test style — this is what "done" looks like here.`,
|
|
79
|
+
"",
|
|
80
|
+
];
|
|
81
|
+
if (p.testExcerpt) {
|
|
82
|
+
body.push(`**Its test — \`${p.testArtifact}\`**`, "", "```", p.testExcerpt, "```", "");
|
|
83
|
+
}
|
|
84
|
+
if (p.technicalExcerpt) {
|
|
85
|
+
body.push(`**Its implementation — \`${p.technicalArtifact}\`**`, "", "```", p.technicalExcerpt, "```", "");
|
|
86
|
+
}
|
|
87
|
+
// Named a precedent, not a rule: the agent must not conclude that copying
|
|
88
|
+
// it satisfies a different requirement.
|
|
89
|
+
body.push("This is an example of *shape*, not of behaviour. Your requirement is the " +
|
|
90
|
+
"one above; do not copy its assertions.");
|
|
91
|
+
parts.push(AgentPrompt.section("Precedent — an accepted requirement nearby", body.join("\n")));
|
|
92
|
+
}
|
|
47
93
|
const baseRules = opts.stageRules || [
|
|
48
94
|
"Write the test first against the technical artifact path declared in the requirement.",
|
|
49
95
|
"Run the project test command; verify the test fails for the expected reason.",
|
|
@@ -51,8 +97,11 @@ class AgentPrompt {
|
|
|
51
97
|
];
|
|
52
98
|
const doneRules = [
|
|
53
99
|
...baseRules,
|
|
54
|
-
"**Do not modify** `spec.md`, `AI_RULES.md`, or any `features/**/*.feature` —
|
|
55
|
-
|
|
100
|
+
"**Do not modify** `spec.md`, `AI_RULES.md`, or any existing `features/**/*.feature` — " +
|
|
101
|
+
"they are the contract you are being judged against. Creating a feature file that " +
|
|
102
|
+
"does not exist yet is not modifying one, and the gate allows it: an agent asked " +
|
|
103
|
+
"to write a missing scenario is not being asked to break this rule.",
|
|
104
|
+
"The harness will run `validate . --strict` and the project test command. Both must pass.",
|
|
56
105
|
];
|
|
57
106
|
parts.push(AgentPrompt.section("Definition of done", doneRules.map((r, i) => `${i + 1}. ${r}`).join("\n")));
|
|
58
107
|
if (opts.previousFailure) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentPrompt.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/AgentPrompt.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"AgentPrompt.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/AgentPrompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,6 +34,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
34
34
|
exports.ARTIFACT_CODES = void 0;
|
|
35
35
|
exports.looksLikePath = looksLikePath;
|
|
36
36
|
exports.declaredPaths = declaredPaths;
|
|
37
|
+
exports.artifactFile = artifactFile;
|
|
37
38
|
exports.checkDeclaredArtifacts = checkDeclaredArtifacts;
|
|
38
39
|
const Diagnostic_1 = require("./Diagnostic");
|
|
39
40
|
exports.ARTIFACT_CODES = Object.freeze({
|
|
@@ -75,6 +76,30 @@ function declaredPaths(cell) {
|
|
|
75
76
|
.filter((part) => looksLikePath(part))
|
|
76
77
|
.map((part) => part.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
77
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* The file a declared artifact names, with any selector removed.
|
|
81
|
+
*
|
|
82
|
+
* A matrix cell can point *into* a file as well as at it. Two conventions turn
|
|
83
|
+
* up: an anchor (`src/auth/login.ts#L15-L89`) and a test selector
|
|
84
|
+
* (`tests/test_config.py::test_request_dispatching`, which is pytest's, and the
|
|
85
|
+
* shape Jest and Go equivalents are usually written in too).
|
|
86
|
+
*
|
|
87
|
+
* The anchor was already stripped before checking the path exists; the selector
|
|
88
|
+
* was not. So `req link --test "tests/x.py::test_y"` was accepted and then
|
|
89
|
+
* `validate` rejected the same string as `declared_artifact_missing` — two parts
|
|
90
|
+
* of the tool disagreeing about a value one of them had just written. A cold
|
|
91
|
+
* evaluator hit it while trying to do the more precise thing, and concluded a
|
|
92
|
+
* requirement can only point at a 1500-line file.
|
|
93
|
+
*
|
|
94
|
+
* The selector stays in the cell. It is information for whoever reads the row
|
|
95
|
+
* and for the command that runs the test; it is just not part of the filename.
|
|
96
|
+
*/
|
|
97
|
+
function artifactFile(cell) {
|
|
98
|
+
return String(cell || "")
|
|
99
|
+
.split("#")[0]
|
|
100
|
+
.split("::")[0]
|
|
101
|
+
.trim();
|
|
102
|
+
}
|
|
78
103
|
/**
|
|
79
104
|
* A declared path counts as touched when the diff contains it, or contains
|
|
80
105
|
* something inside it — a row may name a directory (`src/health/`) and the work
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeclaredArtifacts.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/DeclaredArtifacts.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;;AAkBH,sCAMC;AAUD,sCAOC;AA6BD,wDAmCC;
|
|
1
|
+
{"version":3,"file":"DeclaredArtifacts.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/DeclaredArtifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What `done --check` has to prove before it flips a row (Fase 1.1).
|
|
4
|
+
*
|
|
5
|
+
* ## What it was
|
|
6
|
+
*
|
|
7
|
+
* `--check` and `--strict` were parsed into `DoneOptions` and then never read.
|
|
8
|
+
* `done REQ-001 --check` was a no-op that printed a tick — measured on a matrix
|
|
9
|
+
* pointing at files that do not exist, where `validate --strict-links` exits 1:
|
|
10
|
+
*
|
|
11
|
+
* ✔ REQ-001 → Implemented (1 row updated) exit=0
|
|
12
|
+
*
|
|
13
|
+
* Four documentation pages say `--check` "validates first". It validated
|
|
14
|
+
* nothing. That is the shape this repository keeps finding in itself: something
|
|
15
|
+
* that claims more than it does.
|
|
16
|
+
*
|
|
17
|
+
* ## Why the test command matters here specifically
|
|
18
|
+
*
|
|
19
|
+
* A cold evaluator's summary of the product was "nothing ever runs a test", and
|
|
20
|
+
* they were right: only the harness executes a test command, so a team on the
|
|
21
|
+
* documented path never runs one. `validate` is a static checker — it reads
|
|
22
|
+
* markdown and stats files. Marking a requirement Implemented on the strength
|
|
23
|
+
* of a static check is how "specs as executable contracts" becomes a folder of
|
|
24
|
+
* markdown and a badge.
|
|
25
|
+
*
|
|
26
|
+
* ## The rule about not knowing
|
|
27
|
+
*
|
|
28
|
+
* A project with no test command configured is not a project that passed. It is
|
|
29
|
+
* a project nothing ran, and the two have to look different — otherwise the
|
|
30
|
+
* silent case is the flattering one, which is the bias this whole tool exists to
|
|
31
|
+
* remove.
|
|
32
|
+
*/
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.NO_TEST_COMMAND_WARNING = void 0;
|
|
35
|
+
exports.planDoneVerification = planDoneVerification;
|
|
36
|
+
exports.planGateCheck = planGateCheck;
|
|
37
|
+
/**
|
|
38
|
+
* The checks `done` should run, in the order they should run.
|
|
39
|
+
*
|
|
40
|
+
* `validate` comes first because it is fast and its failures are the ones with
|
|
41
|
+
* a fix line attached; running a whole test suite to then reject the row for a
|
|
42
|
+
* missing matrix header wastes the slowest thing in the loop.
|
|
43
|
+
*/
|
|
44
|
+
function planDoneVerification(projectDir, opts) {
|
|
45
|
+
if (!opts.check && !opts.strict)
|
|
46
|
+
return { steps: [], testsUnverified: false };
|
|
47
|
+
const validateArgs = [projectDir];
|
|
48
|
+
if (opts.strict) {
|
|
49
|
+
// `--strict` means "the gate this project can actually give me". Anything
|
|
50
|
+
// weaker recreates the defect a cold evaluator named: following the
|
|
51
|
+
// documentation leaves you with a weaker gate than the tool supports.
|
|
52
|
+
// The whole gate, not a subset: a subset let a scenario of unfilled
|
|
53
|
+
// `<placeholder>` steps close as Implemented (--strict-scenarios was not
|
|
54
|
+
// in it), and "one gate, one name" is the rule since #174.
|
|
55
|
+
validateArgs.push("--strict");
|
|
56
|
+
}
|
|
57
|
+
if (opts.reqId)
|
|
58
|
+
validateArgs.push("--delivering", opts.reqId);
|
|
59
|
+
const steps = [{ stage: "validate", argv: validateArgs }];
|
|
60
|
+
const testCmd = (opts.testCmd || "").trim();
|
|
61
|
+
if (testCmd !== "")
|
|
62
|
+
steps.push({ stage: "tests", argv: [testCmd] });
|
|
63
|
+
return { steps, testsUnverified: testCmd === "" };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The checks `specgate check` runs: the gate, then the suite.
|
|
67
|
+
*
|
|
68
|
+
* `check` is the one command a team needs in CI and before a PR. It is
|
|
69
|
+
* `validate --strict` — not a subset, because a subset is how ten pages ended
|
|
70
|
+
* up recommending a gate that passed a requirement whose test file was gone —
|
|
71
|
+
* followed by the project's tests when a command is configured.
|
|
72
|
+
*/
|
|
73
|
+
function planGateCheck(projectDir, testCmd) {
|
|
74
|
+
const steps = [{ stage: "validate", argv: [projectDir, "--strict"] }];
|
|
75
|
+
const cmd = (testCmd || "").trim();
|
|
76
|
+
if (cmd !== "")
|
|
77
|
+
steps.push({ stage: "tests", argv: [cmd] });
|
|
78
|
+
return { steps, testsUnverified: cmd === "" };
|
|
79
|
+
}
|
|
80
|
+
/** The line `done` prints when nothing ran the project's tests. */
|
|
81
|
+
exports.NO_TEST_COMMAND_WARNING = Object.freeze({
|
|
82
|
+
message: "No test command configured — this checked the specification, not the code.",
|
|
83
|
+
fix: [
|
|
84
|
+
'Pass --test-cmd "<command>", or set test_cmd: in harness.config.yaml so',
|
|
85
|
+
"every `done --check` runs it. A requirement marked Implemented on a static",
|
|
86
|
+
"check alone is a claim nothing executed.",
|
|
87
|
+
],
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=DoneVerification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DoneVerification.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/DoneVerification.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;;AAyCH,oDAwBC;AAUD,sCAKC;AA9CD;;;;;;GAMG;AACH,SAAgB,oBAAoB,CAClC,UAAkB,EAClB,IAAsB;IAEtB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;IAE9E,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,CAAC;IAClC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,0EAA0E;QAC1E,oEAAoE;QACpE,sEAAsE;QACtE,oEAAoE;QACpE,yEAAyE;QACzE,2DAA2D;QAC3D,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,IAAI,CAAC,KAAK;QAAE,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAE9D,MAAM,KAAK,GAAuB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;IAE9E,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,OAAO,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAEpE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,KAAK,EAAE,EAAE,CAAC;AACpD,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,aAAa,CAAC,UAAkB,EAAE,OAAgB;IAChE,MAAM,KAAK,GAAuB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;IAC1F,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,GAAG,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5D,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,KAAK,EAAE,EAAE,CAAC;AAChD,CAAC;AAED,mEAAmE;AACtD,QAAA,uBAAuB,GAAG,MAAM,CAAC,MAAM,CAAC;IACnD,OAAO,EAAE,4EAA4E;IACrF,GAAG,EAAE;QACH,yEAAyE;QACzE,4EAA4E;QAC5E,0CAA0C;KAC3C;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The gate must mean the same thing after the attempt as before it (#167).
|
|
4
|
+
*
|
|
5
|
+
* `WriteScope` protects the contract: spec.md, AI_RULES.md, features/**,
|
|
6
|
+
* docs/specs/**. It does not protect the file that defines the command the gate
|
|
7
|
+
* *runs*, and that turns out to be the same hole one level up. Measured, with a
|
|
8
|
+
* stub agent that writes no implementation at all:
|
|
9
|
+
*
|
|
10
|
+
* "scripts": { "test": "node --test tests/*.test.js" } → "echo 'all good'"
|
|
11
|
+
*
|
|
12
|
+
* over a suite that was red before it ran. The harness reported
|
|
13
|
+
* `✅ REQ-001 pass (1 attempt)`. An agent that cannot pass the test can weaken
|
|
14
|
+
* the test.
|
|
15
|
+
*
|
|
16
|
+
* ## Why this is not "protect package.json"
|
|
17
|
+
*
|
|
18
|
+
* Adding a dependency during implementation is legitimate and common, and a
|
|
19
|
+
* guard that blocks it would be turned off within a day — at which point it
|
|
20
|
+
* protects nothing. So this does not watch the file. It resolves which *script*
|
|
21
|
+
* the gate command actually invokes and watches only that one value.
|
|
22
|
+
*
|
|
23
|
+
* ## Why it declares what it cannot see
|
|
24
|
+
*
|
|
25
|
+
* `npm test` and `make check` name a script this can find. `mvn -B test` and
|
|
26
|
+
* `pytest` do not — their behaviour lives in a plugin graph or a config file
|
|
27
|
+
* this would have to interpret, and a guard that guesses is worse than one that
|
|
28
|
+
* says it did not look. `resolveGateScript` returns `null` there, and the
|
|
29
|
+
* caller reports the check as not applicable rather than as passed.
|
|
30
|
+
*/
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.resolveGateScript = resolveGateScript;
|
|
33
|
+
exports.npmScriptValue = npmScriptValue;
|
|
34
|
+
exports.makeTargetRecipe = makeTargetRecipe;
|
|
35
|
+
exports.gateCommandIntegrity = gateCommandIntegrity;
|
|
36
|
+
const NPM_RUNNERS = ["npm", "yarn", "pnpm", "bun"];
|
|
37
|
+
/**
|
|
38
|
+
* Which script definition, if any, a gate command depends on.
|
|
39
|
+
*
|
|
40
|
+
* Returns `null` when the command's meaning does not live in a file this can
|
|
41
|
+
* read — which is a real answer, not a failure.
|
|
42
|
+
*/
|
|
43
|
+
function resolveGateScript(testCmd) {
|
|
44
|
+
const tokens = String(testCmd || "")
|
|
45
|
+
.trim()
|
|
46
|
+
.split(/\s+/)
|
|
47
|
+
.filter(Boolean);
|
|
48
|
+
if (tokens.length === 0)
|
|
49
|
+
return null;
|
|
50
|
+
const [runner, ...rest] = tokens;
|
|
51
|
+
if (NPM_RUNNERS.includes(runner)) {
|
|
52
|
+
// `npm test`, `npm run verify`, `yarn test`, `pnpm run check`.
|
|
53
|
+
const args = rest.filter((a) => !a.startsWith("-"));
|
|
54
|
+
if (args.length === 0)
|
|
55
|
+
return null;
|
|
56
|
+
if (args[0] === "run" || args[0] === "run-script") {
|
|
57
|
+
return args[1] ? { manifest: "package.json", script: args[1] } : null;
|
|
58
|
+
}
|
|
59
|
+
if (args[0] === "test" || args[0] === "t")
|
|
60
|
+
return { manifest: "package.json", script: "test" };
|
|
61
|
+
// `npm start`, `npm ci` and friends are not gates; anything else is a
|
|
62
|
+
// script name only if package.json says so, which the caller resolves.
|
|
63
|
+
return { manifest: "package.json", script: args[0] };
|
|
64
|
+
}
|
|
65
|
+
if (runner === "make") {
|
|
66
|
+
const target = rest.find((a) => !a.startsWith("-"));
|
|
67
|
+
return { manifest: "Makefile", script: target || "all" };
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
/** The value of an npm script, or `null` when the manifest has no such script. */
|
|
72
|
+
function npmScriptValue(manifestSource, script) {
|
|
73
|
+
let parsed;
|
|
74
|
+
try {
|
|
75
|
+
parsed = JSON.parse(manifestSource);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const scripts = parsed && parsed.scripts;
|
|
81
|
+
if (!scripts || typeof scripts !== "object")
|
|
82
|
+
return null;
|
|
83
|
+
const value = scripts[script];
|
|
84
|
+
return typeof value === "string" ? value : null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The recipe lines of one Make target.
|
|
88
|
+
*
|
|
89
|
+
* Deliberately literal: a target's body is every indented line under it, up to
|
|
90
|
+
* the next rule. Reproducing Make's own parser would be a bigger promise than
|
|
91
|
+
* this needs to keep.
|
|
92
|
+
*/
|
|
93
|
+
function makeTargetRecipe(manifestSource, target) {
|
|
94
|
+
const lines = String(manifestSource).replace(/\r\n/g, "\n").split("\n");
|
|
95
|
+
const head = new RegExp(`^${target.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*:`);
|
|
96
|
+
const body = [];
|
|
97
|
+
let inside = false;
|
|
98
|
+
for (const line of lines) {
|
|
99
|
+
if (head.test(line)) {
|
|
100
|
+
inside = true;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (!inside)
|
|
104
|
+
continue;
|
|
105
|
+
if (line.trim() === "")
|
|
106
|
+
continue;
|
|
107
|
+
if (!/^\s/.test(line))
|
|
108
|
+
break;
|
|
109
|
+
body.push(line.trim());
|
|
110
|
+
}
|
|
111
|
+
return inside ? body.join("\n") : null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Did the definition the gate command depends on change during the attempt?
|
|
115
|
+
*
|
|
116
|
+
* A script that did not exist before and does not exist after is unchanged. A
|
|
117
|
+
* script that *appears* is a change: inventing the target the gate names is the
|
|
118
|
+
* same move as rewriting it.
|
|
119
|
+
*/
|
|
120
|
+
function gateCommandIntegrity(testCmd, manifestBefore, manifestAfter) {
|
|
121
|
+
const script = resolveGateScript(testCmd);
|
|
122
|
+
if (!script)
|
|
123
|
+
return { checked: false, changed: false };
|
|
124
|
+
const read = (source) => {
|
|
125
|
+
if (source === null)
|
|
126
|
+
return null;
|
|
127
|
+
return script.manifest === "Makefile"
|
|
128
|
+
? makeTargetRecipe(source, script.script)
|
|
129
|
+
: npmScriptValue(source, script.script);
|
|
130
|
+
};
|
|
131
|
+
const before = read(manifestBefore);
|
|
132
|
+
const after = read(manifestAfter);
|
|
133
|
+
// The manifest carries no such script either side: nothing here defines the
|
|
134
|
+
// gate, so there is nothing to protect and saying "passed" would overstate it.
|
|
135
|
+
if (before === null && after === null)
|
|
136
|
+
return { checked: false, changed: false, script };
|
|
137
|
+
return { checked: true, changed: before !== after, script, before, after };
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=GateCommandIntegrity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GateCommandIntegrity.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/GateCommandIntegrity.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,8 +30,9 @@
|
|
|
30
30
|
*
|
|
31
31
|
* ## Severity is not a matter of taste
|
|
32
32
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
33
|
+
* Three rules are errors and can never be demoted to style: `scenario_has_no_steps`,
|
|
34
|
+
* `keyword_case_invalid` and `scenario_placeholder_step` — a template nobody
|
|
35
|
+
* filled in describes no behaviour. Cucumber reports an empty scenario as
|
|
35
36
|
* `1 scenario (1 passed) · 0 steps · exit 0` — a test that proves nothing and
|
|
36
37
|
* says it passed. 27 shipped scenarios were in that state while `--strict`
|
|
37
38
|
* called them fine (H14). The rest are warnings: a two-step scenario is weak,
|
|
@@ -62,7 +63,18 @@ exports.QUALITY_CODES = Object.freeze({
|
|
|
62
63
|
OUTLINE_WITHOUT_EXAMPLES: "scenario_outline_without_examples",
|
|
63
64
|
VAGUE_STEP: "vague_step",
|
|
64
65
|
KEYWORD_CASE: "keyword_case_invalid",
|
|
66
|
+
PLACEHOLDER_STEP: "scenario_placeholder_step",
|
|
65
67
|
});
|
|
68
|
+
/**
|
|
69
|
+
* An unfilled `<placeholder>` in a plain Scenario.
|
|
70
|
+
*
|
|
71
|
+
* In an Outline, `<x>` is a parameter the Examples table fills. In a plain
|
|
72
|
+
* Scenario nothing fills it: `Given <the starting state>` is a template a
|
|
73
|
+
* person was meant to rewrite. Measured 2026-10-06: a scenario made of three
|
|
74
|
+
* such steps passed `validate --strict` and `done --strict` with its
|
|
75
|
+
* requirement Implemented — three steps, a real title, no vague word.
|
|
76
|
+
*/
|
|
77
|
+
const PLACEHOLDER_RE = /<[^<>]+>/;
|
|
66
78
|
/**
|
|
67
79
|
* A title that names nothing: `Test`, `Scenario 1`, or fewer than three words.
|
|
68
80
|
*
|
|
@@ -76,7 +88,7 @@ function isGenericTitle(title) {
|
|
|
76
88
|
return title.split(/\s+/).filter(Boolean).length < 3;
|
|
77
89
|
}
|
|
78
90
|
/**
|
|
79
|
-
* The
|
|
91
|
+
* The nine rules, applied to one scenario.
|
|
80
92
|
*
|
|
81
93
|
* `target` is what the caller wants the reader to look at — a pack scenario id,
|
|
82
94
|
* a file path, whatever locates it. The domain does not invent it because the
|
|
@@ -113,6 +125,10 @@ function analyseScenario(scenario, target, file) {
|
|
|
113
125
|
found.push((0, Diagnostic_1.error)(exports.QUALITY_CODES.OUTLINE_WITHOUT_EXAMPLES, "Scenario Outline has no Examples table.", at({ fix: "Add an `Examples:` table, or make it a plain `Scenario`." })));
|
|
114
126
|
}
|
|
115
127
|
for (const step of scenario.steps) {
|
|
128
|
+
if (!scenario.outline && PLACEHOLDER_RE.test(step.text)) {
|
|
129
|
+
found.push((0, Diagnostic_1.error)(exports.QUALITY_CODES.PLACEHOLDER_STEP, `unfilled placeholder in "${step.keyword} ${step.text}" — nothing fills it outside an Outline.`, at({ fix: "Replace the <placeholder> with the concrete state, action or outcome." })));
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
116
132
|
if (VAGUE_STEP_RE.test(step.text)) {
|
|
117
133
|
found.push((0, Diagnostic_1.warning)(exports.QUALITY_CODES.VAGUE_STEP, `vague step "${step.keyword} ${step.text}" — make it concrete and falsifiable.`, at({ fix: "State a checkable fact: a value, a state, an emitted event." })));
|
|
118
134
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GherkinQuality.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/GherkinQuality.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"GherkinQuality.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/GherkinQuality.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,8 @@ class HarnessConfig {
|
|
|
15
15
|
prCmd: "",
|
|
16
16
|
attemptProfiles: [],
|
|
17
17
|
reviewProfile: "",
|
|
18
|
+
adversaryProfile: "",
|
|
19
|
+
promptPrecedents: false,
|
|
18
20
|
profileAgents: {},
|
|
19
21
|
protectedPaths: [],
|
|
20
22
|
allowPaths: [],
|
|
@@ -42,6 +44,10 @@ class HarnessConfig {
|
|
|
42
44
|
prCmd: cliArgs.prCmd || file.prCmd || HarnessConfig.DEFAULT_SETTINGS.prCmd,
|
|
43
45
|
attemptProfiles: file.attemptProfiles || HarnessConfig.DEFAULT_SETTINGS.attemptProfiles,
|
|
44
46
|
reviewProfile: file.reviewProfile || HarnessConfig.DEFAULT_SETTINGS.reviewProfile,
|
|
47
|
+
adversaryProfile: "",
|
|
48
|
+
promptPrecedents: file.promptPrecedents === undefined
|
|
49
|
+
? HarnessConfig.DEFAULT_SETTINGS.promptPrecedents
|
|
50
|
+
: file.promptPrecedents === true,
|
|
45
51
|
profileAgents: file.profileAgents || HarnessConfig.DEFAULT_SETTINGS.profileAgents,
|
|
46
52
|
// Write scope is a repository decision, like the role ladder: it comes
|
|
47
53
|
// from the file only. A flag that relaxes what the agent may edit is a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HarnessConfig.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/HarnessConfig.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"HarnessConfig.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/HarnessConfig.ts"],"names":[],"mappings":"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"}
|