@sorenllm/opencode-forge 0.1.0 → 0.2.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.
Files changed (3) hide show
  1. package/README.md +110 -17
  2. package/dist/index.js +1182 -27
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # opencode-forge
2
2
 
3
- Single general-purpose **forge** agent + a plan harness for
4
- [opencode](https://opencode.ai) ≥ 1.18. Plans become first-class files on
5
- disk with tool-enforced structure, a hard write-ban while planning, user
6
- confirmation gates for approve/close, and tick-as-you-go task tracking.
3
+ Single general-purpose **forge** agent + two orthogonal harnesses for
4
+ [opencode](https://opencode.ai) ≥ 1.18: a **plan harness** (decide first,
5
+ execute later) and a **goal harness** (arm an objective, let the loop drive
6
+ itself to a host-verified finish). They share nothing but a safety interop;
7
+ OpenSpec spec workflows remain a third, separate lane.
7
8
 
8
9
  ```
9
10
  /plan fix login timeout → read-only recon → plan_write (draft, writes denied)
@@ -16,6 +17,18 @@ confirmation gates for approve/close, and tick-as-you-go task tracking.
16
17
  /plan discard → abandon the current plan (abandoned, writes restored)
17
18
  ```
18
19
 
20
+ ```
21
+ /goal make the suite green --check "npm test" --contains "src/a.ts::export const A"
22
+ → goal_write (arm=true; the user dialog IS the arm action)
23
+ → loop: work → goal_check (advisory) → idle → continuation brief
24
+ → goal_complete re-runs EVERY check itself on the host
25
+ (fail-closed) + per-criterion attestations → user dialog
26
+ = completion gate → completed
27
+ /goal add ... → queue an inert goal (no dialog, no loop)
28
+ /goal → live goal + queue overview
29
+ /goal pause | resume | discard/stop/cancel
30
+ ```
31
+
19
32
  - Plan files: `.opencode/plan/<date>-<slug>.md` in your project, frontmatter
20
33
  state machine `draft → approved → done` (exit: `abandoned`).
21
34
  - While a plan is in draft, `write` / `edit` / `bash` / `task` are **denied
@@ -23,9 +36,14 @@ confirmation gates for approve/close, and tick-as-you-go task tracking.
23
36
  exits are approval and discard. This is deliberate; see Design stance.
24
37
  - `plan_approve` / `plan_close` are pinned to a confirmation dialog: the
25
38
  model can never flip the state itself.
39
+ - Goal files: `.opencode/goal/<date>-<slug>.md`, state machine
40
+ `queued → active ⇄ paused → completed / abandoned`, one live goal per
41
+ session plus a workspace queue. Completion is **verified by the plugin**,
42
+ not attested by the model: `goal_complete` re-executes every check itself
43
+ and refuses (fail-closed) on any failure.
26
44
  - The native `build` / `plan` agents are hidden while the plugin is loaded
27
45
  (runtime injection, nothing written to your config). Uninstall restores
28
- them automatically; plan files are never deleted.
46
+ them automatically; plan and goal files are never deleted.
29
47
 
30
48
  ## Install
31
49
 
@@ -65,22 +83,22 @@ the plugin never writes them):
65
83
  }
66
84
  ```
67
85
 
68
- If you already have a `command.plan` of your own, it wins and the plugin's
69
- `/plan` is not registered.
86
+ If you already have a `command.plan` or `command.goal` of your own, it wins
87
+ and the plugin's command of that name is not registered.
70
88
 
71
89
  ## Uninstall (four steps, restores native opencode)
72
90
 
73
91
  1. Remove the plugin entry from the `plugin` array in
74
92
  `~/.config/opencode/opencode.json` (global installs).
75
93
  2. Delete the package store dir:
76
- `~/.cache/opencode/packages/github_ChengZiiii/opencode-forge/` (github
77
- installs, owner/repo layout; for npm installs it is
78
- `~/.cache/opencode/packages/opencode-forge/`).
94
+ `~/.cache/opencode/packages/@sorenllm/opencode-forge/` (npm installs,
95
+ scope-dir layout; for github installs it is
96
+ `~/.cache/opencode/packages/github_ChengZiiii/opencode-forge/`).
79
97
  3. Delete the `agent["forge"]` block from your config if you added one
80
98
  (otherwise the name lingers in the agent list).
81
99
  4. Done — the hidden native `build`/`plan` agents come back automatically
82
- (the hide was runtime-only). Your `.opencode/plan/` files are yours;
83
- delete them yourself if you want.
100
+ (the hide was runtime-only). Your `.opencode/plan/` and `.opencode/goal/`
101
+ files are yours; delete them yourself if you want.
84
102
 
85
103
  ## File ledger
86
104
 
@@ -89,11 +107,84 @@ What this plugin touches, exhaustively:
89
107
  | Where | What | Lifetime |
90
108
  | --- | --- | --- |
91
109
  | `<project>/.opencode/plan/*.md` | plan files | user data — kept forever, uninstall never deletes |
92
- | merged config object (RAM only) | forge agent, native build/plan `disable`, `skills.paths` entry, `command.plan` | vanishes when the plugin is removed; nothing is written to disk |
110
+ | `<project>/.opencode/goal/*.md` | goal files (contract, Check Log, Turn Ledger) | user data — kept forever, uninstall never deletes |
111
+ | merged config object (RAM only) | forge agent, native build/plan `disable`, `skills.paths` entry, `command.plan`, `command.goal`, goal permission keys | vanishes when the plugin is removed; nothing is written to disk |
93
112
  | `~/.cache/opencode/packages/...` | installed package copy | written by the `opencode plugin` installer, not the plugin |
94
113
  | `~/.config/opencode/opencode.json` | `plugin` array entry | written by the installer |
95
114
 
96
- The plugin writes no temp files, no logs, nothing outside the table.
115
+ The plugin writes no temp files, no logs, nothing outside the table (a
116
+ `FORGE_GOAL_PROBE=1` env opt-in appends continuation diagnostics to the OS
117
+ temp dir for debugging).
118
+
119
+ ## Goal mode (autonomous, host-verified objectives)
120
+
121
+ Three orthogonal workflows — pick per task, they never bind to each other:
122
+
123
+ | Workflow | decides | use when |
124
+ | --- | --- | --- |
125
+ | OpenSpec change | spec deltas, review gates | multi-session features with spec impact |
126
+ | `/plan` | approach + task order, you approve then it executes | single-task execution you want to review first |
127
+ | `/goal` | arm an objective + verification contract, the loop executes | well-defined objective with machine-checkable success |
128
+
129
+ `/goal <objective>` drafts a **contract**: goal, success criteria,
130
+ verification checks, constraints, non-goals, budgets. Contract markers in the
131
+ objective map to structured fields:
132
+
133
+ ```
134
+ /goal make the release green --check "npm test" --check "npm run lint"
135
+ --contains "CHANGELOG.md::## Unreleased"
136
+ --success "zero failing tests" --constraint "no dependency bumps"
137
+ --non-goal "refactoring" --max-turns 15 --max-minutes 30
138
+ ```
139
+
140
+ Two check types, both **executed by the plugin on the host** (the model never
141
+ grades its own homework):
142
+
143
+ - `--check "cmd"` — shell command in the workspace; passes on exit 0,
144
+ timeout-configurable (default 120 s, max 600 s).
145
+ - `--contains "file::text"` — file contract: the literal text must be present
146
+ in that workspace file.
147
+
148
+ **Arming and the loop.** `goal_write` with `arm=true` pops one confirmation
149
+ dialog — your Allow IS the arm action; nothing autonomous runs before it.
150
+ From then on, whenever the session goes idle, the plugin re-prompts the agent
151
+ with a `[forge:goal-continue]` brief (with debounce, owner-checked, and
152
+ compaction-aware: autocontinue is suppressed for active-goal sessions so a
153
+ context compaction can never silently re-trigger the loop). Each continuation
154
+ turn is counted and recorded in the goal's Turn Ledger.
155
+
156
+ **Budgets and auto-pause.** `--max-turns` (default 25, hard ceiling 200) and
157
+ `--max-minutes` (default 60, hard ceiling 480). The loop pauses itself — with
158
+ a `stop_reason` in the frontmatter — on: budget exhaustion, two consecutive
159
+ no-progress continuation turns, three consecutive transport failures, or a
160
+ live draft plan appearing in the session (the only plan/goal interop: a draft
161
+ plan's write ban would wall the loop off, so the goal pauses instead of
162
+ burning turns against it). `/goal pause` (or `goal_pause` with a blocker
163
+ description) pauses by hand; `/goal resume` re-arms through another
164
+ confirmation dialog.
165
+
166
+ **Completion is fail-closed.** `goal_complete` re-executes every check itself
167
+ at the gate — results recorded in the Check Log never substitute for the
168
+ re-run — and requires one attestation per success criterion. Only then does
169
+ the user dialog appear. Revising the contract (`goal_write` with
170
+ `revise=true`) bumps the revision: earlier evidence no longer counts, but the
171
+ Check Log and Turn Ledger survive as an audit trail.
172
+
173
+ **Queueing.** One live goal per session; `/goal add ...` queues additional
174
+ goals (inert, no dialog). When the live goal reaches a terminal state,
175
+ `/goal resume` promotes the oldest queued goal into the now-free session.
176
+
177
+ **Run-mode limitation.** `opencode run` exits before the idle continuation
178
+ debounce fires, so the autonomous loop effectively requires a TUI/serve
179
+ session. Arming, checks, completion, pause/resume, and queueing all work in
180
+ run mode; `--auto` approves the gates, without it they auto-reject
181
+ (headless cannot silently pass a gate).
182
+
183
+ **Security boundary.** Verification shell commands run on your host, in the
184
+ workspace, via the plugin — that is the point (host-verified completion).
185
+ They are drafted by the model from your objective. Read them in the dialog
186
+ before allowing the arm; `--contains` contracts are strictly
187
+ workspace-relative (path escape is refused).
97
188
 
98
189
  ## Design stance (read before filing "bash is blocked" issues)
99
190
 
@@ -117,9 +208,11 @@ bun run bundle # rebuild self-contained dist/index.js (committed)
117
208
  ```
118
209
 
119
210
  Architecture: `plugin.ts` (dual entry — v1 `server` full-featured + v2
120
- `setup` defensive forward-compat) + `src/plan-file.ts` (pure plan document
121
- core, unit-tested, no opencode imports) + `SKILL.md` (planning discipline,
122
- discovered via `config.skills.paths`). Behavioral changes go through the
211
+ `setup` defensive forward-compat) + `src/plan-file.ts` / `src/goal-file.ts`
212
+ (pure document cores, unit-tested, no opencode imports) + `src/run-check.ts`
213
+ (shell/file-contract runner with tree-kill timeouts and a workspace path
214
+ guard) + `SKILL.md` (planning discipline, discovered via
215
+ `config.skills.paths`). Behavioral changes go through the
123
216
  OpenSpec workflow in `openspec/` — see AGENTS.md. Common pitfalls live in
124
217
  `../opencode-plugin-dev-pitfalls.md`.
125
218