@bluewombat/slots 0.9.0 → 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/README.md +177 -64
- package/agents/agent-plugins.mjs +52 -14
- package/agents/claude.mjs +3 -3
- package/agents/cursor.mjs +1 -1
- package/builders/e2e.mjs +124 -0
- package/builders/producer.mjs +4 -0
- package/builders/repair.mjs +4 -0
- package/builders/tests.mjs +139 -0
- package/feature/fix.mjs +134 -0
- package/feature/validate.mjs +205 -0
- package/gates/ci-green.mjs +17 -6
- package/gates/e2e.mjs +538 -0
- package/gates/gitignore-leak.mjs +2 -1
- package/gates/project-checks.mjs +128 -0
- package/gates/tests-frozen.mjs +96 -0
- package/gates/tests-red.mjs +227 -0
- package/gates/workspace-changed.mjs +2 -1
- package/gates/workspace-unchanged.mjs +90 -0
- package/lib/junit.mjs +122 -0
- package/lib/output-tail.mjs +70 -0
- package/package.json +7 -5
- package/refreshers/git.mjs +35 -1
- package/{assembly → ticket}/fix.mjs +2 -2
- package/{assembly → ticket}/validate.mjs +5 -7
package/refreshers/git.mjs
CHANGED
|
@@ -23,6 +23,12 @@ import {
|
|
|
23
23
|
// fast-forward has been written to by somebody else, and that is a person's
|
|
24
24
|
// problem, not a merge to attempt.
|
|
25
25
|
//
|
|
26
|
+
// A Feature's line cut from the final branch that has no commit of its own is
|
|
27
|
+
// only a stale copy of it: when `--base` names that branch and the line is an
|
|
28
|
+
// ancestor of it, the line is fast-forwarded to it, here and on the remote, so
|
|
29
|
+
// a Ticket starts from the code as it now is. A line with commits of its own
|
|
30
|
+
// is left alone.
|
|
31
|
+
//
|
|
26
32
|
// The remote is `origin`, like the git Publisher's. Takes no option.
|
|
27
33
|
|
|
28
34
|
const cwd = process.cwd();
|
|
@@ -53,6 +59,34 @@ if (fetched.status !== 0) {
|
|
|
53
59
|
process.exit(0);
|
|
54
60
|
}
|
|
55
61
|
|
|
62
|
+
const base = take(process.argv, "--base");
|
|
63
|
+
let goal = `origin/${target}`;
|
|
64
|
+
if (base !== undefined && base.trim().length > 0 && base !== target) {
|
|
65
|
+
const fetchedBase = git(["fetch", "origin", `+refs/heads/${base}:refs/remotes/origin/${base}`]);
|
|
66
|
+
if (fetchedBase.status !== 0) {
|
|
67
|
+
emitRefreshRefusal(
|
|
68
|
+
`Cannot fetch origin/${base} from ${cwd}: ${fetchedBase.stderr.trim().slice(-500)}`,
|
|
69
|
+
);
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
const behindBase =
|
|
73
|
+
git(["merge-base", "--is-ancestor", `origin/${target}`, `origin/${base}`]).status === 0;
|
|
74
|
+
if (
|
|
75
|
+
behindBase &&
|
|
76
|
+
git(["rev-parse", `origin/${target}`]).stdout !== git(["rev-parse", `origin/${base}`]).stdout
|
|
77
|
+
) {
|
|
78
|
+
// A plain push: never forced, so it only ever adds history.
|
|
79
|
+
const pushed = git(["push", "origin", `refs/remotes/origin/${base}:refs/heads/${target}`]);
|
|
80
|
+
if (pushed.status !== 0) {
|
|
81
|
+
emitRefreshRefusal(
|
|
82
|
+
`Cannot move origin/${target} up to origin/${base}: ${pushed.stderr.trim().slice(-500)}`,
|
|
83
|
+
);
|
|
84
|
+
process.exit(0);
|
|
85
|
+
}
|
|
86
|
+
goal = `origin/${base}`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
56
90
|
const current = git(["symbolic-ref", "--short", "HEAD"]);
|
|
57
91
|
if (current.status !== 0 || current.stdout.trim() !== target) {
|
|
58
92
|
const exists = git(["rev-parse", "--verify", "--quiet", `refs/heads/${target}`]).status === 0;
|
|
@@ -65,7 +99,7 @@ if (current.status !== 0 || current.stdout.trim() !== target) {
|
|
|
65
99
|
}
|
|
66
100
|
}
|
|
67
101
|
|
|
68
|
-
const merged = git(["merge", "--ff-only",
|
|
102
|
+
const merged = git(["merge", "--ff-only", goal]);
|
|
69
103
|
if (merged.status !== 0) {
|
|
70
104
|
// The one way a copy stops fast-forwarding is a commit made into it that
|
|
71
105
|
// the reference does not have. The copy is the system's, not a person's:
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "@bluewombat/slot-kit";
|
|
16
16
|
import { attemptOf } from "../lib/fill.mjs";
|
|
17
17
|
|
|
18
|
-
const NAME = "
|
|
18
|
+
const NAME = "ticket fix";
|
|
19
19
|
|
|
20
20
|
const DEFAULT_TEMPLATE = `You are a coding agent working unattended in a checkout of the project.
|
|
21
21
|
|
|
@@ -60,7 +60,7 @@ A person reads that line and decides. It is a correct answer, not a failure.
|
|
|
60
60
|
|
|
61
61
|
const report = (take(process.argv, "--report") ?? "").trim();
|
|
62
62
|
if (report.length === 0) {
|
|
63
|
-
emitFailure("fail-blocking", "The
|
|
63
|
+
emitFailure("fail-blocking", "The ticket fix command needs --report.");
|
|
64
64
|
process.exit(1);
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "@bluewombat/slot-kit";
|
|
16
16
|
import { attemptOf } from "../lib/fill.mjs";
|
|
17
17
|
|
|
18
|
-
const NAME = "
|
|
18
|
+
const NAME = "ticket validate";
|
|
19
19
|
|
|
20
20
|
const DEFAULT_TEMPLATE = `You are a coding agent working unattended in a checkout of the project.
|
|
21
21
|
|
|
@@ -67,7 +67,7 @@ const report = (take(process.argv, "--report") ?? "").trim();
|
|
|
67
67
|
if (report.length > 0) {
|
|
68
68
|
emitFailure(
|
|
69
69
|
"fail-blocking",
|
|
70
|
-
"
|
|
70
|
+
"ticket.validate is a read-only review; it does not take --report — that is ticket.fix's job.",
|
|
71
71
|
);
|
|
72
72
|
process.exit(1);
|
|
73
73
|
}
|
|
@@ -149,7 +149,7 @@ function answer(run, bin, name) {
|
|
|
149
149
|
// next round gets the same prompt again.
|
|
150
150
|
emitFailure(
|
|
151
151
|
"fail-retryable",
|
|
152
|
-
`
|
|
152
|
+
`ticket.validate found no MASON_VERDICT: line in the answer: ${
|
|
153
153
|
said.length > 0 ? said.slice(0, 500) : "(no answer)"
|
|
154
154
|
}`,
|
|
155
155
|
);
|
|
@@ -160,9 +160,7 @@ function answer(run, bin, name) {
|
|
|
160
160
|
const why = verdict.slice(refused[0].length).trim();
|
|
161
161
|
emitFailure(
|
|
162
162
|
"fail-retryable",
|
|
163
|
-
why.length > 0
|
|
164
|
-
? why
|
|
165
|
-
: "assembly.validate refused the assembled ticket, with no reason given.",
|
|
163
|
+
why.length > 0 ? why : "ticket.validate refused the assembled ticket, with no reason given.",
|
|
166
164
|
);
|
|
167
165
|
process.exit(1);
|
|
168
166
|
}
|
|
@@ -171,7 +169,7 @@ function answer(run, bin, name) {
|
|
|
171
169
|
}
|
|
172
170
|
emitFailure(
|
|
173
171
|
"fail-retryable",
|
|
174
|
-
`
|
|
172
|
+
`ticket.validate's MASON_VERDICT: line was neither VALIDATED nor REFUSED: ${verdict.slice(0, 500)}`,
|
|
175
173
|
);
|
|
176
174
|
process.exit(1);
|
|
177
175
|
}
|