Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ and this project attempts to adhere to [Semantic Versioning](https://semver.org/

## [Unreleased]

## [1.1.0-beta.4]

### Changed

- Keep all 29 workflow commands compact through durable static message instructions and existing primary/compaction hooks, preserving native inputs, command purposes/resources and bounded authority. Read legacy sync v1 snapshots, retain diagnostics presentation and preserve active workflow outcome/inputs/modes/authority in summary guidance.

## [1.1.0-beta.3]

### Fixed
Expand Down Expand Up @@ -347,7 +353,8 @@ Documentation-only release; the plugin code is unchanged from 1.0.0. It updates

- Josh Thomas <josh@joshthomas.dev> (maintainer)

[unreleased]: https://github.com/snarkipus/opencode-beads/compare/v1.1.0-beta.3...HEAD
[unreleased]: https://github.com/snarkipus/opencode-beads/compare/v1.1.0-beta.4...HEAD
[1.1.0-beta.4]: https://github.com/snarkipus/opencode-beads/releases/tag/v1.1.0-beta.4
[1.1.0-beta.3]: https://github.com/snarkipus/opencode-beads/releases/tag/v1.1.0-beta.3
[1.1.0-beta.2]: https://github.com/snarkipus/opencode-beads/releases/tag/v1.1.0-beta.2
[1.0.2]: https://github.com/snarkipus/opencode-beads/releases/tag/v1.0.2
Expand Down
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

This is an independent project maintained by Matt Jackson under the MIT license. It began as a fork of [Josh Thomas's `opencode-beads`](https://github.com/joshuadavidthomas/opencode-beads), and the original work remains credited to its author. 1.0 rebuilt the plugin for OpenCode 2, and development now continues here independently. It vendors nothing from upstream Beads; instead, every Beads release is checked against the `bd` behavior the plugin relies on (see [Tracking upstream Beads](#tracking-upstream-beads)).

This release is **1.1.0-beta.3**, an opt-in beta targeting npm dist-tag `next`; its integration diagnostic command is `oc-beads:diagnostics`. Beta.1 used `oc-beads:status`; the rename is documented below. The beta's normal public entrypoint enables the eleven qualified operations in the native `beads` code-mode namespace on supported hosts: find, get, edges, memories, recall, claim, note, selected-field update, close, create and remember. No wrapper, internal dependency injection, manual skill copy or activation setting is needed. The opt-in is selecting the beta artifact. The published stable 1.0.2 package is unchanged.
This release is **1.1.0-beta.4**, an opt-in beta targeting npm dist-tag `next`; its integration diagnostic command is `oc-beads:diagnostics`. Beta.1 used `oc-beads:status`; the rename is documented below. The beta's normal public entrypoint enables the eleven qualified operations in the native `beads` code-mode namespace on supported hosts: find, get, edges, memories, recall, claim, note, selected-field update, close, create and remember. No wrapper, internal dependency injection, manual skill copy or activation setting is needed. The opt-in is selecting the beta artifact. The published stable 1.0.2 package is unchanged.

The beta registers 29 `oc-beads:<stem>` workflows plus `oc-beads:diagnostics` through ordinary native command registration and owns its packaged `oc-beads` skill at the installed path, with all 15 corpus resources plus CODE_MODE and ADR (17 links). User configuration/file commands retain native precedence on load and rebuild; removing an override restores the package definition. Other plugin conflicts follow native ordering. Diagnostics reports observed registration and name/description mismatches; identical-description overrides and public owner identity remain unobservable.

Expand Down Expand Up @@ -45,7 +45,7 @@ The beta requires OpenCode `>=2.1.1 <2.2` and `bd` 1.3.1 or later. Exact OpenCod

```json
{
"plugins": ["@snarkipus/opencode-beads@1.1.0-beta.3"]
"plugins": ["@snarkipus/opencode-beads@1.1.0-beta.4"]
}
```

Expand All @@ -63,7 +63,7 @@ Plugin options use the object form:
{
"plugins": [
{
"package": "@snarkipus/opencode-beads@1.1.0-beta.3",
"package": "@snarkipus/opencode-beads@1.1.0-beta.4",
"options": { "luna": true, "autoMigrate": false }
}
]
Expand Down Expand Up @@ -131,6 +131,18 @@ explicit modes and parent acceptance still apply. Guide/report commands produce
their advertised artifact. This action-contract correction starts with beta.3;
earlier beta artifacts do not contain this correction.

Beta.4 keeps all 29 `/oc-beads:<workflow>` invocations compact, with
single-line free text inline and multiline text below, preserving whitespace.
Full static instructions live in durable `ocBeadsWorkflow` message metadata,
expanded by existing primary and compaction hooks; retained `ocBeadsSync` v1
history remains readable. Attachments/skills, prompt hooks and native delivery
remain normal inputs. Diagnostics retains its observed-report presentation.
Plugin activation is required for expansion; summaries retain semantic context,
not guaranteed verbatim snapshots. Native storage/estimates can include copies or
miss hidden text; this is not a token-savings claim. See the
[workflow evaluation](docs/workflow-native-context-evaluation.md) and original
[sync design](docs/sync-native-context-plan.md) / [evaluation](docs/sync-native-context-evaluation.md).

Starting with beta.2, the package-owned `oc-beads:status` is removed without an alias. Use `oc-beads:diagnostics` for integration health and `oc-beads:stats` for the issue-database overview via `bd status` (alias `bd stats`). User-defined old status overrides are untouched and are not migrated; the package does not edit configuration.

`oc-beads:compact` guides semantic issue compaction with `bd admin compact`; `bd compact` squashes Dolt history and is a different operation. Neither is conversation compaction. A bare invocation explains the workflow; a sufficiently specified semantic apply request supplies its bounded authority under actual permissions and policy. See the packaged [compact guidance](assets/oc-beads/resources/TROUBLESHOOTING.md) for mode/actor boundaries and upstream help uncertainty. `oc-beads:restore` retrieves pre-compaction issue content, displaying it by default; `--apply` requires explicit authority to write it back and does not mean database backup recovery. Quickstart uses installed help and authorized context; sync guides Dolt-remote synchronization, distinct from `bd federation sync`.
Expand Down
70 changes: 70 additions & 0 deletions docs/reviews/opus-sync-context-source-bbd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Source/evidence verdict: READY for opencode-beads-9ux (16-path candidate)

This review (opencode-beads-bbd) found no material Spec/Behavior or Standards/Proportionality findings. The candidate matches the corrected plan's scope. The retained evidence supports accepting it as a bounded walking skeleton. I did not re-run anything; this rests on reading the source plus the retained artifacts.

## Spec/Behavior

No material findings. The contract points check out against source:

- **One compact native prompt.**
- Sync stores `/oc-beads:sync` plus `Literal user details:` when details are present, with a versioned snapshot in `metadata.ocBeadsSync` (candidate.diff:176-186).
- `...input.prompt` still passes files, agents and skills through unchanged.
- Overwriting `metadata` loses nothing from the invocation. `CommandInvocation.prompt` is `PromptInput.Prompt`, which has only text/files/agents/skills (schema `prompt.js:46-51`). Admission metadata is a separate field (`promise/session.d.ts:17`).
- The snapshot is the beta.3 instruction text exactly, digest-pinned at host.test:313. The other 29 commands still go through the shared `instructions + details` path (candidate.diff:186), and all 29 are digest-checked against generated baseline values (workflows.test:445-454).
- **Expansion helper** (`expandBeadsSyncContext`, candidate.diff:152-166).
- It replaces array entries rather than mutating the stored message, and acts only on user-role messages whose metadata is exactly version 1 with string instructions.
- It drops only its own key and keeps foreign metadata and IDs. Running it twice is a no-op.
- Tests cover each rejection case: assistant role, version 2, non-string instructions, empty metadata, and slash-looking text without a tag.
- **Hook placement.**
- In `context` it runs after the unload check and before `session.get` and the location/eligibility returns (host diff :117-120). A test proves expansion still happens on the location-mismatch path, and that nothing is expanded after cleanup (host.test:265-281).
- `compaction` was restructured equivalently, so the cue keeps its existing eligibility gate.
- Only `context` and `compaction` are registered. Both the host test (:272) and the packed smoke test (:79) assert that title and generate are absent.
- **Compaction (SB-1 as implemented).**
- The added `BEADS_COMPACTION_GUIDANCE` sentence is exactly the approved one, with no promise of verbatim retention or native-window override.
- Replay of a JSON round-tripped retained message expands exactly once through the registered hooks.
- **Lifecycle.**
- An ambiguous admission failure propagates after one call, with no retry (workflows.test:437-443). Pre-admission unload still throws.
- There is no synthetic pairing, pending queue, or new model call. Queue and steer are passed through unchanged.
- **OpenSpec delta** (spec.md:898-933): its scenarios match the behavior above, including the explicit no-verbatim-retention limit.

## Standards/Proportionality

No material findings.

- The product change is about 30 lines across three source files, using only supported SDK types (`SessionContext["messages"]`). There is no framework, parser, floor change, or provider/CLI workaround.
- Tests extend the existing fakes. The serializer check reuses the real `@opencode/ai` Responses path over loopback rather than adding a fixture corpus.
- The packed smoke test drives the registered hooks at the actual installed skill path.

## Context effectiveness

**Shown by the deterministic serializer test** (actual OpenAI Responses serialization, no inference):
- Each tagged message carries exactly one snapshot, and `ocBeadsSync` never reaches the outbound request.
- Unexpanded stored messages also serialize without the key. For this serializer, the metadata is not emitted, which settles the SB-3 question for this provider.
- Expansion is byte-stable across replays, and storage is unchanged.
- Compared with beta.3, the only difference is the visible `/oc-beads:sync` part plus one extra text-part boundary: +46 chars per invocation (2738→2784 for one sync, 7858→7996 for three). That growth is bounded and linear, the same shape as beta.3.
- The 113-char compaction cue is disclosed separately.

**Shown by the one genuine 2.1.2 sample:**
- `R1-provider-wire-inputs.json:16-29` shows a single user message: the snapshot first, then `/oc-beads:sync`, with no marker.
- Later requests use `previous_response_id`, so the sample does not re-test replay; that rests on the fixture.
- The persisted record holds compact text plus metadata only (`R1-persisted-user-message.json`). There were 5 primary and 0 auxiliary requests.

**Not measured:** cost, savings, and cache attribution.
- `R1-provider-usage.json` shows cached input going 0 → 12544 → 9216 → 21760. A single sample cannot attribute that pattern to the plugin. Expansion is deterministic, so nothing in the source would make the prefix unstable.
- The docs correctly say the instructions are relocated, not made cheaper.

## Optional observations (nonblocking)

1. **Undeclared test dependency.** `tests/host.test.ts` imports `@opencode/ai` without declaring it. It resolves deterministically today as an exact `2.1.1` dependency of `@opencode/plugin` (`plugin/package.json:50`). Declaring it in devDependencies, pinned, would make that explicit.
2. **Wrapper hides missing `messages`.** The `fakeContext` hook wrapper defaults `event.messages ??= []` for every test. That matches the SDK type, where `messages` is required, but it would hide a host that omitted it.
3. **Cue scope.** The cue is added on every eligible Beads compaction, not only sessions with a tagged sync. This was accepted earlier and is disclosed.
4. **Archive naming.** The sample archive is local source under the beta.3 version string. That is for publication/versioning to handle, not this gate.

## Limitations

- This is a source and evidence review only. I did not run tests, the typecheck, the package smoke test, or the sample.
- I relied on the parent's custody of the 16 candidate paths, the 164 protected paths, and the logs.
- I did not view the UI renders.
- Serializer evidence covers OpenAI Responses only. Hooked paths delete the key before conversion, so other providers' handling matters only for unhooked lowerings.

READY does not authorize commit, release or publication; the parent owns acceptance.
65 changes: 65 additions & 0 deletions docs/reviews/opus-workflow-context-plan-0ny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
## Verdict: **READY**

This verdict covers the plan and task structure only: plan.md (SHA256 `4aacd155…`) and task `opencode-beads-8fl` as captured in the packet. It does not approve any implementation, release or publication.

I found no material spec, behavior, authority or completeness issue that would change the decision. The plan fits the current source: it is a small extension of the existing sync mechanism, not a new architecture.

## Spec and behavior findings (none blocking)

**1. Mechanism and schema: coherent and proportionate.**
- Current sync writes `metadata: { ocBeadsSync: { version: 1, instructions } }` (`src/workflows.ts:136-139`). The reader expands it once and strips the key (`src/workflows.ts:92-106`). The plan adds one key, one writer and one renamed helper on top of this.
- **No metadata clobbering.** `CommandInvocation.prompt` is a `PromptInput.Prompt`, and that type has no `metadata` field. So spreading `...input.prompt` and then setting `metadata` overwrites nothing. Prompt-hook edits to `SessionPrompt.metadata` happen after admission and are untouched.
- **Dual-key handling is idempotent in every combination:**
- Both keys valid: generalized wins and both keys are stripped.
- Generalized malformed, legacy valid: legacy expands, and the malformed key stays and is inert on a second pass.
- The reverse case works the same way.
- **Provider serialization (actual behavior, not speculation):** the existing local Responses harness test sends unexpanded stored history with `ocBeadsSync` metadata. It asserts that neither `ocBeadsSync` nor `Invoked command:` appears in the outbound request (`tests/host.test.ts:1037-1039`). The serializer drops message metadata, so leftover unknown or malformed metadata is not a provider leak.
- **Hook placement:** expansion stays before the location and eligibility early returns (`src/host.ts:337, 378`), as the plan states. Nothing else in `host.ts` needs to change.

**2. Command semantics: preserved.**
- All per-command authority lives in the static `WORKFLOWS` purpose strings plus the shared `common` block (`src/workflows.ts:15-45, 115-124`). This includes:
- restore display-only unless `--apply`
- compact `--auto`/`--dolt` mode authority
- stats using `bd status`
- QuickStart, init, template and delete/import/rename-prefix limits
- The plan moves these bytes into the snapshot unchanged and adds no parsing.
- **Inventory:** 30 unique names, matching the canonical spec's "exactly 30" (`openspec/specs/workflow-access/spec.md:35`).
- **Exceptions:** only diagnostics has dynamic content, built from a runtime report (`src/workflows.ts:143-155`). It is correctly the one retained exception. No other command, including prime, needs one.
- **Canonical spec:** the "invoked name, requested outcome and any literal details" scenario (`spec.md:17`) is still met in the effective context.

**3. Compaction cue: sufficient.**
- The proposed sentence replaces `src/guidance.ts:76`. Its "unresolved inputs or explicit modes" wording covers `--apply`, `--auto` and `--dolt`.
- Eligibility gating stays as is (`src/host.ts:379`).
- The compaction request itself sees the expanded snapshots, so the summarizer gets full instructions. Retention stays semantic and makes no verbatim claim.

**4. Task 8fl: correct.**
- One cohesive record: status `blocked`, no assignee, `implementation_authorized: false`, a `blocks` dependency on 5jm, and an approval-plus-dispatch gate.
- It names the local uncommitted reference (not HEAD), says no release is required, and states that the parent owns sync closeout.
- **Spec sequencing:** the plan requires a scoped change before any product edits. That change must replace the active delta's "All other command outputs and descriptions SHALL remain unchanged" (`openspec/changes/compact-sync-command-context/specs/workflow-access/spec.md:7`). This is the right planning and dispatch boundary.

**5. Tests and evidence: adequate.**
- They reuse the existing five-case results, replay tests and serializer harness, and add one justified smoke test: `update` through native code mode, a path sync never exercised.
- No benchmark or command-by-model test matrix.

## Standards and proportionality findings

None material. The changes are limited to `workflows.ts`, two helper calls in `host.ts` and one sentence in `guidance.ts`. No new hooks, model calls, pending state or registry redesign. Having sync write the generalized key keeps a single writer, and the legacy reader is a small cost for old histories.

## Optional observations (non-blocking)

1. **Fixture reconciliation mechanism.** `tests/fixtures/non-sync-command-baseline.json` stores hashes of `{description, sent}` from a call made with details (`tests/workflows.test.ts:305-308`). It does not store the bare instruction bodies the plan says to compare against. Two ways to get that baseline without "blind regeneration":
- Rebuild the old payload from each new snapshot (`snapshot + "\n\nLiteral user details:\n" + fixedText` plus the same native fields) and assert it matches the **existing** hash unchanged.
- Or capture bare-body digests from the reference source before editing.

Spelling out one of these in the design would remove ambiguity for the implementer.
2. **Spec ordering.** If the sync change is still active, a new delta can't use MODIFIED against a requirement that isn't canonical yet. That would leave the implementer to redo the "unchanged" constraint by hand. Archiving the sync change first is the cleaner path. The plan already delegates this choice to the parent.
3. **Base check durability.** The base check relies on a manifest under `/opt/data/cache/scratch/…`. Recording that manifest's digest in 8fl or the evaluation doc would keep the check usable if scratch is cleaned up. Also, 8fl's acceptance text omits the design's "or parent-accepted equivalent integration" clause, which matters if closeout changes any bytes.
4. **Legacy reader necessity.** If sync and the migration ship together, no released build ever wrote `ocBeadsSync`. The legacy reader then only serves local canary and disposable histories. It is cheap, so keeping it is reasonable while the base order is undecided.
5. **Test updates.** Existing assertions on `ocBeadsSync` and the old cue (`tests/host.test.ts:954, 972, 1008, 1024`; `scripts/test-package.ts:340`) need updating. They fall within the listed test files, but `host.test.ts:972` is a cue assertion that the plan only mentions for `guidance.test.ts`.

## Evidence and limitations

- **Read:** the packet's `plan.md`, `implementation-bead.json` (including the embedded 5jm record), `parent-inventory-check.json` and `command-inventory.json` dispositions.
- **Read in source:** `src/workflows.ts` (all), `src/host.ts:320-389`, `src/guidance.ts:70-77`, the plugin session/command type definitions, the canonical `workflow-access` spec slices, the active sync delta spec, and the relevant test slices (`tests/host.test.ts:940-1048`, `tests/workflows.test.ts` baseline usage).
- **Not run:** nothing. No tests, inventory factory, smoke or live probes. I didn't verify the 182-path hashes myself or reread the evaluation and plan docs.
- **Status:** implementation stays blocked pending owner approval, explicit dispatch, and the parent's choice of base and spec order. The future tests and the `update` smoke haven't been run, and no results are claimed.
Loading
Loading