feat(lanes): add ship-feature pipeline template (E1)

This commit is contained in:
2026-08-04 17:56:38 +07:00
parent 31f984c750
commit e600df236e
2 changed files with 61 additions and 4 deletions
+39 -4
View File
@@ -334,7 +334,7 @@ test.describe("rule precision against real command shapes", () => {
tool_name: "Bash",
tool_input: {
command:
'GIT_TERMINAL_PROMPT=0 git -c credential.helper=x push --force-with-lease origin main',
"GIT_TERMINAL_PROMPT=0 git -c credential.helper=x push --force-with-lease origin main",
},
});
assert.equal(r.nodeId, "ship");
@@ -354,8 +354,8 @@ test.describe("ship detection against this repo's actual push command", () => {
// `|`-free shell between `git` and `push`, so a same-segment pattern like
// `git[^;&|]*push` never matches it. Six real pushes produced no signal.
const REAL_PUSH =
'cd /repo && git add -A && git commit -q --amend --no-edit && ' +
'GIT_TERMINAL_PROMPT=0 git -c credential.helper=\'!f() { echo username=token; echo "password=$TK"; }; f\' push --force-with-lease origin main';
"cd /repo && git add -A && git commit -q --amend --no-edit && " +
"GIT_TERMINAL_PROMPT=0 git -c credential.helper='!f() { echo username=token; echo \"password=$TK\"; }; f' push --force-with-lease origin main";
test.it("detects ship from the real push command", () => {
const r = detect(pipeline, { tool_name: "Bash", tool_input: { command: REAL_PUSH } });
@@ -404,7 +404,7 @@ test.describe("ship must match a git push INVOCATION, not the word push", () =>
const cases = [
"git push origin main",
"git push --force-with-lease",
'GIT_TERMINAL_PROMPT=0 git -c credential.helper=\'!f() { echo x; }; f\' push --force-with-lease origin main',
"GIT_TERMINAL_PROMPT=0 git -c credential.helper='!f() { echo x; }; f' push --force-with-lease origin main",
"cd /repo && git -c core.hooksPath=/dev/null push origin main",
];
for (const command of cases) {
@@ -448,3 +448,38 @@ test.describe("tests rule covers the runners this repo actually uses", () => {
}
});
});
test.describe("ship-feature pipeline template", () => {
test.it("loads without throwing and has one node per skill stage", () => {
const { reload } = require("../lib/pipelines");
reload();
const pipeline = getPipeline("ship-feature");
const ids = pipeline.nodes.map((n) => n.id);
assert.deepEqual(ids, [
"intake",
"plan",
"implementing",
"gates",
"e2e-feature",
"e2e-feature-passed",
"review",
"qc-plan",
"qc",
"gate",
"publishing",
"pr-open",
"reported",
"watching-pr",
"merged",
"done",
]);
});
test.it("every node id is unique", () => {
const { reload } = require("../lib/pipelines");
reload();
const pipeline = getPipeline("ship-feature");
const ids = pipeline.nodes.map((n) => n.id);
assert.deepEqual(ids, [...new Set(ids)]);
});
});
+22
View File
@@ -0,0 +1,22 @@
{
"id": "ship-feature",
"name": "Ship feature (lane pipeline)",
"nodes": [
{ "id": "intake", "label": "intake", "icon": "📝", "gate": false, "aliases": [] },
{ "id": "plan", "label": "plan", "icon": "🧭", "gate": false, "aliases": [] },
{ "id": "implementing", "label": "implement (TDD)", "icon": "🛠", "gate": false, "aliases": [] },
{ "id": "gates", "label": "CI gates + preflight", "icon": "🧪", "gate": true, "aliases": [] },
{ "id": "e2e-feature", "label": "e2e on feature branch", "icon": "🧪", "gate": false, "aliases": [] },
{ "id": "e2e-feature-passed", "label": "e2e passed", "icon": "🧪", "gate": true, "aliases": [] },
{ "id": "review", "label": "code review", "icon": "👀", "gate": true, "aliases": [] },
{ "id": "qc-plan", "label": "QC plan", "icon": "📋", "gate": false, "aliases": [] },
{ "id": "qc", "label": "browser QC", "icon": "🔍", "gate": true, "aliases": [] },
{ "id": "gate", "label": "senior GO/NO-GO gate", "icon": "🚦", "gate": true, "aliases": [] },
{ "id": "publishing", "label": "publish PR", "icon": "🔀", "gate": false, "aliases": [] },
{ "id": "pr-open", "label": "PR open", "icon": "🔀", "gate": false, "aliases": ["ship"] },
{ "id": "reported", "label": "reported", "icon": "📣", "gate": false, "aliases": [] },
{ "id": "watching-pr", "label": "watching PR", "icon": "👁", "gate": false, "aliases": [] },
{ "id": "merged", "label": "merged — post-verify", "icon": "🔗", "gate": false, "aliases": [] },
{ "id": "done", "label": "done", "icon": "✅", "gate": false, "aliases": ["complete", "completed"] }
]
}