opendoor-plugin 0.2.0 → 0.5.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 +222 -243
- package/dist/browser/pi-web-plugin.js +2121 -1452
- package/dist/package.json +6 -29
- package/dist/pi-extension/index.js +136 -0
- package/dist/server-plugin.js +54 -21
- package/package.json +19 -10
package/README.md
CHANGED
|
@@ -1,300 +1,279 @@
|
|
|
1
1
|
# opendoor — a Doorstop requirements-management plugin for PI WEB
|
|
2
2
|
|
|
3
|
-
`opendoor` is a
|
|
4
|
-
[Doorstop](https://github.com/doorstop-dev/doorstop) requirements stored in
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
falls back to the workspace terminal. The paired backend also recovers the
|
|
13
|
-
reviewed version of an item file from git history, so the item detail pane
|
|
14
|
-
can show a **Changes since review** diff — and Review can optionally record
|
|
15
|
-
a pathspec-limited review commit (`commitAfterReview`).
|
|
3
|
+
`opendoor` is a PI WEB plugin that surfaces
|
|
4
|
+
[Doorstop](https://github.com/doorstop-dev/doorstop) requirements stored in the
|
|
5
|
+
workspace in a **Requirements** workspace tab with
|
|
6
|
+
the document tree, per-item state (reviewed/unreviewed changes, suspect links),
|
|
7
|
+
validation findings and `doorstop` actions, plus agent prompts
|
|
8
|
+
that insert requirement context into the session.
|
|
9
|
+
The paired backend also recovers an item file's reviewed version from git for
|
|
10
|
+
the **Changes since review** diff, and Review can opt in to a review commit
|
|
11
|
+
(`commitAfterReview`).
|
|
16
12
|
|
|
17
13
|
Full feature spec: [`docs/feature-doorstop-plugin.md`](docs/feature-doorstop-plugin.md)
|
|
18
14
|
(§5 architecture, §6 requirements state model, §7–§8 UI/actions).
|
|
19
15
|
|
|
20
16
|
## Status
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
section fetches via `context.backend.request("doorstop.item-baseline", …)`)
|
|
67
|
-
and the captured output appears in the panel's status bar (auto-expanded);
|
|
68
|
-
the panel auto-rescans on completion. When the backend is absent (unpaired
|
|
69
|
-
install, or a workspace the provider does not own), the action falls back to
|
|
70
|
-
`terminal.runCommand()` with the same shell command, so output stays visible
|
|
71
|
-
and auditable in the terminal.
|
|
72
|
-
|
|
73
|
-
`doorstop.run` and `doorstop.item-baseline`) shared by both halves, plus the
|
|
74
|
-
four git-action contracts (`doorstop.git-status`, `doorstop.git-stage`,
|
|
75
|
-
`doorstop.git-unstage`, `doorstop.git-commit`), live in
|
|
76
|
-
`src/doorstop-backend-contract.ts`. Later modules import these and must not
|
|
77
|
-
redefine them.
|
|
18
|
+
Requires **pi-web 1.202611.1 or newer** (browser and server plugin API v5).
|
|
19
|
+
|
|
20
|
+
One package (`opendoor-plugin`) ships the PI WEB plugin (both entries below)
|
|
21
|
+
and the Pi extension (`/opendoor-review`).
|
|
22
|
+
|
|
23
|
+
- **Browser entry** (`src/browser/pi-web-plugin.ts`, apiVersion 5, name
|
|
24
|
+
`Opendoor`) delegates to `createOpendoorBrowserContributions`
|
|
25
|
+
(`src/browser/doorstop-contributions.ts`): the **panel** `workspace.doorstop`
|
|
26
|
+
(title **Requirements**, order 5 — below the Files panel's order 10 so doorstop
|
|
27
|
+
item links reach its `fileOpenQuery` first, at the cost of the Requirements tab
|
|
28
|
+
preceding Files in the tab order; controller registry in
|
|
29
|
+
`src/browser/doorstop-panel.ts`, sections in **Using the panel**),
|
|
30
|
+
the **actions** `view.doorstop` (mod+7) and `workspace.refresh-doorstop`
|
|
31
|
+
(mod+shift+d), the **label** `doorstop-status` (requirement-health counts,
|
|
32
|
+
feature spec §7.4), and the **session-row label** `doorstop.review` (reopens the
|
|
33
|
+
Requirements tab from a row carrying public `opendoor` metadata, archived rows
|
|
34
|
+
included — feature spec, **Session metadata and session-list row labels**).
|
|
35
|
+
- **Server entry** (`src/server-plugin.ts`, apiVersion 5, default export
|
|
36
|
+
`PiWebServerPlugin`) contributes a workspace provider for projects whose root
|
|
37
|
+
has a `.doorstop.yml` (cheap `fs.access` probe; everything else stays with the
|
|
38
|
+
bundled Git provider) and serves six operations: `doorstop.run` (one CLI
|
|
39
|
+
invocation; a review carrying the opt-in `commit: true` flag is followed by a
|
|
40
|
+
pathspec-limited `doorstop: review <uid>` commit), the read-only
|
|
41
|
+
`doorstop.item-baseline` (the reviewed version, from git history), and
|
|
42
|
+
`doorstop.git-status` / `-stage` / `-unstage` / `-commit` (see **Git
|
|
43
|
+
actions**). `src/doorstop-backend.ts` validates each request, builds argv
|
|
44
|
+
server-side (never a browser shell string) and runs it via `execFile()`; see
|
|
45
|
+
its header for timeouts and per-workspace serialization. The entry declares no
|
|
46
|
+
`requires` and no `start()`: the retired `doorstop.ask-agent` dispatch could
|
|
47
|
+
not live there (provider-cycle rule) — see `src/server-plugin.ts`.
|
|
48
|
+
- **Pi extension** (`src/pi-extension/opendoor-review.ts`, bundled to
|
|
49
|
+
`dist/pi-extension/index.js`, declared by `pi.extensions`) registers
|
|
50
|
+
`/opendoor-review <UID> [instruction…]`: it publishes the public `opendoor`
|
|
51
|
+
metadata (`{ schema: 1, op: "review", uids }`) and asks PI WEB's per-session
|
|
52
|
+
dispatch bridge to start an independent conversation in the same project (the
|
|
53
|
+
`spawn_session` rules, model/thinking inherited), reporting every outcome in
|
|
54
|
+
the initiating conversation — the pathway **Start review session** drives.
|
|
55
|
+
|
|
56
|
+
Dispatch (`src/browser/doorstop-panel-element.ts`) uses
|
|
57
|
+
`context.peer.request("doorstop.run", …)` (the review-commit flag rides along
|
|
58
|
+
when enabled; **Changes since review** uses `doorstop.item-baseline`) with the
|
|
59
|
+
output in the auto-expanded status bar, or falls back to `terminal.runCommand()`
|
|
60
|
+
with the same shell command when unpaired. Shared types and operation contracts
|
|
61
|
+
live in `src/doorstop-contract.ts` and `src/doorstop-backend-contract.ts`.
|
|
78
62
|
|
|
79
63
|
## Workspace settings (`.pi-web/opendoor.json`)
|
|
80
64
|
|
|
81
|
-
Optional per-workspace configuration, read
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
bundled workspace-tasks plugin. The *server* entry's host-scoped knobs
|
|
87
|
-
(CLI binary path, exec timeout) are configured through
|
|
88
|
-
`plugins.opendoor.settings` instead — see **Host settings** below:
|
|
65
|
+
Optional per-workspace configuration, read on every plugin load (missing file →
|
|
66
|
+
defaults; malformed or invalid values → warning diagnostics + defaults). pi-web's
|
|
67
|
+
`plugins.<id>.settings` is host-side and reaches only server entries, so this
|
|
68
|
+
file plays the role `.pi-web/tasks.json` plays for the bundled workspace-tasks
|
|
69
|
+
plugin; server-entry knobs are in **Host settings** below:
|
|
89
70
|
|
|
90
71
|
```json
|
|
91
72
|
{
|
|
92
73
|
"version": 1,
|
|
93
74
|
"publish": { "target": "./public" },
|
|
94
75
|
"discovery": { "excludedDirectories": ["published", "vendor"] },
|
|
76
|
+
"showAdditionalAttribute": ["text", "component"],
|
|
95
77
|
"commitAfterReview": false
|
|
96
78
|
}
|
|
97
79
|
```
|
|
98
80
|
|
|
99
|
-
- `publish.target` — path passed to `doorstop publish all
|
|
81
|
+
- `publish.target` — path passed to `doorstop publish all`; must be a safe
|
|
100
82
|
workspace-relative path (no `..`, no absolute, no drive prefix, no leading
|
|
101
|
-
`-`).
|
|
102
|
-
|
|
103
|
-
|
|
83
|
+
`-`). Shell-quoted at the terminal-command boundary when it contains characters
|
|
84
|
+
outside the inert `\w./-` alphabet; on the backend path it is an argv element,
|
|
85
|
+
never a shell string.
|
|
104
86
|
- `discovery.excludedDirectories` — additional directory names the
|
|
105
87
|
`.doorstop.yml` walk never enters (merged with the built-in
|
|
106
88
|
`.git`/`node_modules` skips, max 16 names).
|
|
107
|
-
- `
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
89
|
+
- `showAdditionalAttribute` — attribute NAMES rendered in every item-list row as
|
|
90
|
+
`key: value` (values jsonish-quoted, joined with ` · `, in configured order);
|
|
91
|
+
any extended attribute key works, an attribute an item lacks is skipped, and no
|
|
92
|
+
unconfigured attribute ever appears. The modeled `text` is special-cased: the
|
|
93
|
+
body renders raw and unquoted on an indented second line below the row, clamped
|
|
94
|
+
to two lines with an ellipsis (the full body lives in the detail pane), skipped
|
|
95
|
+
when empty. Default `[]` leaves today's rows unchanged. Invalid entries are
|
|
96
|
+
dropped with a warning each, duplicates deduplicated, capped at 16 names;
|
|
97
|
+
unknown keys simply match nothing.
|
|
98
|
+
- `commitAfterReview` — opt-in boolean (default `false`): on a paired workspace
|
|
99
|
+
the **Review** action's `doorstop review <uid>` is followed by a
|
|
100
|
+
pathspec-limited commit of the item file with the conforming message
|
|
101
|
+
`doorstop: review <uid>` (git `add` then `commit -m … -- <path>`; other
|
|
102
|
+
staged/unstaged work is untouched). Committing user content is strictly opt-in;
|
|
103
|
+
the status bar narrates every outcome (`commit: <sha>` / `clean` (already
|
|
104
|
+
committed) / `skipped` (not a git repository | item file not found | review
|
|
105
|
+
failed | deadline) / `failed` — `<stderr>`); Review is otherwise unchanged.
|
|
117
106
|
|
|
118
107
|
## Host settings (`plugins.opendoor.settings`)
|
|
119
108
|
|
|
120
|
-
Optional, server-side only (
|
|
121
|
-
|
|
109
|
+
Optional, server-side only (needs the paired install and a sessiond restart);
|
|
110
|
+
wrong types fall back to defaults:
|
|
122
111
|
|
|
123
112
|
```json
|
|
124
113
|
{ "doorstopPath": "/opt/venv/bin/doorstop", "gitPath": "git", "timeoutMs": 8000 }
|
|
125
114
|
```
|
|
126
115
|
|
|
127
|
-
- `doorstopPath` — the Doorstop CLI binary
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
- `gitPath` — the git binary
|
|
131
|
-
`doorstop.item-baseline` fetch
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
bounds every git exec of the review→commit pipeline, the baseline fetch,
|
|
139
|
-
and the git actions, which share one deadline budget per callback.
|
|
116
|
+
- `doorstopPath` — the Doorstop CLI binary, default `"doorstop"`, resolved on the
|
|
117
|
+
**sessiond host PATH** (the daemon environment, not your login shell — set it
|
|
118
|
+
when the CLI lives in a venv or is off the service PATH).
|
|
119
|
+
- `gitPath` — the git binary for the review→commit pipeline, the
|
|
120
|
+
`doorstop.item-baseline` fetch and the four git actions. Default `"git"` on the
|
|
121
|
+
**sessiond host PATH** — the same escape hatch as `doorstopPath`.
|
|
122
|
+
- `timeoutMs` — per-run exec timeout in ms. May SHORTEN the 8 500 ms default but
|
|
123
|
+
never exceed it (the host bounds every provider callback at 10 s, so a longer run
|
|
124
|
+
would be killed by pi-web, not by the plugin). It also bounds every git exec of
|
|
125
|
+
the review→commit pipeline, the `doorstop.item-baseline` fetch and the git
|
|
126
|
+
actions: one deadline budget per callback.
|
|
140
127
|
|
|
141
128
|
## Using the panel
|
|
142
129
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
- **
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
`
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
would silently resolve the conflict in the index. On unpaired installs no
|
|
241
|
-
git control is rendered at all; while a run is in flight no minus appears
|
|
242
|
-
and the palette buttons are disabled (the per-row affordance is also
|
|
243
|
-
suppressed when the status file list is truncated, so stale path data is
|
|
244
|
-
never acted on).
|
|
245
|
-
- **Git commit** — a single-line message input plus a **Commit** button,
|
|
246
|
-
served by the `doorstop.git-commit` operation. The commit records **the
|
|
247
|
-
staged index** (`git commit -m <message>` with no pathspec and no
|
|
248
|
-
add) — exactly like the git CLI. Consequences, all intended: unstaged
|
|
249
|
-
WIP is never swept into a commit; files you staged yourself (via the
|
|
250
|
-
git CLI or any other tool) are committed too; the strip's `staged`
|
|
251
|
-
count tells you what a commit will record before you click. Empty or
|
|
252
|
-
whitespace-only messages are rejected client-side (git with an empty
|
|
253
|
-
`-m` would open an editor and hang the exec). Committing with nothing
|
|
254
|
-
staged reports `clean — nothing staged`. Outcomes are narrated in the
|
|
255
|
-
status bar (`staged <n> paths` / `committed <sha>` / `clean — nothing
|
|
256
|
-
to stage` / `clean — nothing staged` / `skipped` / `failed — <stderr
|
|
257
|
-
excerpt>`); a failing pre-commit hook surfaces its stderr in the
|
|
258
|
-
expanded status bar body.
|
|
259
|
-
- **Ask the agent** menu: inserts ready-made prompts (explain, fix suspect
|
|
260
|
-
links, draft child requirement, review readiness) into the session prompt
|
|
261
|
-
editor using the item's paths and state (feature spec §7.3).
|
|
262
|
-
- Fingerprints and the requirement state are recomputed in the browser from
|
|
263
|
-
the YAML files; everything mutating goes through the visible `doorstop`
|
|
264
|
-
CLI — paired, headlessly via the server entry (output captured in the
|
|
265
|
-
panel), or in a workspace terminal when unpaired — plus, opt-in, the
|
|
266
|
-
narrated pathspec-limited review commit (`commitAfterReview`) — so all
|
|
267
|
-
effects stay auditable in git.
|
|
130
|
+
Five vertical sections, top to bottom: `project-actions` (project heading — root
|
|
131
|
+
path, basename shown, full path on hover — the Items/Findings toggle, Refresh, Run
|
|
132
|
+
validation, Publish HTML, and on paired installs the Git strip, Stage all and
|
|
133
|
+
Commit), `item-list` (filters row above rows showing level, UID, excerpt,
|
|
134
|
+
`showAdditionalAttribute` values and state chips), `item-details` (Markdown item
|
|
135
|
+
text, links in/out, references, extended attributes, the Changes diff),
|
|
136
|
+
`item-action-palette` (Review, Clear suspect links, Link, Ask agent — spanning the
|
|
137
|
+
panel at chat-prompt-footer height, with the muted "Select an item…" placeholder,
|
|
138
|
+
hidden in the Findings view) and `status-bar` (see below).
|
|
139
|
+
|
|
140
|
+
- **Items / Findings toggle**: Findings lists plugin-computed findings and
|
|
141
|
+
diagnostics (error > warning > info), and a finding's UID navigates back to the
|
|
142
|
+
item. They are informational — **Run validation** gives the authoritative
|
|
143
|
+
`doorstop` output (paired: status bar; unpaired: terminal).
|
|
144
|
+
- **Status bar** (sized like the center-panel one): after a paired action it shows
|
|
145
|
+
status (ok / failed / killed / error) and duration, and the panel re-scans
|
|
146
|
+
automatically. Captured stdout/stderr *auto-expands* whenever there is something
|
|
147
|
+
to show (output, an error, a review-commit line); a run with nothing to display
|
|
148
|
+
stays collapsed. **Dismiss** clears the run and collapses the bar; the next run
|
|
149
|
+
with output re-expands it. Killed runs keep partial output (prefer the terminal
|
|
150
|
+
for long publishes). With `commitAfterReview` on, the bar adds the `commit: …`
|
|
151
|
+
line from **Workspace settings**; a failed or skipped commit never changes the
|
|
152
|
+
run's ok/failed badge.
|
|
153
|
+
- **State chips** per item (feature spec §6): inactive, non-normative, reviewed /
|
|
154
|
+
unreviewed changes, suspect links, no child links, no links, unknown link,
|
|
155
|
+
missing reference.
|
|
156
|
+
- **Changes since review** (item detail pane, paired installs only): an item with
|
|
157
|
+
unreviewed changes and a stored `reviewed` fingerprint gets a collapsed section;
|
|
158
|
+
expanding it fetches the reviewed item file from git history via
|
|
159
|
+
`doorstop.item-baseline`, stamp-matches it against the fingerprint and renders a
|
|
160
|
+
line diff plus chips for `ref`/`references`/link-UID/extended-attribute changes.
|
|
161
|
+
With no recoverable baseline it says so ("no git history", "could not locate the
|
|
162
|
+
reviewed version — history may have been rewritten"). The `doorstop: review
|
|
163
|
+
<uid>` message is the historical anchor feature spec §12's deferred browser-side
|
|
164
|
+
git parsing could not give; recovery runs server-side.
|
|
165
|
+
- **Item actions** (item-action-palette): Review (`doorstop review UID`, plus the
|
|
166
|
+
review commit when `commitAfterReview` is on), Clear suspect links (`doorstop
|
|
167
|
+
clear UID [parents…]`), Edit (`doorstop edit UID`), Link/Unlink via inline UID
|
|
168
|
+
input (Doorstop UID grammar enforced; shell metacharacters rejected), and on
|
|
169
|
+
paired installs Stage / Unstage for the item's own file (`doorstop.git-stage` /
|
|
170
|
+
`doorstop.git-unstage`; see **Git actions**). Each disables independently: Stage
|
|
171
|
+
without unstaged (`Y`) changes, Unstage with nothing staged (`X`), both mid-run.
|
|
172
|
+
- **Git actions** (paired only; otherwise every git control is hidden and you
|
|
173
|
+
commit manually):
|
|
174
|
+
- **Git status strip** — compact readout above the item list:
|
|
175
|
+
`⎇ <branch> · <n> staged · <n> dirty · ↑<ahead> ↓<behind>` (zero/absent parts
|
|
176
|
+
omitted, `no git` outside a repository, a retry link on fetch errors).
|
|
177
|
+
Refreshes on panel load, after every run (a stage, unstage or commit
|
|
178
|
+
invalidates the cache) and on click; outside a repository the other git
|
|
179
|
+
controls report `skipped`.
|
|
180
|
+
- **Stage all** — stages every Doorstop-managed file (root `.doorstop.yml`, each
|
|
181
|
+
document config, each item file) via `doorstop.git-stage`. Idempotent: a
|
|
182
|
+
second click over an already-staged set reports `clean — nothing to stage`
|
|
183
|
+
instead of a git error (staged deletions are skipped, not fatal). Disabled
|
|
184
|
+
during a run or with no documents in the loaded index, and only as fresh as
|
|
185
|
+
that index — files created after the last **Refresh** are missed until you
|
|
186
|
+
refresh and stage again.
|
|
187
|
+
- **Unstage (per item)** — a staged item file swaps its row's plus for a
|
|
188
|
+
**minus** and enables **Unstage** in the palette, both via
|
|
189
|
+
`doorstop.git-unstage` (`git reset -q -- :(literal)<path>` server-side). A file
|
|
190
|
+
both staged and further modified (`MM`) still shows the minus; the palette then
|
|
191
|
+
offers Stage and Unstage as two independently-disabled buttons. Unstaging
|
|
192
|
+
restores the index entry but never touches the working tree (a staged addition
|
|
193
|
+
returns to `??`, a staged deletion to an unstaged deletion); it is idempotent
|
|
194
|
+
(`clean — nothing to unstage`) and excludes unmerged paths (`UU`, `AA`, `DD`,
|
|
195
|
+
`DU`, `AU`, `UD`, `UA`), where `git reset` would silently resolve the conflict.
|
|
196
|
+
During a run no minus appears and the palette buttons are disabled; the per-row
|
|
197
|
+
affordance is also suppressed when the status file list is truncated, so stale
|
|
198
|
+
path data is never acted on.
|
|
199
|
+
- **Git commit** — a message input plus **Commit**, served by
|
|
200
|
+
`doorstop.git-commit`. It records **the staged index** (`git commit -m
|
|
201
|
+
<message>`, no pathspec, no add), exactly like the git CLI: unstaged WIP is
|
|
202
|
+
never swept in, files you staged yourself are included, and the strip's
|
|
203
|
+
`staged` count shows what a commit will record. Empty or whitespace-only
|
|
204
|
+
messages are rejected client-side (git would open an editor and hang the exec);
|
|
205
|
+
nothing staged reports `clean — nothing staged`. Outcomes are narrated in the
|
|
206
|
+
status bar (`staged <n> paths` / `committed <sha>` / `clean — nothing to stage`
|
|
207
|
+
/ `clean — nothing staged` / `skipped` / `failed — <stderr excerpt>`), including
|
|
208
|
+
a failing pre-commit hook's stderr.
|
|
209
|
+
- **Ask the agent** menu: inserts ready-made prompts (explain, fix suspect links,
|
|
210
|
+
draft child requirement, review readiness) into the session prompt editor from
|
|
211
|
+
the item's paths and state (feature spec §7.3). **Start review session**
|
|
212
|
+
composes `/opendoor-review <UID>` plus the item context there and needs no
|
|
213
|
+
paired backend: the extension starts an independent review conversation whose
|
|
214
|
+
row carries a **`firstUid +n` label** reopening the Requirements tab on that
|
|
215
|
+
workspace (unselected and archived rows included, no live Pi connection needed),
|
|
216
|
+
landing on the item detail pane. After the insert the status bar shows a quiet
|
|
217
|
+
`ok` **review dispatch** run row. Without the extension the inserted text is
|
|
218
|
+
still a self-sufficient review instruction, so the review happens in the current
|
|
219
|
+
conversation; a refused dispatch is reported in the chat by the extension (see
|
|
220
|
+
**Session metadata and session-list row labels** in the feature spec).
|
|
221
|
+
- Fingerprints and requirement state are recomputed in the browser from the YAML
|
|
222
|
+
files; everything mutating goes through the visible `doorstop` CLI — paired,
|
|
223
|
+
headlessly via the server entry, or in a workspace terminal when unpaired —
|
|
224
|
+
plus, opt-in, the narrated review commit (`commitAfterReview`) — so all effects
|
|
225
|
+
stay auditable in git.
|
|
226
|
+
|
|
268
227
|
|
|
269
228
|
## Commands
|
|
270
229
|
|
|
271
230
|
```sh
|
|
272
|
-
npm install
|
|
273
|
-
npm test
|
|
231
|
+
npm install # install dependencies
|
|
232
|
+
npm test # vitest (unit tests under src/**/*.test.ts)
|
|
274
233
|
npm run test:coverage # v8 coverage report
|
|
275
|
-
npm run typecheck
|
|
276
|
-
npm run build
|
|
277
|
-
|
|
278
|
-
npm run dev
|
|
234
|
+
npm run typecheck # tsc --noEmit (strict)
|
|
235
|
+
npm run build # esbuild → dist/browser, dist/server, dist/pi-extension
|
|
236
|
+
# + the dist-root manifest (see the build script header)
|
|
237
|
+
npm run dev # watch build
|
|
279
238
|
```
|
|
280
239
|
|
|
281
240
|
## Installing the plugin locally (id `opendoor`)
|
|
282
241
|
|
|
242
|
+
The package carries two independently enabled halves: the **PI WEB plugin**
|
|
243
|
+
(browser + server entries) and the **Pi extension** (`/opendoor-review`). The
|
|
244
|
+
repository-root `package.json` is the npm-package-root manifest, so both halves
|
|
245
|
+
come from ONE install through **Settings → Pi packages** (npm name, git/URL or a
|
|
246
|
+
local source); the `ln -s dist` route below remains for plugin-only development.
|
|
247
|
+
|
|
248
|
+
### PI WEB plugin (browser + server entries)
|
|
249
|
+
|
|
250
|
+
Install the package once — **Settings → Pi packages** with source
|
|
251
|
+
`opendoor-plugin` (or this repository's path / git URL) — then enable
|
|
252
|
+
**Opendoor** under **Settings → PI WEB plugins**. Plugin-only local build:
|
|
253
|
+
|
|
283
254
|
```sh
|
|
284
255
|
npm run build
|
|
285
256
|
ln -s "$(pwd)/dist" ~/.pi-web/plugins/opendoor
|
|
286
257
|
```
|
|
287
258
|
|
|
288
259
|
Then **restart the session daemon** (server entries load at sessiond startup
|
|
289
|
-
only; the browser bundle hot-reloads on page reload) and reload the
|
|
290
|
-
page:
|
|
260
|
+
only; the browser bundle hot-reloads on page reload) and reload the page:
|
|
291
261
|
|
|
292
262
|
```sh
|
|
293
263
|
systemctl --user restart pi-web-sessiond.service
|
|
294
264
|
curl -s http://127.0.0.1:8504/pi-web-plugins/manifest.json
|
|
295
265
|
```
|
|
296
266
|
|
|
297
|
-
The manifest should list an `opendoor`
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
267
|
+
The manifest should list an `opendoor` entry **with a `backendRevision`** (signing
|
|
268
|
+
the paired server module); if it is missing, the server module failed to load
|
|
269
|
+
(check the sessiond log) and the plugin works fully via the terminal fallback.
|
|
270
|
+
|
|
271
|
+
### Review dispatch (Pi extension)
|
|
272
|
+
|
|
273
|
+
Installing the package loads the extension; enabling the PI WEB plugin is a
|
|
274
|
+
separate decision. After installing or updating the package, run `/reload` in
|
|
275
|
+
each idle conversation so `/opendoor-review` is registered there (an ordinary
|
|
276
|
+
Pi-resource change — no provider restart). The extension needs PI WEB's
|
|
277
|
+
session-dispatch bridge (1.202610.x); on an older host it reports "requires PI
|
|
278
|
+
WEB's session dispatch bridge" and starts nothing.
|
|
279
|
+
|