opencode-harness-kit 0.0.0-stage → 0.1.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/GLOBAL.md +110 -0
- package/LICENSE +21 -0
- package/README.md +421 -2
- package/agents/build.md +66 -0
- package/agents/locate.md +48 -0
- package/agents/plan.md +61 -0
- package/agents/reviewer.md +62 -0
- package/agents/verify.md +54 -0
- package/bin/baseline.mjs +367 -0
- package/bin/git-hooks/pre-commit +30 -0
- package/bin/oc-harness.mjs +977 -0
- package/dist/index.js +976 -0
- package/docs/KNOWN-LIMITS.md +188 -0
- package/docs/RESEARCH.md +210 -0
- package/examples/muse-spark-1.3-contributor-free.json +41 -0
- package/package.json +77 -4
- package/profiles/deepseek-v4-flash-free.json +41 -0
- package/profiles/index.json +60 -0
- package/profiles/longcat-2.5-preview-free.json +41 -0
- package/profiles/schema.json +132 -0
- package/profiles/space-bunny-free.json +42 -0
- package/profiles/x-preview-f-free.json +41 -0
- package/retention.yml +110 -0
- package/skills/space-build/SKILL.md +54 -0
- package/skills/space-finish/SKILL.md +63 -0
- package/skills/space-plan/SKILL.md +101 -0
- package/skills/space-plan/reference/task-template.md +47 -0
- package/skills/space-review/SKILL.md +53 -0
- package/src/config.js +326 -0
- package/src/effort.js +98 -0
- package/src/guard.ts +59 -0
- package/src/index.ts +80 -0
- package/src/profile.js +333 -0
- package/src/prune.ts +258 -0
- package/src/router.ts +192 -0
- package/src/rules.js +496 -0
- package/src/telemetry.ts +98 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://github.com/anomalyco/opencode-harness-kit/profiles/schema.json",
|
|
4
|
+
"title": "OpenCode harness profile",
|
|
5
|
+
"description": "Everything that changes when you change model. Plugins read this file and contain no model names of their own.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["id", "provider", "model", "retention", "limits", "effort", "roles"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"id": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Slug used as the profile filename and the oc-harness use argument."
|
|
13
|
+
},
|
|
14
|
+
"title": { "type": "string" },
|
|
15
|
+
"provider": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "opencode provider id, e.g. opencode, opencode-go, anthropic."
|
|
18
|
+
},
|
|
19
|
+
"model": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Model id without the provider prefix, e.g. space-bunny-free."
|
|
22
|
+
},
|
|
23
|
+
"family": {
|
|
24
|
+
"type": ["string", "null"],
|
|
25
|
+
"description": "Model family for grouping. Stealth models report null upstream, so this may be set by hand."
|
|
26
|
+
},
|
|
27
|
+
"verified": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "ISO date a human checked this profile against live metadata."
|
|
30
|
+
},
|
|
31
|
+
"retention": {
|
|
32
|
+
"enum": ["zero-retention", "may-train", "unknown"],
|
|
33
|
+
"description": "Must match an entry in retention.yml. A profile whose model is unknown there cannot become the default."
|
|
34
|
+
},
|
|
35
|
+
"notes": { "type": "string" },
|
|
36
|
+
"limits": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"required": ["context", "output"],
|
|
39
|
+
"additionalProperties": false,
|
|
40
|
+
"description": "Token ceilings from the provider catalog. `input` is absent for several Zen models, in which case the loader derives it from `context`.",
|
|
41
|
+
"properties": {
|
|
42
|
+
"context": { "type": "integer", "minimum": 1 },
|
|
43
|
+
"input": { "type": "integer", "minimum": 1 },
|
|
44
|
+
"output": { "type": "integer", "minimum": 1 }
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"supports": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"additionalProperties": false,
|
|
50
|
+
"description": "Capability flags. Missing or false means do not emit the related config.",
|
|
51
|
+
"properties": {
|
|
52
|
+
"reasoning": { "type": "boolean" },
|
|
53
|
+
"temperature": { "type": "boolean" },
|
|
54
|
+
"toolCall": { "type": "boolean" },
|
|
55
|
+
"structuredOutput": { "type": "boolean" },
|
|
56
|
+
"attachment": {
|
|
57
|
+
"type": "boolean",
|
|
58
|
+
"description": "Accepts image or video input. Gates screenshot-based verification."
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"effort": {
|
|
63
|
+
"type": "object",
|
|
64
|
+
"description": "Available reasoning levels, lowest to highest. Empty means the model has no tunable effort.",
|
|
65
|
+
"properties": {
|
|
66
|
+
"levels": {
|
|
67
|
+
"type": "array",
|
|
68
|
+
"items": { "type": "string" },
|
|
69
|
+
"examples": [["low", "medium", "high", "xhigh", "max"]]
|
|
70
|
+
},
|
|
71
|
+
"default": { "type": "string" },
|
|
72
|
+
"reserveShare": {
|
|
73
|
+
"type": "number",
|
|
74
|
+
"minimum": 0,
|
|
75
|
+
"maximum": 0.5,
|
|
76
|
+
"default": 0.12,
|
|
77
|
+
"description": "Share of the input ceiling held back for reasoning and tool output growth."
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"roles": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"description": "Requested effort per agent role. Resolved against effort.levels, never emitted raw.",
|
|
84
|
+
"additionalProperties": false,
|
|
85
|
+
"properties": {
|
|
86
|
+
"plan": { "$ref": "#/definitions/effortRequest" },
|
|
87
|
+
"build": { "$ref": "#/definitions/effortRequest" },
|
|
88
|
+
"reviewer": { "$ref": "#/definitions/effortRequest" },
|
|
89
|
+
"locate": { "$ref": "#/definitions/effortRequest" },
|
|
90
|
+
"verify": { "$ref": "#/definitions/effortRequest" }
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"prune": {
|
|
94
|
+
"type": "object",
|
|
95
|
+
"additionalProperties": false,
|
|
96
|
+
"description": "Deterministic context pruning. Only used when a model-driven compressor is unavailable or unproven.",
|
|
97
|
+
"properties": {
|
|
98
|
+
"enabled": { "type": "boolean" },
|
|
99
|
+
"keepRecentToolCalls": {
|
|
100
|
+
"type": "integer",
|
|
101
|
+
"minimum": 1,
|
|
102
|
+
"default": 6,
|
|
103
|
+
"description": "Verbatim tool outputs kept at the tail."
|
|
104
|
+
},
|
|
105
|
+
"keepRecentTurns": {
|
|
106
|
+
"type": "integer",
|
|
107
|
+
"minimum": 1,
|
|
108
|
+
"default": 3,
|
|
109
|
+
"description": "Trailing turns whose text and reasoning stay verbatim."
|
|
110
|
+
},
|
|
111
|
+
"keepUserMessages": {
|
|
112
|
+
"type": "boolean",
|
|
113
|
+
"default": true,
|
|
114
|
+
"description": "Never stub a user message. Their instructions are the point of the session."
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"fallback": {
|
|
119
|
+
"type": "array",
|
|
120
|
+
"description": "Ordered profile ids to fall back to. Selection happens at session start, not mid-session: no opencode plugin hook can change a live session's model.",
|
|
121
|
+
"items": { "type": "string" }
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"definitions": {
|
|
125
|
+
"effortRequest": {
|
|
126
|
+
"oneOf": [
|
|
127
|
+
{ "type": "string", "description": "Desired level, resolved to the nearest available one." },
|
|
128
|
+
{ "type": "null", "description": "This role should not set a variant at all." }
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Validated against models.dev on 2026-10-07. Regenerate with `oc-harness use --refresh`.",
|
|
3
|
+
"id": "space-bunny-free",
|
|
4
|
+
"title": "Space Bunny Free (OpenCode Zen)",
|
|
5
|
+
"provider": "opencode",
|
|
6
|
+
"model": "space-bunny-free",
|
|
7
|
+
"family": null,
|
|
8
|
+
"verified": "2026-10-07",
|
|
9
|
+
"retention": "zero-retention",
|
|
10
|
+
"notes": "Stealth preview reasoning model. Served over /v1/chat/completions (openai-compatible), which is the weaker cache dialect compared with models on /v1/responses. At the time of writing it is the only free model on Zen whose top reasoning effort is `max` and whose provider is zero-retention. Free for a limited time; expect the slot to rotate.",
|
|
11
|
+
"limits": {
|
|
12
|
+
"context": 1048576,
|
|
13
|
+
"input": 524288,
|
|
14
|
+
"output": 524288
|
|
15
|
+
},
|
|
16
|
+
"supports": {
|
|
17
|
+
"reasoning": true,
|
|
18
|
+
"temperature": false,
|
|
19
|
+
"toolCall": true,
|
|
20
|
+
"structuredOutput": false,
|
|
21
|
+
"attachment": true
|
|
22
|
+
},
|
|
23
|
+
"effort": {
|
|
24
|
+
"levels": ["low", "medium", "high", "xhigh", "max"],
|
|
25
|
+
"default": "max",
|
|
26
|
+
"reserveShare": 0.12
|
|
27
|
+
},
|
|
28
|
+
"roles": {
|
|
29
|
+
"plan": "max",
|
|
30
|
+
"build": "high",
|
|
31
|
+
"reviewer": "max",
|
|
32
|
+
"locate": "low",
|
|
33
|
+
"verify": "low"
|
|
34
|
+
},
|
|
35
|
+
"prune": {
|
|
36
|
+
"enabled": true,
|
|
37
|
+
"keepRecentToolCalls": 6,
|
|
38
|
+
"keepRecentTurns": 3,
|
|
39
|
+
"keepUserMessages": true
|
|
40
|
+
},
|
|
41
|
+
"fallback": ["x-preview-f-free", "longcat-2.5-preview-free", "deepseek-v4-flash-free"]
|
|
42
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Fallback tier 1 for space-bunny-free. Zero-retention, 1M context, and a `max` effort, but only three levels: there is no medium or xhigh, so roles asking for those resolve down to high.",
|
|
3
|
+
"id": "x-preview-f-free",
|
|
4
|
+
"title": "x-preview-f Free (OpenCode Zen)",
|
|
5
|
+
"provider": "opencode",
|
|
6
|
+
"model": "x-preview-f-free",
|
|
7
|
+
"family": null,
|
|
8
|
+
"verified": "2026-10-07",
|
|
9
|
+
"retention": "zero-retention",
|
|
10
|
+
"notes": "Only three effort levels (low, high, max) and a 131k completion ceiling, so long single answers are not its strength. Kept as first fallback: same 1M context class and the same zero-retention terms as the default.",
|
|
11
|
+
"limits": {
|
|
12
|
+
"context": 1000000,
|
|
13
|
+
"output": 131072
|
|
14
|
+
},
|
|
15
|
+
"supports": {
|
|
16
|
+
"reasoning": true,
|
|
17
|
+
"temperature": true,
|
|
18
|
+
"toolCall": true,
|
|
19
|
+
"structuredOutput": true,
|
|
20
|
+
"attachment": true
|
|
21
|
+
},
|
|
22
|
+
"effort": {
|
|
23
|
+
"levels": ["low", "high", "max"],
|
|
24
|
+
"default": "max",
|
|
25
|
+
"reserveShare": 0.12
|
|
26
|
+
},
|
|
27
|
+
"roles": {
|
|
28
|
+
"plan": "max",
|
|
29
|
+
"build": "high",
|
|
30
|
+
"reviewer": "max",
|
|
31
|
+
"locate": "low",
|
|
32
|
+
"verify": "low"
|
|
33
|
+
},
|
|
34
|
+
"prune": {
|
|
35
|
+
"enabled": true,
|
|
36
|
+
"keepRecentToolCalls": 6,
|
|
37
|
+
"keepRecentTurns": 3,
|
|
38
|
+
"keepUserMessages": true
|
|
39
|
+
},
|
|
40
|
+
"fallback": ["longcat-2.5-preview-free", "deepseek-v4-flash-free"]
|
|
41
|
+
}
|
package/retention.yml
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Data retention and privacy, curated by hand.
|
|
2
|
+
#
|
|
3
|
+
# models.dev describes capability and price. It does NOT describe what a
|
|
4
|
+
# provider does with your prompts. That gap is why this file exists: the most
|
|
5
|
+
# consequential choice in a coding agent is often invisible in the metadata.
|
|
6
|
+
#
|
|
7
|
+
# Values:
|
|
8
|
+
# zero-retention provider keeps nothing, no training
|
|
9
|
+
# may-train prompts and/or completions may be used to improve the model
|
|
10
|
+
# unknown not verified here; `oc-harness use` refuses to make it a
|
|
11
|
+
# default until a human fills this in
|
|
12
|
+
#
|
|
13
|
+
# Sources: https://opencode.ai/docs/zen (Privacy section). Re-verify on their
|
|
14
|
+
# release notes; terms change without a model rename.
|
|
15
|
+
|
|
16
|
+
defaults:
|
|
17
|
+
unknown: unknown
|
|
18
|
+
|
|
19
|
+
models:
|
|
20
|
+
opencode/space-bunny-free:
|
|
21
|
+
retention: zero-retention
|
|
22
|
+
note: >-
|
|
23
|
+
"Its provider follows a zero-retention policy and does not use your data
|
|
24
|
+
for model training." Free for a limited time; stealth model with no public
|
|
25
|
+
identity.
|
|
26
|
+
verified: 2026-10-07
|
|
27
|
+
source: https://opencode.ai/docs/zen
|
|
28
|
+
|
|
29
|
+
opencode/space-bunny:
|
|
30
|
+
retention: zero-retention
|
|
31
|
+
note: Same provider as space-bunny-free, paid route on the Go plan.
|
|
32
|
+
verified: 2026-10-07
|
|
33
|
+
source: https://opencode.ai/docs/zen
|
|
34
|
+
|
|
35
|
+
opencode/longcat-2.5-preview-free:
|
|
36
|
+
retention: zero-retention
|
|
37
|
+
note: "free on OpenCode for a limited time. Its provider follows a zero-retention policy."
|
|
38
|
+
verified: 2026-10-07
|
|
39
|
+
source: https://opencode.ai/docs/zen
|
|
40
|
+
|
|
41
|
+
# The two entries below are not named individually in the Privacy section.
|
|
42
|
+
# They fall under the general policy - providers follow zero-retention and do
|
|
43
|
+
# not train on your data, with a named exception list - so this is inferred
|
|
44
|
+
# from that list rather than quoted. Re-check before relying on it for
|
|
45
|
+
# anything sensitive.
|
|
46
|
+
|
|
47
|
+
opencode/x-preview-f-free:
|
|
48
|
+
retention: zero-retention
|
|
49
|
+
note: >-
|
|
50
|
+
Not named in the Privacy exception list, so the general zero-retention
|
|
51
|
+
policy applies. Inferred, not quoted.
|
|
52
|
+
verified: 2026-10-07
|
|
53
|
+
source: https://opencode.ai/docs/zen
|
|
54
|
+
|
|
55
|
+
opencode/deepseek-v4-flash-free:
|
|
56
|
+
retention: zero-retention
|
|
57
|
+
note: >-
|
|
58
|
+
Not named in the Privacy exception list, so the general zero-retention
|
|
59
|
+
policy applies. Inferred, not quoted. This route is also documented as
|
|
60
|
+
returning 429 for extended periods, so see docs/KNOWN-LIMITS.md.
|
|
61
|
+
verified: 2026-10-07
|
|
62
|
+
source: https://opencode.ai/docs/zen
|
|
63
|
+
|
|
64
|
+
opencode/muse-spark-1.3-contributor-free:
|
|
65
|
+
retention: may-train
|
|
66
|
+
note: >-
|
|
67
|
+
"Heavily discounted token pricing in exchange for permission to use your
|
|
68
|
+
prompts and completions to train future Meta models." 1M context, but its
|
|
69
|
+
top reasoning effort is xhigh, not max. Kept as an example of a
|
|
70
|
+
capability/privacy tradeoff, never as a default for private code.
|
|
71
|
+
verified: 2026-10-07
|
|
72
|
+
source: https://opencode.ai/docs/zen
|
|
73
|
+
|
|
74
|
+
opencode/muse-spark-1.3:
|
|
75
|
+
retention: may-train
|
|
76
|
+
note: Same Meta contributor terms as the free variant.
|
|
77
|
+
verified: 2026-10-07
|
|
78
|
+
source: https://opencode.ai/docs/zen
|
|
79
|
+
|
|
80
|
+
opencode/big-pickle:
|
|
81
|
+
retention: may-train
|
|
82
|
+
note: "collected data may be used to improve the model" during its free period.
|
|
83
|
+
verified: 2026-10-07
|
|
84
|
+
source: https://opencode.ai/docs/zen
|
|
85
|
+
|
|
86
|
+
opencode/exo-free:
|
|
87
|
+
retention: may-train
|
|
88
|
+
note: "collected data may be used to improve the model" during its free period.
|
|
89
|
+
verified: 2026-10-07
|
|
90
|
+
source: https://opencode.ai/docs/zen
|
|
91
|
+
|
|
92
|
+
opencode/fledge-alpha-free:
|
|
93
|
+
retention: may-train
|
|
94
|
+
note: "collected data may be used to improve the model" during its free period.
|
|
95
|
+
verified: 2026-10-07
|
|
96
|
+
source: https://opencode.ai/docs/zen
|
|
97
|
+
|
|
98
|
+
opencode/mimo-v2.5-free:
|
|
99
|
+
retention: may-train
|
|
100
|
+
note: "collected data may be used to improve the model" during its free period.
|
|
101
|
+
verified: 2026-10-07
|
|
102
|
+
source: https://opencode.ai/docs/zen
|
|
103
|
+
|
|
104
|
+
opencode/nemotron-3-ultra-free:
|
|
105
|
+
retention: may-train
|
|
106
|
+
note: >-
|
|
107
|
+
NVIDIA free trial endpoints. Trial use only, do not submit personal or
|
|
108
|
+
confidential data; sessions are logged.
|
|
109
|
+
verified: 2026-10-07
|
|
110
|
+
source: https://opencode.ai/docs/zen
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: space-build
|
|
3
|
+
description: Implement one planned task and verify it with a real command. Use when the plan is settled and files need to change.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Build one task, then prove it
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. **Read the task from `.space/tasks.md`, not from the conversation.** The file
|
|
11
|
+
the plan wrote is the requirement; memory of the request is not. If there is
|
|
12
|
+
no file, ask for the plan first — a task with no verify command in it is not
|
|
13
|
+
a task you can finish.
|
|
14
|
+
2. **Locate before you read.** `grep`/`glob` for the candidate files, then
|
|
15
|
+
`read` with an `offset`/`limit` for the range you need. Reading whole files to
|
|
16
|
+
find out where something lives was the most expensive habit measured on this
|
|
17
|
+
setup: 2,966 full-file reads against 249 searches, about twelve per search.
|
|
18
|
+
3. **Read the whole file before editing it** - not a grep hit, the file. Partial
|
|
19
|
+
reads produce edits that contradict code you did not see.
|
|
20
|
+
4. **Make the smallest change** that satisfies the task. If the task is bigger
|
|
21
|
+
than it looks, stop and say so rather than quietly expanding it.
|
|
22
|
+
5. **Run the verify command the plan named.** That command, not a different one,
|
|
23
|
+
not a subset.
|
|
24
|
+
6. **On failure, read the actual message.** Not the last ten lines, the error.
|
|
25
|
+
Fix the cause, then run it again. The third identical attempt is a signal to
|
|
26
|
+
stop and report.
|
|
27
|
+
7. **Mark the task done in `.space/tasks.md`** and paste the verify command's
|
|
28
|
+
verbatim final lines into its `verify:` line. A task marked done without
|
|
29
|
+
that has not been verified.
|
|
30
|
+
8. **Report the command and its verbatim output.**
|
|
31
|
+
|
|
32
|
+
## Test-first when the plan called for it
|
|
33
|
+
|
|
34
|
+
If the plan said test first, write the failing test and watch it fail. A test
|
|
35
|
+
that has never failed has not been shown to test anything.
|
|
36
|
+
|
|
37
|
+
## Never
|
|
38
|
+
|
|
39
|
+
- Leave a `TODO`, a stub, or a commented-out block for later. Partial work
|
|
40
|
+
reported as complete is the failure mode this exists to prevent.
|
|
41
|
+
- Widen the task. A drive-by refactor belongs in its own plan.
|
|
42
|
+
- Skip a failing test to get to green. Report it.
|
|
43
|
+
- Claim a result you did not run.
|
|
44
|
+
|
|
45
|
+
## Handing back
|
|
46
|
+
|
|
47
|
+
Which task, which command, which result. If anything is unfinished, list it
|
|
48
|
+
explicitly rather than letting the review step find it.
|
|
49
|
+
|
|
50
|
+
**If you were handed back here by `space-review`**, you have a blocker with a
|
|
51
|
+
`file:line` and a failing command, not a fresh task. Fix that specific thing.
|
|
52
|
+
Do not re-read the plan, do not look for other improvements, and do not treat
|
|
53
|
+
the review as a suggestion. A blocker that gets fixed together with a refactor
|
|
54
|
+
cannot be verified on its own.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: space-finish
|
|
3
|
+
description: Close out a task: confirm checks, summarise the change, and hand the publish decision to a human. Use when work is implemented and reviewed.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Finish
|
|
7
|
+
|
|
8
|
+
Reached only when `space-review` pass 1 was clean. If there is an open
|
|
9
|
+
blocker, you are at the wrong step: send it to `space-build` instead. Finishing
|
|
10
|
+
over an unreviewed or blocked change is the failure this skill exists to stop.
|
|
11
|
+
|
|
12
|
+
## Steps
|
|
13
|
+
|
|
14
|
+
1. **Read `.space/tasks.md` first.** Any task still `pending` or `blocked`
|
|
15
|
+
means the work is unfinished: stop and say which one. The file is the
|
|
16
|
+
requirement, same as it was for `space-review`.
|
|
17
|
+
2. **Run the checks one final time, on the final state of the tree.** A green
|
|
18
|
+
suite from before the last edit is not a green suite. Use `verify`.
|
|
19
|
+
3. **Read the diff once more as a whole.** Reviewers read task by task; you
|
|
20
|
+
read the change as someone who has never seen it will.
|
|
21
|
+
4. **Check the documentation.** Did this change make a document describe
|
|
22
|
+
something that no longer exists? Fix the document, do not note it for later.
|
|
23
|
+
5. **Write the summary** a person needs in order to trust the change without
|
|
24
|
+
reading the whole diff. Anything the Decisions section of `.space/tasks.md`
|
|
25
|
+
marked as deliberately not done belongs in the summary, with its reason.
|
|
26
|
+
6. **Check the install is still whole.** If this project is driven by a generated
|
|
27
|
+
config or profile, run its verify command. A hand-edit survives a regeneration
|
|
28
|
+
silently, and that is how a zero-retention claim ends up running on a
|
|
29
|
+
may-train model.
|
|
30
|
+
2. **Read the diff once more as a whole.** Reviewers read task by task; you
|
|
31
|
+
read the change as someone who has never seen it will.
|
|
32
|
+
3. **Check the documentation.** Did this change make a document describe
|
|
33
|
+
something that no longer exists? Fix the document, do not note it for later.
|
|
34
|
+
4. **Write the summary** a person needs in order to trust the change without
|
|
35
|
+
reading the whole diff.
|
|
36
|
+
5. **Check the install is still whole.** If this project is driven by a generated
|
|
37
|
+
config or profile, run its verify command. A hand-edit survives a regeneration
|
|
38
|
+
silently, and that is how a zero-retention claim ends up running on a
|
|
39
|
+
may-train model.
|
|
40
|
+
|
|
41
|
+
## Summary shape
|
|
42
|
+
|
|
43
|
+
- What changed, in one sentence.
|
|
44
|
+
- Which checks ran and their results, verbatim.
|
|
45
|
+
- What was deliberately not done, and why.
|
|
46
|
+
- Anything risky or irreversible.
|
|
47
|
+
|
|
48
|
+
## The publish boundary
|
|
49
|
+
|
|
50
|
+
Publishing is a human action. Do not `git push`, do not open a pull request, do
|
|
51
|
+
not publish a package, do not change repository visibility, even if the task
|
|
52
|
+
seems to imply it. The guard will block `git push` in code, but the boundary
|
|
53
|
+
is yours to hold, not only the hook's.
|
|
54
|
+
|
|
55
|
+
Leave the tree in a state a human can review: on a branch, with the change
|
|
56
|
+
visible in `git diff`.
|
|
57
|
+
|
|
58
|
+
## Do not
|
|
59
|
+
|
|
60
|
+
- Do not declare success over a failing check.
|
|
61
|
+
- Do not squash, rebase, or force-push to tidy history.
|
|
62
|
+
- Do not delete a failing test to make the suite green. A reported failure is
|
|
63
|
+
information; a deleted test is lost information.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: space-plan
|
|
3
|
+
description: Turn a vague request into an executable plan before any code is written. Use when a task is ambiguous, touches several files, or two people could disagree about done.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Plan before building
|
|
7
|
+
|
|
8
|
+
Most wasted agent time is not bad code, it is solving the wrong problem well.
|
|
9
|
+
|
|
10
|
+
## The loop these four skills form
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
space-plan ─one task─▶ space-build ─verify passes─▶ space-review ─pass 1 clean─▶ space-finish ─▶ human
|
|
14
|
+
▲ │
|
|
15
|
+
└──── back to build, on a blocker: the file:line, the requirement
|
|
16
|
+
missed, and the failing output
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The only backwards edge is `space-review → space-build`: a blocker is the loop
|
|
20
|
+
working, not the loop failing, and the only way out of a blocker is to fix the
|
|
21
|
+
thing it names. `space-plan` is never a backwards edge. Each forward edge names
|
|
22
|
+
what it hands over:
|
|
23
|
+
|
|
24
|
+
| From | To | Hands over |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `space-plan` | `space-build` | one task: exact paths, the concrete change, the verify command |
|
|
27
|
+
| `space-build` | `space-review` | the command that ran, and its verbatim output |
|
|
28
|
+
| `space-review` | `space-build` | on a blocker: the `file:line`, the requirement missed, the failing output |
|
|
29
|
+
| `space-review` | `space-finish` | pass 1 clean: the diff as a whole |
|
|
30
|
+
| `space-finish` | human | the summary, the checks, and what was deliberately left undone |
|
|
31
|
+
|
|
32
|
+
**Re-plan only when the request itself was wrong**, not when a task turns out
|
|
33
|
+
harder than estimated. The second case is a build failure and belongs in
|
|
34
|
+
`space-build`.
|
|
35
|
+
|
|
36
|
+
## Write the plan down
|
|
37
|
+
|
|
38
|
+
A plan that only lives in the context gets lost the first time the context is
|
|
39
|
+
pruned, which is exactly the moment the loop needs it. So the plan ends as a
|
|
40
|
+
file, and every later step reads the file instead of the conversation.
|
|
41
|
+
|
|
42
|
+
- Path: `.space/tasks.md` in the project you are planning for.
|
|
43
|
+
- Format: [`reference/task-template.md`](reference/task-template.md) — goal,
|
|
44
|
+
constraints, decisions, risks, and one task per bullet with its files, its
|
|
45
|
+
concrete change, and its verify command.
|
|
46
|
+
- `space-plan` creates it and keeps the Tasks section current. `space-build`
|
|
47
|
+
works from the task in the file. `space-review` diffs against it.
|
|
48
|
+
`space-finish` treats any task still `pending` or `blocked` as unfinished.
|
|
49
|
+
|
|
50
|
+
## When this applies
|
|
51
|
+
|
|
52
|
+
Use it when any of these is true:
|
|
53
|
+
|
|
54
|
+
- The request has no single obvious file to change.
|
|
55
|
+
- Nobody could tell from the diff whether the task was finished.
|
|
56
|
+
- More than one design would satisfy the wording.
|
|
57
|
+
- The task is a feature rather than a fix.
|
|
58
|
+
|
|
59
|
+
Skip it for a single obvious edit. Writing a plan for `fix the typo` is waste.
|
|
60
|
+
|
|
61
|
+
## Steps
|
|
62
|
+
|
|
63
|
+
1. **Read first, but narrowly.** Grep the file names that must be involved,
|
|
64
|
+
then read the functions you need with an offset. A plan built on assumed
|
|
65
|
+
paths is worse than no plan: it reads as confident and sends the build step
|
|
66
|
+
to the wrong place. Reading whole files to check whether a function exists is
|
|
67
|
+
not orientation, it is 20x the context.
|
|
68
|
+
2. **State the goal in one sentence, in the caller's words.** If you cannot,
|
|
69
|
+
you do not understand the request yet. Ask **one** specific question, and only
|
|
70
|
+
when a wrong guess would cost money, break the build irreversibly, publish
|
|
71
|
+
something, or be irreversible. Everything else you decide yourself.
|
|
72
|
+
3. **List the constraints.** What must not change. What is out of scope. What
|
|
73
|
+
already exists that must keep working.
|
|
74
|
+
4. **Break it into tasks that fit in a few minutes each.** For every task:
|
|
75
|
+
- exact file paths
|
|
76
|
+
- the concrete change, not "handle errors"
|
|
77
|
+
- the verify command, and what passing looks like
|
|
78
|
+
5. **Order so the repository stays working.** Every step should leave the tests
|
|
79
|
+
green. A plan whose middle step is red is a plan that gets abandoned.
|
|
80
|
+
6. **Name the risks** and the cheapest way to find out early.
|
|
81
|
+
7. **Write it to `.space/tasks.md`** using `reference/task-template.md`, then
|
|
82
|
+
hand that file over with the plan summary.
|
|
83
|
+
|
|
84
|
+
## What to hand off
|
|
85
|
+
|
|
86
|
+
The `.space/tasks.md` file, plus a summary a reviewer can read in one screen:
|
|
87
|
+
the goal sentence, the decisions you made rather than asked about, and the risks.
|
|
88
|
+
Then let the agent that runs the plan load the `space-build` skill for one task at
|
|
89
|
+
a time and `space-review` after the set. Use the `locate` agent to close gaps in
|
|
90
|
+
your evidence first: it is read-only, and a gap closed before the plan is written
|
|
91
|
+
costs a fraction of a gap found during the build.
|
|
92
|
+
|
|
93
|
+
Do not batch the builds. One task at a time is what keeps the verify command
|
|
94
|
+
attributable to a change.
|
|
95
|
+
|
|
96
|
+
## Failure modes
|
|
97
|
+
|
|
98
|
+
- Planning from the request alone, without reading code. This is the main one.
|
|
99
|
+
- Tasks sized "and then the rest". They cannot be verified, so they are not tasks.
|
|
100
|
+
- A plan that requires a decision you cannot make. That is a question, and it
|
|
101
|
+
belongs at the top, not buried in task 6.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Task contract: `.space/tasks.md`
|
|
2
|
+
|
|
3
|
+
`space-plan` writes this file into the project it is planning for. It is the
|
|
4
|
+
one artifact the whole loop reads, so it has to survive a session whose context
|
|
5
|
+
has been pruned. Never keep it in your head.
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
8
|
+
# <goal, one sentence, in the caller's words>
|
|
9
|
+
|
|
10
|
+
## Constraints
|
|
11
|
+
- <what must not change, what must not be touched>
|
|
12
|
+
|
|
13
|
+
## Decisions
|
|
14
|
+
- <date> <decision, one line> — <why; links to plan/summary if there is one>
|
|
15
|
+
|
|
16
|
+
## Risks
|
|
17
|
+
- <the thing most likely to go wrong, and the cheapest way to find out early>
|
|
18
|
+
|
|
19
|
+
## Tasks
|
|
20
|
+
- [ ] <task, small enough to finish in a few minutes>
|
|
21
|
+
- files: <exact paths to change>
|
|
22
|
+
- change: <what the change is, concretely, not "handle errors">
|
|
23
|
+
- verify: <the exact command, and what passing looks like>
|
|
24
|
+
- status: pending | done | blocked
|
|
25
|
+
- [x] <finished task>
|
|
26
|
+
- files: <paths>
|
|
27
|
+
- change: <what was done, including anything the original task did not name>
|
|
28
|
+
- verify: <the command that was actually run, and its verbatim final lines>
|
|
29
|
+
- status: done
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
How the loop uses it:
|
|
33
|
+
|
|
34
|
+
| step | does |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `space-plan` | creates and rewrites the Tasks section; records Decisions and Risks |
|
|
37
|
+
| `space-build` | reads the task, writes only what it names, marks it done with the real verify output |
|
|
38
|
+
| `space-review` | reads the Tasks section as the requirement, diffs against it in pass 1 |
|
|
39
|
+
| `space-finish` | treats any `pending` or `blocked` task as "not finished", and asks for the summary decision |
|
|
40
|
+
|
|
41
|
+
Rules:
|
|
42
|
+
|
|
43
|
+
- One file per body of work. Start a new one only when the goal changes.
|
|
44
|
+
- A task is `done` only with the verify command's real output pasted into its
|
|
45
|
+
`verify:` line. A task marked done without it has not been verified.
|
|
46
|
+
- Add a Decisions line the moment something was chosen rather than asked. That
|
|
47
|
+
is the line that stops the next session re-litigating it.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: space-review
|
|
3
|
+
description: Review a change in two passes, spec compliance then code quality, without editing. Use before committing or deciding a task is done.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Review in two passes
|
|
7
|
+
|
|
8
|
+
The order matters. Quality opinions on a change that does the wrong thing are
|
|
9
|
+
noise, and they bury the finding that mattered.
|
|
10
|
+
|
|
11
|
+
## Pass 1 - does it do what was asked
|
|
12
|
+
|
|
13
|
+
Style is out of scope. Only the question of whether the task got done. The
|
|
14
|
+
requirement is the Tasks section of `.space/tasks.md`, in the format
|
|
15
|
+
`space-plan` wrote — not the conversation, and not your guess at the
|
|
16
|
+
intent. If there is no file, there is no requirement to review against: say
|
|
17
|
+
so and stop.
|
|
18
|
+
|
|
19
|
+
- Every requirement in the task met? Name the ones that are not, with
|
|
20
|
+
`file:line`.
|
|
21
|
+
- Anything in the diff the task did not ask for?
|
|
22
|
+
- Does the verify command the task named exist, and does it pass?
|
|
23
|
+
- Any file described as changed that is not actually in the diff?
|
|
24
|
+
|
|
25
|
+
Any failure here is a **blocker**. Report it and hand it back to `space-build`
|
|
26
|
+
with the location and the verify output that shows it. A review that stops
|
|
27
|
+
without naming where to go next is a half result: the task is still open and
|
|
28
|
+
now has an extra person who knows it is.
|
|
29
|
+
|
|
30
|
+
## Pass 2 - is it any good
|
|
31
|
+
|
|
32
|
+
Only if pass 1 was clean.
|
|
33
|
+
|
|
34
|
+
- Duplication that will cost something on the next change
|
|
35
|
+
- Error paths that swallow the reason a thing failed
|
|
36
|
+
- Edge cases the tests do not cover, named specifically rather than gestured at
|
|
37
|
+
- Names that do not match what they hold
|
|
38
|
+
- Dead code, debug leftovers, commented-out blocks
|
|
39
|
+
|
|
40
|
+
## Rules
|
|
41
|
+
|
|
42
|
+
- Every finding needs a location and a consequence. "This could be clearer" is
|
|
43
|
+
not a finding. "If the API returns a list, this takes the first element and
|
|
44
|
+
silently drops the rest" is.
|
|
45
|
+
- Severity is real: `blocker`, `should-fix`, `nit`. Do not inflate to look
|
|
46
|
+
thorough.
|
|
47
|
+
- Propose the smallest change that removes the defect. Not a rewrite.
|
|
48
|
+
- **Silence is a valid result.** Say the diff is clean. Inventing findings to
|
|
49
|
+
fill a review costs the author more than an empty review.
|
|
50
|
+
|
|
51
|
+
## Report
|
|
52
|
+
|
|
53
|
+
Two sections. If pass 1 blocked, one section plus the reason.
|