@voidlabs.gg/voidshift-agents 0.0.0-stage → 0.4.1
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/LICENSE +202 -0
- package/README.md +136 -2
- package/dist/config.d.ts +60 -0
- package/dist/config.js +98 -0
- package/dist/control.d.ts +25 -0
- package/dist/control.js +711 -0
- package/dist/engine.d.ts +22 -0
- package/dist/engine.js +95 -0
- package/dist/git.d.ts +30 -0
- package/dist/git.js +136 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1171 -0
- package/dist/keychain.d.ts +3 -0
- package/dist/keychain.js +19 -0
- package/dist/launchd.d.ts +7 -0
- package/dist/launchd.js +68 -0
- package/dist/linear.d.ts +33 -0
- package/dist/linear.js +122 -0
- package/dist/manage.d.ts +18 -0
- package/dist/manage.js +120 -0
- package/dist/memory.d.ts +2 -0
- package/dist/memory.js +37 -0
- package/dist/names.d.ts +8 -0
- package/dist/names.js +26 -0
- package/dist/repos.d.ts +1 -0
- package/dist/repos.js +45 -0
- package/dist/runner.d.ts +23 -0
- package/dist/runner.js +432 -0
- package/dist/state.d.ts +63 -0
- package/dist/state.js +107 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.js +3 -0
- package/dist/workflow.d.ts +52 -0
- package/dist/workflow.js +111 -0
- package/pack/vs-dev/SKILL.md +51 -0
- package/pack/vs-plan/SKILL.md +140 -0
- package/pack/vs-plan-review/SKILL.md +63 -0
- package/pack/vs-publish/SKILL.md +45 -0
- package/pack/vs-qa/SKILL.md +72 -0
- package/package.json +50 -4
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export declare const PLAN_HEADING = "## Plan";
|
|
2
|
+
export declare const LABELS: {
|
|
3
|
+
stage: Record<string, string>;
|
|
4
|
+
changes: string;
|
|
5
|
+
verified: string;
|
|
6
|
+
parked: string;
|
|
7
|
+
version: (round: number) => string;
|
|
8
|
+
working: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const isVersionLabel: (name: string) => boolean;
|
|
11
|
+
export declare const isRoundLabel: (name: string) => boolean;
|
|
12
|
+
export declare const isStatusLabel: (name: string) => boolean;
|
|
13
|
+
export declare function stageLabels(current: string[], trigger: string, stage: string, round?: number): string[];
|
|
14
|
+
export type Verdict = 'SHIP' | 'FIX' | 'SKIP';
|
|
15
|
+
export interface StepResult {
|
|
16
|
+
step: string;
|
|
17
|
+
verdict: Verdict;
|
|
18
|
+
report: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function parseVerdict(output: string): Verdict;
|
|
21
|
+
export type DevResult = {
|
|
22
|
+
status: 'done';
|
|
23
|
+
} | {
|
|
24
|
+
status: 'blocked';
|
|
25
|
+
reason: string;
|
|
26
|
+
};
|
|
27
|
+
export declare function parseDevResult(output: string): DevResult;
|
|
28
|
+
export declare function qaPassed(results: StepResult[]): boolean;
|
|
29
|
+
export declare function findingsFor(results: StepResult[]): string;
|
|
30
|
+
export declare function latestPlan(comments: {
|
|
31
|
+
body: string;
|
|
32
|
+
createdAt: string;
|
|
33
|
+
}[]): string | null;
|
|
34
|
+
export declare function skillBody(markdown: string): string;
|
|
35
|
+
export interface PromptInput {
|
|
36
|
+
skill: string;
|
|
37
|
+
card: {
|
|
38
|
+
identifier: string;
|
|
39
|
+
title: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
url?: string;
|
|
42
|
+
};
|
|
43
|
+
plan: string;
|
|
44
|
+
base: string;
|
|
45
|
+
round: number;
|
|
46
|
+
findings?: string;
|
|
47
|
+
extra?: string;
|
|
48
|
+
}
|
|
49
|
+
export declare function buildPrompt(p: PromptInput): string;
|
|
50
|
+
export declare function verdictBlock<T extends string>(steps: T[], i: number, isVerdict: (s: T) => boolean): [number, number];
|
|
51
|
+
export declare function fixTarget<T extends string>(steps: T[], blockStart: number, isProducer: (s: T) => boolean): number;
|
|
52
|
+
export declare function planBody(output: string): string;
|
package/dist/workflow.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// The build workflow and the pure decisions around it. The runner does the I/O;
|
|
2
|
+
// everything here is testable without Linear, git or an agent.
|
|
3
|
+
export const PLAN_HEADING = '## Plan';
|
|
4
|
+
// Plans posted before 0.1.5 used this heading; still read them.
|
|
5
|
+
const OLD_PLAN_HEADING = '## VoidShift plan';
|
|
6
|
+
// A card carries at most two VoidShift labels: one stage label (which agent has
|
|
7
|
+
// it, or how it ended) and one version label (which round it is on).
|
|
8
|
+
export const LABELS = {
|
|
9
|
+
stage: {
|
|
10
|
+
'vs-plan': 'vs-planning',
|
|
11
|
+
'vs-plan-review': 'vs-plan-review',
|
|
12
|
+
'vs-publish': 'vs-publish',
|
|
13
|
+
'vs-dev': 'vs-dev',
|
|
14
|
+
'vs-qa': 'vs-qa',
|
|
15
|
+
},
|
|
16
|
+
changes: 'vs-changes-requested',
|
|
17
|
+
verified: 'vs-qa-verified',
|
|
18
|
+
parked: 'vs-parked',
|
|
19
|
+
version: (round) => `vs-v${round}`,
|
|
20
|
+
// Labels from earlier runners, still cleaned off cards.
|
|
21
|
+
working: 'vs-working',
|
|
22
|
+
};
|
|
23
|
+
const STAGE_NAMES = new Set([...Object.values(LABELS.stage), LABELS.changes, LABELS.verified, LABELS.parked, LABELS.working]);
|
|
24
|
+
export const isVersionLabel = (name) => /^vs-v\d+$/.test(name);
|
|
25
|
+
// Round labels earlier runners stacked up, one per step and round.
|
|
26
|
+
export const isRoundLabel = (name) => /^vs-(plan|review|dev|qa)-v\d+$/.test(name);
|
|
27
|
+
export const isStatusLabel = (name) => STAGE_NAMES.has(name) || isVersionLabel(name) || isRoundLabel(name);
|
|
28
|
+
// The card's labels with every VoidShift label (and the trigger) replaced by
|
|
29
|
+
// one stage label and, when given, one version label.
|
|
30
|
+
export function stageLabels(current, trigger, stage, round) {
|
|
31
|
+
const kept = current.filter((l) => l !== trigger && !isStatusLabel(l));
|
|
32
|
+
return [...new Set([...kept, stage, ...(round ? [LABELS.version(round)] : [])])];
|
|
33
|
+
}
|
|
34
|
+
// The last "VERDICT: X" line wins; anything unreadable counts as FIX so a
|
|
35
|
+
// confused agent never waves a change through.
|
|
36
|
+
export function parseVerdict(output) {
|
|
37
|
+
const matches = [...output.matchAll(/^\s*VERDICT:\s*(SHIP|FIX|SKIP)\b/gim)];
|
|
38
|
+
const last = matches.at(-1)?.[1]?.toUpperCase();
|
|
39
|
+
return last === 'SHIP' || last === 'SKIP' ? last : 'FIX';
|
|
40
|
+
}
|
|
41
|
+
export function parseDevResult(output) {
|
|
42
|
+
const matches = [...output.matchAll(/^\s*RESULT:\s*(DONE|BLOCKED)\b\s*(.*)$/gim)];
|
|
43
|
+
const last = matches.at(-1);
|
|
44
|
+
if (last?.[1]?.toUpperCase() === 'DONE')
|
|
45
|
+
return { status: 'done' };
|
|
46
|
+
if (last?.[1]?.toUpperCase() === 'BLOCKED')
|
|
47
|
+
return { status: 'blocked', reason: last[2]?.trim() || 'no reason given' };
|
|
48
|
+
return { status: 'blocked', reason: 'the dev agent ended without a RESULT line' };
|
|
49
|
+
}
|
|
50
|
+
export function qaPassed(results) {
|
|
51
|
+
return results.every((r) => r.verdict !== 'FIX');
|
|
52
|
+
}
|
|
53
|
+
// What the dev agent sees on the next round.
|
|
54
|
+
export function findingsFor(results) {
|
|
55
|
+
const failed = results.filter((r) => r.verdict === 'FIX');
|
|
56
|
+
if (failed.length === 1)
|
|
57
|
+
return failed[0].report.trim();
|
|
58
|
+
return failed.map((r) => `### ${r.step}\n\n${r.report.trim()}`).join('\n\n');
|
|
59
|
+
}
|
|
60
|
+
export function latestPlan(comments) {
|
|
61
|
+
const headingOf = (body) => {
|
|
62
|
+
const first = body.trimStart().split('\n', 1)[0].trim();
|
|
63
|
+
return first === PLAN_HEADING || first === OLD_PLAN_HEADING ? first : null;
|
|
64
|
+
};
|
|
65
|
+
const plans = comments
|
|
66
|
+
.filter((c) => headingOf(c.body))
|
|
67
|
+
.sort((a, b) => Date.parse(a.createdAt) - Date.parse(b.createdAt));
|
|
68
|
+
const last = plans.at(-1);
|
|
69
|
+
return last ? last.body.trimStart().slice(headingOf(last.body).length).trim() : null;
|
|
70
|
+
}
|
|
71
|
+
// Strip the frontmatter from a SKILL.md so the body can be inlined.
|
|
72
|
+
export function skillBody(markdown) {
|
|
73
|
+
return markdown.replace(/^---\n[\s\S]*?\n---\n/, '').trim();
|
|
74
|
+
}
|
|
75
|
+
export function buildPrompt(p) {
|
|
76
|
+
const parts = [
|
|
77
|
+
skillBody(p.skill),
|
|
78
|
+
'---',
|
|
79
|
+
`# Card ${p.card.identifier}: ${p.card.title}`,
|
|
80
|
+
p.card.url ? p.card.url : '',
|
|
81
|
+
p.card.description?.trim() || '(no description)',
|
|
82
|
+
'# Plan',
|
|
83
|
+
p.plan,
|
|
84
|
+
`# Round\n\nRound ${p.round}. Base branch: \`${p.base}\`.`,
|
|
85
|
+
];
|
|
86
|
+
if (p.findings)
|
|
87
|
+
parts.push('# Findings to address', p.findings);
|
|
88
|
+
if (p.extra)
|
|
89
|
+
parts.push(p.extra);
|
|
90
|
+
return parts.filter(Boolean).join('\n\n');
|
|
91
|
+
}
|
|
92
|
+
// Consecutive verdict steps run as one block so every finding comes back at
|
|
93
|
+
// once. Returns [start, end) of the block that starts at `i`.
|
|
94
|
+
export function verdictBlock(steps, i, isVerdict) {
|
|
95
|
+
let end = i;
|
|
96
|
+
while (end < steps.length && isVerdict(steps[end]))
|
|
97
|
+
end++;
|
|
98
|
+
return [i, end];
|
|
99
|
+
}
|
|
100
|
+
// Where a failed check sends the work: the nearest earlier step that produces
|
|
101
|
+
// something. -1 means nothing to send it back to.
|
|
102
|
+
export function fixTarget(steps, blockStart, isProducer) {
|
|
103
|
+
for (let j = blockStart - 1; j >= 0; j--)
|
|
104
|
+
if (isProducer(steps[j]))
|
|
105
|
+
return j;
|
|
106
|
+
return -1;
|
|
107
|
+
}
|
|
108
|
+
// Plan output minus the trailing RESULT line, ready to post.
|
|
109
|
+
export function planBody(output) {
|
|
110
|
+
return output.replace(/^\s*RESULT:.*$/gim, '').trim();
|
|
111
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vs-dev
|
|
3
|
+
description: Implement a published plan on its branch. Run by the background runner, not by hand.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Implement a plan
|
|
7
|
+
|
|
8
|
+
You implement one Linear card on its own branch, unattended. The runner gives
|
|
9
|
+
you the card, the plan and, on later rounds, the QA findings to fix. Nobody
|
|
10
|
+
will answer questions; make the call the plan and the code support.
|
|
11
|
+
|
|
12
|
+
## Work
|
|
13
|
+
|
|
14
|
+
1. **Read before you write.** Read every file the plan names, plus the code
|
|
15
|
+
around it, so the change matches the style already there.
|
|
16
|
+
2. **Follow the plan.** Do the numbered steps in order. Where the plan is
|
|
17
|
+
wrong against the code, follow the code, do the smallest thing that meets
|
|
18
|
+
the card, and note it in your report.
|
|
19
|
+
3. **On a fix round**, address every QA finding. When CI failed, read each
|
|
20
|
+
failed check's log first: `gh run view --job <job id from its link>
|
|
21
|
+
--log-failed`. Only fix failures your change caused; if a check fails the
|
|
22
|
+
same way on the base branch, say so in your report instead. Where a finding is wrong,
|
|
23
|
+
leave the code and say why in one line, with the file and line.
|
|
24
|
+
4. **Tests.** Add or update the tests the plan lists. Run the project's
|
|
25
|
+
typecheck, lint and tests that apply, and fix what you broke.
|
|
26
|
+
5. **Commit** on the current branch with short messages in the repo's style.
|
|
27
|
+
Do not push and do not open a pull request; the runner does both.
|
|
28
|
+
|
|
29
|
+
## Never
|
|
30
|
+
|
|
31
|
+
- Run migrations, backfills or scripts against any shared or remote database.
|
|
32
|
+
- Change CI, deploy or environment configuration unless the plan says so.
|
|
33
|
+
- Touch files outside the repository.
|
|
34
|
+
- Put ticket ids in code comments, or use em dashes or en dashes.
|
|
35
|
+
|
|
36
|
+
## Report
|
|
37
|
+
|
|
38
|
+
Short and plain, for a reviewer who has not seen the plan:
|
|
39
|
+
|
|
40
|
+
- First line: what you did, in one sentence.
|
|
41
|
+
- Up to 3 lines on anything that differs from the plan and why.
|
|
42
|
+
- One line on checks: which ran, pass or fail.
|
|
43
|
+
|
|
44
|
+
The final line is exactly one of:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
RESULT: DONE
|
|
48
|
+
RESULT: BLOCKED <one line reason>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
BLOCKED only when the card cannot be done without a human decision.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vs-plan
|
|
3
|
+
description: Plan a Linear card against this repo before any code is written. Use when the user asks to plan a card, plan a ticket, or runs /vs-plan with a card id like ENG-123.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Plan a card
|
|
7
|
+
|
|
8
|
+
You are planning one Linear card against whatever repository is open, with
|
|
9
|
+
the developer beside you. This agent is installed once per machine and works
|
|
10
|
+
in any repo; it never adds files to the repo. The plan becomes the spec a dev
|
|
11
|
+
agent executes later, unattended, without rediscovering what you found. Write
|
|
12
|
+
for that agent. A human should get the whole picture in under a minute.
|
|
13
|
+
|
|
14
|
+
You read code. You do not edit it.
|
|
15
|
+
|
|
16
|
+
## 1. Load the card
|
|
17
|
+
|
|
18
|
+
Fetch the card through the Linear connection: title, description, comments,
|
|
19
|
+
labels. If Linear is not connected, stop and tell the developer to connect it.
|
|
20
|
+
Comments that answer earlier questions are decisions; build on them.
|
|
21
|
+
|
|
22
|
+
Plan drafts live outside every repo, at `~/.config/voidshift/plans/<CARD>.md`.
|
|
23
|
+
If that file exists, this is a revision: read it first and
|
|
24
|
+
keep what still holds.
|
|
25
|
+
|
|
26
|
+
## 2. Check the card against the code
|
|
27
|
+
|
|
28
|
+
Cards are written from memory. Confirm every factual claim before planning:
|
|
29
|
+
something called missing may be mostly built, a "bug" may be configuration, a
|
|
30
|
+
field may not exist, the fix may already be on the base branch. Where the card
|
|
31
|
+
is wrong, say so plainly. If it is already done, the plan is the proof.
|
|
32
|
+
|
|
33
|
+
## 3. Think through six angles
|
|
34
|
+
|
|
35
|
+
Work through each. Write only what applies; "none" is a fine answer.
|
|
36
|
+
|
|
37
|
+
1. **Data and schema.** Tables, collections, fields, indexes, validators. What
|
|
38
|
+
old records look like after the change. Any migration or backfill is a
|
|
39
|
+
human step, never an agent step.
|
|
40
|
+
2. **UI and UX.** The experience end to end: every screen where the value is
|
|
41
|
+
shown or edited, empty, loading and error states, mobile, keyboard,
|
|
42
|
+
accessibility, copy.
|
|
43
|
+
3. **Backend.** Routes, services, jobs, permissions on every path touched,
|
|
44
|
+
other clients of the same endpoint, concurrency and idempotency, cost and
|
|
45
|
+
performance on real data sizes.
|
|
46
|
+
4. **Reuse.** The existing helper, component or pattern to follow so the
|
|
47
|
+
change reads like it was always there. A rule that exists in three places
|
|
48
|
+
gets one home, not a fourth copy.
|
|
49
|
+
5. **Solidify what is there.** Small fixes to the current UI and UX on the
|
|
50
|
+
surfaces this card already touches, which make the result feel finished.
|
|
51
|
+
Keep them small and on those surfaces only.
|
|
52
|
+
6. **Nearby bugs.** Defects in the code around this change that could break it
|
|
53
|
+
or that it would make worse. Fix the ones on the path; list the rest under
|
|
54
|
+
Out of scope.
|
|
55
|
+
|
|
56
|
+
Name what you searched for, so a reviewer can repeat it.
|
|
57
|
+
|
|
58
|
+
## 4. Ask, then write
|
|
59
|
+
|
|
60
|
+
Ask the developer only what blocks the plan and is not answered by the repo or
|
|
61
|
+
the card, one line per question, each with the option you would pick. Where a
|
|
62
|
+
sensible default exists, pick it and say so.
|
|
63
|
+
|
|
64
|
+
Then write the plan to `~/.config/voidshift/plans/<CARD>.md` (create the
|
|
65
|
+
folder if needed). Never post to Linear from this agent; `vs-publish` does that.
|
|
66
|
+
|
|
67
|
+
## 5. Get it reviewed before showing it
|
|
68
|
+
|
|
69
|
+
The developer should only ever see a plan that has already been reviewed.
|
|
70
|
+
|
|
71
|
+
1. Run the `vs-plan-review` checks as a separate pass with fresh eyes: in Claude
|
|
72
|
+
Code, hand them to a subagent with the card id and the plan file path; where
|
|
73
|
+
no subagent is available, re-read the plan cold and apply that checklist
|
|
74
|
+
yourself.
|
|
75
|
+
2. If it says FIX, fix the plan file for every finding that is right. Where a
|
|
76
|
+
finding is wrong, keep the plan and note why in one line.
|
|
77
|
+
3. Repeat until it says SHIP, at most 3 rounds. If it still says FIX after 3,
|
|
78
|
+
stop and show what is left as decisions for the developer.
|
|
79
|
+
|
|
80
|
+
Then show the developer the short version below.
|
|
81
|
+
|
|
82
|
+
## What you show the developer
|
|
83
|
+
|
|
84
|
+
The plan file holds the detail. In the chat, keep it short and plain:
|
|
85
|
+
|
|
86
|
+
- First line: `Reviewed: ready after N rounds.` or `Reviewed: N things still need your call.`
|
|
87
|
+
- One or two lines: what the card really needs, and what it got wrong.
|
|
88
|
+
- The steps, one short sentence each, no file paths.
|
|
89
|
+
- Any decision only they can make, as a question with your pick.
|
|
90
|
+
- The path to the plan file, and that `/vs-publish <CARD>` hands it over.
|
|
91
|
+
|
|
92
|
+
## Plan shape (the file)
|
|
93
|
+
|
|
94
|
+
Start straight at Understanding. Do not repeat the card id or title; the card
|
|
95
|
+
already shows them.
|
|
96
|
+
|
|
97
|
+
Length follows the change: under 350 words for a small one, never padded.
|
|
98
|
+
|
|
99
|
+
**Understanding.** Two to four sentences: what the card asks, what it got
|
|
100
|
+
wrong, which reading you chose.
|
|
101
|
+
|
|
102
|
+
**Surfaces.** Each file that changes as `path/to/file.ts:123` and why. One
|
|
103
|
+
line on what you searched and ruled out.
|
|
104
|
+
|
|
105
|
+
**Approach.** Numbered steps concrete enough to execute without judgment, each
|
|
106
|
+
naming the pattern to follow. One line on the alternative not taken.
|
|
107
|
+
|
|
108
|
+
**Six angles.** One short line per angle that applies.
|
|
109
|
+
|
|
110
|
+
**Tests.** For each behaviour that changes, the test that fails before and
|
|
111
|
+
passes after. Tests that encode the old behaviour and must change.
|
|
112
|
+
|
|
113
|
+
**Done when.** Checkable criteria plus the commands that must pass, and
|
|
114
|
+
anything a human must click.
|
|
115
|
+
|
|
116
|
+
**Human steps.** Migrations, backfills, environment variables, releases.
|
|
117
|
+
"None" if none.
|
|
118
|
+
|
|
119
|
+
**Out of scope.** Worth doing, not asked for, one line each.
|
|
120
|
+
|
|
121
|
+
## Rules
|
|
122
|
+
|
|
123
|
+
- No ticket ids in code comments.
|
|
124
|
+
- No em dashes or en dashes.
|
|
125
|
+
- No narration of process. State findings.
|
|
126
|
+
|
|
127
|
+
## When you run inside a workflow
|
|
128
|
+
|
|
129
|
+
The card is in the prompt and nobody can answer. Skip the Linear fetch, the
|
|
130
|
+
questions and step 5 (the workflow runs its own review): pick the sensible default for anything open and state it under
|
|
131
|
+
Understanding. Do not write a plan file. Return the plan in the shape above as
|
|
132
|
+
your final message, then one last line, exactly one of:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
RESULT: DONE
|
|
136
|
+
RESULT: BLOCKED <one line reason>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
If findings from a plan review are in the prompt, revise the plan to address
|
|
140
|
+
every one, or say in one line why a finding is wrong.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vs-plan-review
|
|
3
|
+
description: Review a plan against the code before it is published. Use when the user asks to review a plan, check a plan, or runs /vs-plan-review with a card id.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Review a plan
|
|
7
|
+
|
|
8
|
+
You check a plan written by `vs-plan` for one Linear card. Your job is to find
|
|
9
|
+
what the plan got wrong or missed before a dev agent spends a run on it. You
|
|
10
|
+
read code. You do not edit code or the plan.
|
|
11
|
+
|
|
12
|
+
## Inputs
|
|
13
|
+
|
|
14
|
+
- The plan at `~/.config/voidshift/plans/<CARD>.md`.
|
|
15
|
+
- The card, through the Linear connection: description and comments.
|
|
16
|
+
- The open repository.
|
|
17
|
+
|
|
18
|
+
## Check
|
|
19
|
+
|
|
20
|
+
1. **Claims.** Every file, function, field and line the plan cites exists and
|
|
21
|
+
says what the plan says. Re-run the searches the plan names.
|
|
22
|
+
2. **Missed surfaces.** Search for the thing the card is about yourself. Any
|
|
23
|
+
reader, writer, screen, export, validator, permission or test the plan
|
|
24
|
+
left out is a finding.
|
|
25
|
+
3. **Six angles.** Data and schema, UI and UX, backend, reuse, solidifying
|
|
26
|
+
what is there, nearby bugs. Flag any angle the plan skipped that applies.
|
|
27
|
+
4. **Executability.** Could an agent follow each step without judgment? Vague
|
|
28
|
+
steps ("update the UI as needed") are findings.
|
|
29
|
+
5. **Done when.** Every criterion is checkable and covers what the card asks.
|
|
30
|
+
6. **Scope.** Work the card did not ask for belongs under Out of scope.
|
|
31
|
+
|
|
32
|
+
Do not flag style preferences or restate the plan. Each finding must change
|
|
33
|
+
what gets built.
|
|
34
|
+
|
|
35
|
+
## Output
|
|
36
|
+
|
|
37
|
+
Write for a busy developer: the answer first, plain words, no file paths in the
|
|
38
|
+
main points.
|
|
39
|
+
|
|
40
|
+
1. First line: `Ready to build.` or `Not ready yet. N things to fix:`
|
|
41
|
+
2. The findings that change what gets built, most important first, at most 5,
|
|
42
|
+
one short plain line each: what is wrong and what to do about it.
|
|
43
|
+
3. Everything smaller in one line: `Minor: ...`.
|
|
44
|
+
4. A short `Details` section: for each finding, the file and line that proves it.
|
|
45
|
+
5. Last line, exactly one of:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
VERDICT: SHIP
|
|
49
|
+
VERDICT: FIX
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
SHIP means a dev agent can execute the plan as written. Offer to apply the
|
|
53
|
+
fixes to the plan file.
|
|
54
|
+
|
|
55
|
+
## Rules
|
|
56
|
+
|
|
57
|
+
- No em dashes or en dashes.
|
|
58
|
+
- No narration of process. State findings.
|
|
59
|
+
|
|
60
|
+
## When you run inside a workflow
|
|
61
|
+
|
|
62
|
+
The card and the plan are in the prompt; read them there instead of the plan
|
|
63
|
+
file and Linear. Do not offer to edit anything. End with the VERDICT line.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vs-publish
|
|
3
|
+
description: Publish an approved plan to its Linear card and hand the card to the background agents. Use when the user says the plan is approved, asks to publish a plan, or runs /vs-publish with a card id.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Publish a plan
|
|
7
|
+
|
|
8
|
+
The developer has reviewed and approved the plan for one card. Hand it over to
|
|
9
|
+
the background agents. Do every step; stop and report if one fails.
|
|
10
|
+
|
|
11
|
+
1. **Read the plan** at `~/.config/voidshift/plans/<CARD>.md`. If it is
|
|
12
|
+
missing, stop and say so.
|
|
13
|
+
2. **Post it to the card** through the Linear connection as one comment whose
|
|
14
|
+
first line is exactly:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
## Plan
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
followed by the plan unchanged. The background agents find the plan by
|
|
21
|
+
that heading, newest first.
|
|
22
|
+
3. **Create the branch** the card names (Linear's branch name for the card),
|
|
23
|
+
from the project's base branch without switching the developer's checkout.
|
|
24
|
+
The base is the `base` of this repo's project in
|
|
25
|
+
`~/.config/voidshift/agents/config.json`, or the repo's default branch when
|
|
26
|
+
it has none:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
git fetch origin
|
|
30
|
+
git branch <branch> origin/<base>
|
|
31
|
+
git push -u origin <branch>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If the branch already exists on origin, leave it.
|
|
35
|
+
4. **Hand it over.** Add the label `vs-plan` to the card and make sure the card
|
|
36
|
+
is assigned to the developer. That label is what the background agents
|
|
37
|
+
pick up.
|
|
38
|
+
5. **Clean up.** Delete the local plan file.
|
|
39
|
+
6. **Report** in one line: the card, the branch, and that the agents pick it
|
|
40
|
+
up within about a minute if the runner is on.
|
|
41
|
+
|
|
42
|
+
## Rules
|
|
43
|
+
|
|
44
|
+
- Never edit the plan while publishing.
|
|
45
|
+
- No em dashes or en dashes.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vs-qa
|
|
3
|
+
description: QA a branch against its card and plan, CI first, then code review, then a usability check in a headless browser. Use when the user asks to QA a branch or card, or runs /vs-qa with a card id.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# QA
|
|
7
|
+
|
|
8
|
+
You check the change on the current branch for one Linear card. Three checks,
|
|
9
|
+
in order. You read code and run commands; you do not edit code.
|
|
10
|
+
|
|
11
|
+
## 1. CI
|
|
12
|
+
|
|
13
|
+
If the prompt already reports CI as passed, move on. Otherwise run
|
|
14
|
+
`gh pr checks` for the branch. Failing checks are findings; stop here and
|
|
15
|
+
report them, since review on a red build wastes everyone's time.
|
|
16
|
+
|
|
17
|
+
## 2. Code review
|
|
18
|
+
|
|
19
|
+
1. **Diff.** `git diff <base>...HEAD` is the whole change. Read it fully, and
|
|
20
|
+
the surrounding code for every hunk.
|
|
21
|
+
2. **Against the card.** Every acceptance point in the card and every Done
|
|
22
|
+
when criterion in the plan is met. Check exemptions and special cases in
|
|
23
|
+
the code against the card's wording: a carve-out the card did not allow is
|
|
24
|
+
a finding.
|
|
25
|
+
3. **Correctness.** Logic errors, missed callers, broken old records,
|
|
26
|
+
permissions, error and empty states, races, anything that would fail in
|
|
27
|
+
production.
|
|
28
|
+
4. **Surfaces.** Search for other readers and writers of what changed. A
|
|
29
|
+
surface the change should have updated and did not is a finding.
|
|
30
|
+
5. **Tests.** The changed behaviour has tests that would fail without it. Run
|
|
31
|
+
the project's typecheck and tests if they exist and report failures.
|
|
32
|
+
6. **Fit.** The change follows the patterns around it, with no duplicated
|
|
33
|
+
rules, no `any`, no dead code, no ticket ids in comments.
|
|
34
|
+
|
|
35
|
+
Only report findings that change behaviour or would block a careful reviewer.
|
|
36
|
+
No style nits.
|
|
37
|
+
|
|
38
|
+
## 3. Usability check
|
|
39
|
+
|
|
40
|
+
Only if the change has a user-facing surface.
|
|
41
|
+
|
|
42
|
+
1. Find how the project runs locally (README, `package.json` scripts). If it
|
|
43
|
+
needs services you cannot start (databases, other apps, secrets), skip this
|
|
44
|
+
check and say why in one line.
|
|
45
|
+
2. Start it from this checkout on a free port, in the background, and wait
|
|
46
|
+
until it answers.
|
|
47
|
+
3. Drive a headless browser with Playwright (for example a short script run
|
|
48
|
+
with `npx playwright`). Never open a visible window. For each flow in the
|
|
49
|
+
plan's Done when: open the page, do the clicks and typing, check what is on
|
|
50
|
+
screen. Note console errors, failed requests, layout that breaks at a phone
|
|
51
|
+
width, and anything unreadable.
|
|
52
|
+
4. Stop everything you started.
|
|
53
|
+
|
|
54
|
+
## Output
|
|
55
|
+
|
|
56
|
+
Write for a busy developer: the answer first, plain words.
|
|
57
|
+
|
|
58
|
+
1. First line: `Passed.` or `Changes needed: N things.`
|
|
59
|
+
2. One line per check: CI, Code review, Usability, each passed, failed or
|
|
60
|
+
skipped (with why).
|
|
61
|
+
3. The problems, most important first, at most 5, one short plain line each:
|
|
62
|
+
what is wrong and what to do.
|
|
63
|
+
4. Everything smaller in one line: `Minor: ...`.
|
|
64
|
+
5. A short `Details` section with the file and line for each problem.
|
|
65
|
+
6. Last line, exactly one of:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
VERDICT: SHIP
|
|
69
|
+
VERDICT: FIX
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
No em dashes or en dashes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voidlabs.gg/voidshift-agents",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "Agents for Claude Code and Codex that plan, build and QA Linear cards, chained and run in the background.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/EratosVoid/voidshift.git",
|
|
9
|
+
"directory": "tools/agents"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://voidlabs.gg",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/EratosVoid/voidshift/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"claude-code",
|
|
17
|
+
"codex",
|
|
18
|
+
"agents",
|
|
19
|
+
"linear",
|
|
20
|
+
"cli",
|
|
21
|
+
"macos"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "dist/index.js",
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"pack",
|
|
29
|
+
"LICENSE",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"os": [
|
|
33
|
+
"darwin"
|
|
34
|
+
],
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=22.18"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public",
|
|
40
|
+
"provenance": true
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "rm -rf dist && tsc -p tsconfig.json",
|
|
44
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
45
|
+
"test": "node --test test/*.test.ts",
|
|
46
|
+
"prepublishOnly": "rm -rf dist && tsc -p tsconfig.json"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^22.18.0",
|
|
50
|
+
"typescript": "^5.9.0"
|
|
51
|
+
}
|
|
52
|
+
}
|