From 08dd8fab28ebca452af5e8e94fdf4c7913b67262 Mon Sep 17 00:00:00 2001 From: Matt Jackson Date: Tue, 10 Nov 2026 02:46:41 +0000 Subject: [PATCH 1/2] feat(spec): propose additive Terra task agent and document native harness onboarding --- AGENTS.md | 6 ++++ .../add-terra-task-agent/.openspec.yaml | 4 +++ .../changes/add-terra-task-agent/design.md | 32 +++++++++++++++++ .../changes/add-terra-task-agent/proposal.md | 33 +++++++++++++++++ .../specs/workflow-access/spec.md | 36 +++++++++++++++++++ .../changes/add-terra-task-agent/tasks.md | 18 ++++++++++ 6 files changed, 129 insertions(+) create mode 100644 openspec/changes/add-terra-task-agent/.openspec.yaml create mode 100644 openspec/changes/add-terra-task-agent/design.md create mode 100644 openspec/changes/add-terra-task-agent/proposal.md create mode 100644 openspec/changes/add-terra-task-agent/specs/workflow-access/spec.md create mode 100644 openspec/changes/add-terra-task-agent/tasks.md diff --git a/AGENTS.md b/AGENTS.md index bfd3976..a74b905 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -76,6 +76,12 @@ This project-owned policy applies to commands in generated integration blocks to - Give a substantive independently owned review one bounded review Bead linked to its planning work and exact candidate. Reuse it through correction/recheck cycles; do not create a ticket per document, invocation, transient retry or minor nit. Record the actual reviewer actor/session, verdict, findings and evidence. Do not invent retroactive claims or timestamps for reviews already performed. - Ownership of behavior, rationale/evidence and execution status follows [Where truth lives](#where-truth-lives). Close planning/review from their own evidence and owner acceptance, not from implementation completion. Their closure does not authorize implementation, release or deployment. Readiness alone is never dispatch permission. +## Native harness onboarding + +- Codex uses the shared `.agents/skills/beads` skill, `.codex/hooks.json` and the enabled native hooks feature. Review/trust the exact repo hook hashes through Codex's normal trust mechanism; do not use a blanket hook-trust bypass. For ordinary orchestrated work, retain user config so its hash-scoped trust records load, while selecting model/effort and assignment authority explicitly. `--ignore-user-config` is for deliberately isolated runs, not proof of complete native hook onboarding. +- Claude Code uses its installed Beads plugin for the skill, command resources and lifecycle context. When authentication HOME differs from plugin-install HOME, pass `--plugin-dir` for the verified existing plugin directory; do not copy credentials, install duplicate hooks or infer loading from `bd setup claude --check` alone. +- Verify actual hook/context delivery and one scoped CLI operation in a fresh harness run. Setup checks prove file/config presence, not execution. Full Beads capability remains available; task-specific read/write/claim/closure limits come from the assigned Bead and dispatch. Native hook output and historical memories do not expand those limits or transfer parent acceptance. + ## Releasing a New Version **Triggers**: User says "bump the version", "cut a new release", "release a new version", "let's do a release", or similar. diff --git a/openspec/changes/add-terra-task-agent/.openspec.yaml b/openspec/changes/add-terra-task-agent/.openspec.yaml new file mode 100644 index 0000000..415f7ea --- /dev/null +++ b/openspec/changes/add-terra-task-agent/.openspec.yaml @@ -0,0 +1,4 @@ +schema: spec-driven +created: 2026-11-10 +goal: Add an opt-in Terra Medium Beads task agent alongside the unchanged + inherited-model and Luna profiles diff --git a/openspec/changes/add-terra-task-agent/design.md b/openspec/changes/add-terra-task-agent/design.md new file mode 100644 index 0000000..90f2fe0 --- /dev/null +++ b/openspec/changes/add-terra-task-agent/design.md @@ -0,0 +1,32 @@ +# Design + +## Context + +See [proposal](proposal.md) for motivation and the [workflow-access delta](specs/workflow-access/spec.md) for behavior. Current source at `56e3a3bb4c261e500ce81b8c337073f1710eaa22` builds the inherited agent and optional Luna in `src/agents.ts`; `src/host.ts` forwards `luna`, and task-agent recognition uses the exported agent-name set. Native configuration already overrides registered fields. + +## Goals / Non-Goals + +Add one explicit opt-in profile through the existing mechanism. Do not introduce a model router, configurable profile registry, fallback, new permissions, dependency changes, store work or token/latency benchmark. Existing lifecycle/typed-operation mechanisms are verification-only unless an actual Terra recognition omission requires a direct correction. + +## Decisions + +1. **Add `terra?: boolean`; keep `luna?: boolean`.** False or omitted means no corresponding registration. Both true means three agents. Replacement or a Luna-labelled Terra route would unnecessarily change a public contract. +2. **Use the exact native route** `{ providerID: "openai", id: "gpt-6.1-terra", variant: "medium" }`. Broaden the existing model type only enough for both constants; no arbitrary model-selection framework. Host/provider support is an explicit prerequisite, not an inference from Codex availability. +3. **Reuse the base definition.** Terra gets the same shared prompt, description, step cap and permission policy. Add its name to existing recognition so context/actor handling does not misclassify it as an unrelated subagent. Preserve per-rebuild user override precedence and normal disposal. +4. **Reuse existing tests and package smoke.** Cover neither/Luna/Terra/both, literal routes and shared policy equality. Extend one host fixture for actual option forwarding and Terra eligibility; use existing customization/disposal checks rather than multiplying the entire lifecycle suite. + +## Risks / Trade-offs + +- Provider availability differs by host → verify the exact OpenCode catalog/variant before a single disposable native dispatch; preserve host errors and do not add fallback logic. +- Registration alone misses context eligibility → assert the actual recognized Terra request path using the existing host fixture. +- A public option needs current instructions → update the user-guide option table/example and relevant installed guidance only if it enumerates profiles. Do not rewrite frozen evidence or command semantic baselines for an agent-only addition. + +## Verification and acceptance boundary + +Implementation requires owner acceptance of this package and later execution tracking. Expected editable production modules are only `src/agents.ts` and option forwarding in `src/host.ts`; relevant existing fixtures/package smoke and current docs are in scope. Stop and discuss if new provider APIs, persistence/permission machinery, dependency acquisition or unrelated lifecycle changes become necessary. + +After source checks, qualify registration and one small read-only child dispatch on an owned disposable supported OpenCode host with an already-authorized provider login. Verify actual selected model/variant and observed child tool results; do not copy credentials, use the operator session or create junk issues in a live tracker. A missing host/auth prerequisite is a named pending gate, not a reason for another integration platform or repeated model campaign. Existing unchanged qualification remains evidence for unchanged mechanisms. + +## Migration and release + +No data or configuration migration is needed. Existing users keep Luna and the inherited agent. Later consumers opt into `terra: true`; disabling it removes only the Terra profile through normal rebuild. A future 2.1.0 release is appropriate, but preparation/publication/activation are outside this draft. After accepted implementation, reconcile canonical specs and archive this change under separately granted closeout authority. diff --git a/openspec/changes/add-terra-task-agent/proposal.md b/openspec/changes/add-terra-task-agent/proposal.md new file mode 100644 index 0000000..8642e07 --- /dev/null +++ b/openspec/changes/add-terra-task-agent/proposal.md @@ -0,0 +1,33 @@ +# Proposal + +## Why + +Offer Terra Medium as an optional implementation worker without taking Luna Max away from existing users or changing the normal model-inheriting task agent. An orchestrator should select a named worker while retaining the same Beads scope, permissions and acceptance boundaries. + +## What Changes + +- Add opt-in `terra: true`, registering `beads-task-agent-terra` with `openai/gpt-6.1-terra` and reasoning variant `medium`. +- Keep `luna: true`, `beads-task-agent-luna` and its Luna Max route unchanged. Both options can be enabled independently or together. +- Keep the always-available `beads-task-agent` model-inheriting; no parent-session model change or silent route fallback. +- Treat Terra as a normal Beads task agent for context eligibility, actor derivation, permissions, interruption limits, native override precedence and cleanup. +- Document selection, provider prerequisites and the distinction between an available worker and authority to execute a task. + +## Capabilities + +### New Capabilities + +None. + +### Modified Capabilities + +- `workflow-access`: add the optional named task-agent profile contract, including additive selection and unchanged execution/ownership boundaries. + +## Impact + +Expected production edits are confined to `src/agents.ts` and the option forwarding in `src/host.ts`, with focused existing fixtures, package smoke assertions and current user guidance. The existing shared task-agent guidance and lifecycle mechanisms are reused; amend a relevant reference only if it enumerates profiles. + +No dependency, host compatibility, Beads minimum, typed-operation, workflow-command or storage change is proposed. No routing framework, model fallback, migration, benchmark campaign or Hermes/Codex configuration change is included. This is a backward-compatible feature suitable for a later 2.1.0 release; version preparation, publication and consumer activation remain separately authorized. + +## Scope and authority + +This package is a proposal for owner review, not permission to implement, release or activate Terra. Native Claude/Codex onboarding in this source repository is separately verified maintenance, not part of the shipped Terra feature or its qualification. diff --git a/openspec/changes/add-terra-task-agent/specs/workflow-access/spec.md b/openspec/changes/add-terra-task-agent/specs/workflow-access/spec.md new file mode 100644 index 0000000..0c2babf --- /dev/null +++ b/openspec/changes/add-terra-task-agent/specs/workflow-access/spec.md @@ -0,0 +1,36 @@ +## ADDED Requirements + +### Requirement: Optional named task-agent profiles + +The integration SHALL offer independent opt-in Luna Max and Terra Medium task-agent profiles alongside its unchanged model-inheriting default. Fixed profiles SHALL select explicit provider, model and reasoning variant without changing the parent route or silently falling back. All profiles SHALL preserve existing Beads scope, permissions, context, ownership and lifecycle behavior and native user-configuration precedence. + +#### Scenario: Existing configuration remains unchanged + +- **WHEN** neither option is enabled, or only existing `luna: true` is enabled +- **THEN** the default `beads-task-agent` remains model-inheriting +- **AND** Luna is absent unless enabled, and enabled Luna retains `beads-task-agent-luna` with `openai/gpt-6-luna` at `max` +- **AND** Terra is not registered without `terra: true` + +#### Scenario: Terra is selected independently + +- **WHEN** `terra: true` is enabled and Luna is not enabled +- **THEN** `beads-task-agent-terra` is registered with `openai/gpt-6.1-terra` at `medium` alongside the unchanged default +- **AND** no Luna profile is added and the parent session route is unchanged + +#### Scenario: Both fixed profiles are selected + +- **WHEN** `luna: true` and `terra: true` are enabled together +- **THEN** the default, Luna and Terra profiles are independently selectable with their respective routing +- **AND** selecting a profile does not authorize additional work, synchronization, publication or closure + +#### Scenario: Terra participates in the existing task-agent lifecycle + +- **WHEN** a Terra task agent executes a permitted read-only assignment or authorized task +- **THEN** it receives the same applicable Beads context, guidance, interruption cap and permission rules as the other task-agent profiles, with identity derived from its actual invoking session and agent +- **AND** existing stop, partial-result, ownership and parent-acceptance requirements remain controlling +- **AND** native configuration overrides and plugin disposal apply without changing unrelated user artifacts + +#### Scenario: The configured provider route is unavailable + +- **WHEN** an enabled fixed profile cannot use its configured provider, model or variant +- **THEN** the host-reported inability is preserved without a plugin-selected substitute model or a claim of successful execution diff --git a/openspec/changes/add-terra-task-agent/tasks.md b/openspec/changes/add-terra-task-agent/tasks.md new file mode 100644 index 0000000..f8eaf4a --- /dev/null +++ b/openspec/changes/add-terra-task-agent/tasks.md @@ -0,0 +1,18 @@ +# Tasks + +Planning only: all tasks below are unexecuted and require owner acceptance plus a scoped implementation assignment. One cohesive implementation Bead can own these tasks after acceptance; do not create an epic or one ticket per checkbox. + +## 1. Add the optional profile through the existing mechanism + +- [ ] 1.1 Extend `src/agents.ts` and option forwarding in `src/host.ts` with `terra: true`, the explicit Terra Medium route and task-agent recognition. Add focused existing-fixture coverage for neither/Luna/Terra/both, unchanged inherited and Luna routes, shared guidance/permissions/steps, and actual Terra context eligibility; demonstrate new behavior fails before implementation and passes afterward. +- [ ] 1.2 Update current user-guide options/selection examples and any relevant profile enumeration in existing guidance/reference/package smoke assertions, preserving all existing command semantics and resource paths. Verify documented names and route match registration, native overrides/disposal remain covered and no dependency, compatibility or baseline changes occurred. + +## 2. Accept the integrated candidate + +- [ ] 2.1 Run the inexpensive existing full tests, typecheck, exact-package smoke, strict change/canonical validation and whitespace checks; inspect the complete source delta against the accepted scope and record the tested candidate plus unresolved limitations. Reuse prior evidence for unchanged permission/lifecycle mechanisms instead of repeating their campaigns. +- [ ] 2.2 With separately authorized disposable host/provider access, verify the selected OpenCode catalog exposes Terra Medium, then record one representative read-only parent-to-Terra dispatch against disposable task data with actual model/variant, child Beads read results, unchanged parent route and no unauthorized writes. Record missing prerequisites honestly and obtain parent acceptance; do not copy credentials or use an operator session as the fixture. + +## Workflow follow-up + +- After accepted implementation and authorized closeout, synchronize the added requirement into canonical `workflow-access`, archive this change, inspect the generated delta and validate again without changing reviewed runtime bytes. +- Release preparation (proposed 2.1.0), Git publication/merge, registry publication and consumer activation are separate owner decisions. Do not check these implementation boxes merely because the planning package exists. From 3aef3769e94b0918c8cb2310968534f436071a2b Mon Sep 17 00:00:00 2001 From: Matt Jackson Date: Tue, 10 Nov 2026 17:34:21 +0000 Subject: [PATCH 2/2] :bookmark: bump version 2.0.0 -> 2.1.0 Add the opt-in Terra Medium task agent without replacing Luna or the model-inheriting default. Reconcile packaged and injected Beads writing, checkpoint and handoff guidance with attributed upstream excerpts. Synchronize the accepted named-profile requirement into workflow-access and archive the completed Terra specification change. Validated with 224 tests / 12,180 assertions, typecheck, exact-package smoke, strict specs and whitespace checks. Native Terra and staged writing/handoff qualification plus final Opus 5.5 review are accepted; the disclosed fixture matcher correction is retained in the evidence. No consumer activation or release publication is included. --- .github/workflows/beads-contract.yml | 2 +- AGENTS.md | 2 +- CHANGELOG.md | 15 ++- README.md | 14 ++- assets/oc-beads/SKILL.md | 13 +- assets/oc-beads/THIRD_PARTY_NOTICES.md | 25 ++++ assets/oc-beads/resources/BOUNDARIES.md | 3 +- assets/oc-beads/resources/ISSUE_CREATION.md | 118 +++++++++++++++++- assets/oc-beads/resources/RESUMABILITY.md | 74 ++++++++++- assets/oc-beads/resources/WORKFLOWS.md | 65 +++++++++- docs/beads-artifact-policy.md | 2 +- docs/claude-code-integration-inventory.json | 7 ++ docs/opencode-terra-qualification-ug9.md | 24 ++++ docs/user-guide.md | 20 +-- .../.openspec.yaml | 0 .../design.md | 2 + .../proposal.md | 2 + .../specs/workflow-access/spec.md | 0 .../2026-11-10-add-terra-task-agent}/tasks.md | 16 +-- openspec/specs/workflow-access/spec.md | 35 ++++++ package.json | 2 +- scripts/test-package.ts | 13 ++ src/agents.ts | 10 +- src/guidance.ts | 6 +- src/host.ts | 1 + src/workflows.ts | 2 +- tests/docs.test.ts | 18 ++- tests/guidance.test.ts | 18 ++- tests/host.test.ts | 25 ++++ tests/upstream-review.test.ts | 2 + tests/workflows.test.ts | 19 ++- 31 files changed, 508 insertions(+), 47 deletions(-) create mode 100644 assets/oc-beads/THIRD_PARTY_NOTICES.md create mode 100644 docs/opencode-terra-qualification-ug9.md rename openspec/changes/{add-terra-task-agent => archive/2026-11-10-add-terra-task-agent}/.openspec.yaml (100%) rename openspec/changes/{add-terra-task-agent => archive/2026-11-10-add-terra-task-agent}/design.md (95%) rename openspec/changes/{add-terra-task-agent => archive/2026-11-10-add-terra-task-agent}/proposal.md (90%) rename openspec/changes/{add-terra-task-agent => archive/2026-11-10-add-terra-task-agent}/specs/workflow-access/spec.md (100%) rename openspec/changes/{add-terra-task-agent => archive/2026-11-10-add-terra-task-agent}/tasks.md (60%) diff --git a/.github/workflows/beads-contract.yml b/.github/workflows/beads-contract.yml index cf30812..22008e1 100644 --- a/.github/workflows/beads-contract.yml +++ b/.github/workflows/beads-contract.yml @@ -1,6 +1,6 @@ name: beads-contract -# Nothing is vendored from upstream Beads. This checks the latest stable bd release against the +# Project-owned guidance contains attributed excerpts; no upstream executable or sync-managed vendor tree is shipped. This checks the latest stable bd release against the # plugin's contract daily, and fails when a newer release has not been reviewed yet. # Independent MAIN source comparison is informational; unavailable evidence fails only its job. on: diff --git a/AGENTS.md b/AGENTS.md index a74b905..fcecbb7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -59,7 +59,7 @@ its repository-specific tools, architecture and style rules do not apply here. ## Notes - This is an OpenCode V2 plugin integrating the beads issue tracker -- Nothing is vendored from upstream Beads; see `docs/beads-artifact-policy.md`. Review each Beads release's upgrade notes against the surfaces listed there +- Project-owned guidance contains attributed excerpts; no upstream executable, host integration or sync-managed vendor tree is shipped; see `docs/beads-artifact-policy.md`. Review each Beads release's upgrade notes against the surfaces listed there ## Upstream responsibility boundary diff --git a/CHANGELOG.md b/CHANGELOG.md index 4db2011..048e811 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,18 @@ and this project attempts to adhere to [Semantic Versioning](https://semver.org/ ## [Unreleased] +## [2.1.0] + +### Added + +- Optional `terra: true` profile registers `beads-task-agent-terra` on `openai/gpt-6.1-terra#medium`, with the same scope-bounded guidance, permissions, step cap, actor attribution and Beads context eligibility as the existing task agents. The default agent still inherits its model; Luna Max is unchanged and both optional profiles can coexist. Provider access remains external; no silent fallback or model-quality guarantee is added. + +### Changed + +- Align issue-writing and deliberate handoff guidance with attributed Beads excerpts; monitor the upstream license alongside the existing source inventory. +- Document native Claude Code and Codex Beads onboarding for orchestrated work: retain verified native integration, confirm actual context delivery and bind execution authority to the assigned Bead. +- Reconcile the validated Beads CLI baseline to 1.3.4 while preserving minimum 1.3.1, and add independent daily/manual advisory upstream-source comparison. These maintenance changes were already delivered on main; they do not introduce runtime repair or automatic adoption. + ## [2.0.0] ### Changed @@ -378,7 +390,8 @@ Documentation-only release; the plugin code is unchanged from 1.0.0. It updates - Josh Thomas (maintainer) -[unreleased]: https://github.com/snarkipus/opencode-beads/compare/v2.0.0...HEAD +[unreleased]: https://github.com/snarkipus/opencode-beads/compare/v2.1.0...HEAD +[2.1.0]: https://github.com/snarkipus/opencode-beads/releases/tag/v2.1.0 [2.0.0]: https://github.com/snarkipus/opencode-beads/releases/tag/v2.0.0 [1.1.0-beta.5]: https://github.com/snarkipus/opencode-beads/releases/tag/v1.1.0-beta.5 [1.1.0-beta.4]: https://github.com/snarkipus/opencode-beads/releases/tag/v1.1.0-beta.4 diff --git a/README.md b/README.md index ba677f4..aba66f3 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,11 @@ The installed `bd` CLI stays authoritative for issues, project initialization, s ## Supported versions -Version **2.0.0** is the stable line. +Version **2.1.0** targets the stable line. | Component | Supported | Evidence | | --- | --- | --- | -| OpenCode | `>=2.2.6 <2.3` | Exact 2.2.6 native-host qualification plus one genuine model workflow | +| OpenCode | `>=2.2.6 <2.3` | Base integration: exact 2.2.6 native-host qualification plus one genuine model workflow; one read-only Terra Medium child dispatch on 2.2.6 | | `bd` CLI | 1.3.1 through 1.x | 1.3.4 contract baseline | A compatible range is admission, not proof that every future patch was tested. The plugin refuses to register on hosts outside the range. Older hosts: see [Compatibility](docs/user-guide.md#compatibility). @@ -44,18 +44,20 @@ A compatible range is admission, not proof that every future patch was tested. T ```json { - "plugins": ["@snarkipus/opencode-beads@2.0.0"] + "plugins": ["@snarkipus/opencode-beads@2.1.0"] } ``` - OpenCode reloads configuration automatically. Update the pin explicitly when upgrading. Options such as `luna`, `stealth` and `autoMigrate` use the [object form](docs/user-guide.md#plugin-options). + OpenCode reloads configuration automatically. Update the pin explicitly when upgrading. Options such as `luna`, `terra`, `stealth` and `autoMigrate` use the [object form](docs/user-guide.md#plugin-options). 3. Check the install: `opencode debug agents` lists `beads-task-agent`, and `/oc-beads:diagnostics` reports native registration and observed capabilities. -### Upgrading to 2.0.0 +### Upgrading to 2.1.0 Upgrade OpenCode before changing the plugin pin: 2.0.0 requires `>=2.2.6 <2.3` and has no 2.1 compatibility layer. Then replace the existing plugin entry, not add a second one, and check `/oc-beads:diagnostics`. Existing exact 1.x and beta pins remain available; installations are not upgraded automatically. Staying on OpenCode 2.1? Keep the exact `1.1.0-beta.5` pin, which retains its `>=2.1.1 <2.2` range. Other migration notes are in the [user guide](docs/user-guide.md#upgrading). +From plugin 2.0.0, the host range and existing options are unchanged. To add the optional `beads-task-agent-terra` profile, enable `terra: true` in the object form. It uses `openai/gpt-6.1-terra#medium`; the default agent still inherits its model, Luna Max remains available, and both optional profiles can coexist. Enabling a profile does not authorize work or change the parent route. + ## First use In an initialized project: @@ -89,7 +91,7 @@ The agent claims the issue atomically and appends checkpoints under the actual s ## Authorship and license -This is an independent project maintained by Matt Jackson. 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. It vendors nothing from upstream Beads; the daily/manual maintenance workflow checks tagged CLI compatibility and independently compares reviewed upstream integration sources with current MAIN. Completed source changes are informational; adoption remains a human decision. +This is an independent project maintained by Matt Jackson. 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. Its project-owned guidance includes attributed MIT-licensed excerpts; it redistributes no upstream executable, host integration or sync-managed vendor tree. See the [notice](assets/oc-beads/THIRD_PARTY_NOTICES.md). The daily/manual maintenance workflow checks tagged CLI compatibility and independently compares reviewed upstream integration sources with current MAIN. Completed source changes are informational; adoption remains a human decision. opencode-beads is licensed under the MIT license. See [`LICENSE`](LICENSE). diff --git a/assets/oc-beads/SKILL.md b/assets/oc-beads/SKILL.md index 464e1bb..aeb87b3 100644 --- a/assets/oc-beads/SKILL.md +++ b/assets/oc-beads/SKILL.md @@ -98,6 +98,10 @@ WORKTREES only for relevant worktree context. evidence expected, actor, and stop condition. There is no required command-count threshold or one-issue-per-invocation loop. +## Issue fields + +Title identifies the outcome; description explains why and context; design records the approach and may change; acceptance states stable, verifiable outcomes; notes hold evolving state. Lifecycle progress alone does not change objectives or acceptance; authorized factual corrections and genuine clarifications remain legitimate. This package-owned `oc-beads` skill is distinct from the shared `beads` skill that `bd init` may create. + ## Keep useful progress At a meaningful change in direction, record what was attempted, what happened, @@ -108,8 +112,13 @@ the issue's notes so useful earlier learning remains available: bd update '' --append-notes="Tried …; result …; because …; blocker …; next …" --actor='' --sandbox --json ``` -Use `--append-notes` for checkpoints. Replacing notes is a deliberate edit, not -the routine checkpoint path. Keep records concise and evidence-based; do not +Use `--append-notes` for checkpoints. For a deliberate current-state handoff, replace working notes while carrying forward relevant decisions, rejected approaches and reasons, blockers and the next action: + +```sh +bd update '' --notes="Current state; decisions; blockers; next action" --actor='' --sandbox --json +``` + +The typed `note` operation is append-only. If only typed operations are available, append a labelled handoff and report the typed-only limitation; replacement requires an available, permissioned direct shell. Keep records concise and evidence-based; do not store credentials, raw dumps, or guesses as facts. Do not write just to meet a count or frequency target when nothing material changed. If a write fails or its result is uncertain, report that state and inspect before retrying. diff --git a/assets/oc-beads/THIRD_PARTY_NOTICES.md b/assets/oc-beads/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..8c916cd --- /dev/null +++ b/assets/oc-beads/THIRD_PARTY_NOTICES.md @@ -0,0 +1,25 @@ +# Third-party notices + +The following MIT license covers attributed Beads excerpts from revision `5ac194105c138ca799bc2f6534c8f92712d8d782` in ISSUE_CREATION, RESUMABILITY and WORKFLOWS, and earlier project adaptations from revision `4a67d0d0288c1b4ee23e17fc896f47616931ba2d`. + +MIT License + +Copyright (c) 2025 Beads Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/assets/oc-beads/resources/BOUNDARIES.md b/assets/oc-beads/resources/BOUNDARIES.md index a5fdfc3..7764916 100644 --- a/assets/oc-beads/resources/BOUNDARIES.md +++ b/assets/oc-beads/resources/BOUNDARIES.md @@ -53,5 +53,6 @@ only within the authority already granted. For a tracked item, preserve its execution identity and history. Claim atomically when authorized, use an explicit actor on writes, and append material -progress rather than replacing previous notes. A task record does not own the +progress; a deliberate current-state handoff may replace working notes while +preserving relevant learning. A task record does not own the Beads database or authorize sync, setup, permission changes, or Git operations. diff --git a/assets/oc-beads/resources/ISSUE_CREATION.md b/assets/oc-beads/resources/ISSUE_CREATION.md index d572c4d..0232d5d 100644 --- a/assets/oc-beads/resources/ISSUE_CREATION.md +++ b/assets/oc-beads/resources/ISSUE_CREATION.md @@ -1,6 +1,6 @@ # Creating useful issues -> Adapted from [Beads marketplace-main `ISSUE_CREATION.md`](https://github.com/gastownhall/beads/blob/4a67d0d0288c1b4ee23e17fc896f47616931ba2d/plugins/beads/skills/beads/resources/ISSUE_CREATION.md). +> Adapted from Beads [`ISSUE_CREATION.md`](https://github.com/gastownhall/beads/blob/5ac194105c138ca799bc2f6534c8f92712d8d782/plugins/beads/skills/beads/resources/ISSUE_CREATION.md) at `5ac194105c138ca799bc2f6534c8f92712d8d782`; see [third-party notices](../THIRD_PARTY_NOTICES.md). Create a durable issue when work needs its own assignment, dependencies, multi-session history, or acceptance record, and only when the existing authority @@ -14,7 +14,7 @@ not authorize the new issue. - **Description:** why the work exists, relevant context, and boundaries. - **Design:** the intended approach and important constraints. - **Acceptance:** observable conditions that define completion. -- **Notes:** current progress and later checkpoints, appended as work proceeds. +- **Notes:** evolving progress, incremental checkpoints and deliberate current-state handoffs. Do not treat a proposed approach as an acceptance test. Avoid secrets, copied logs, vague “investigate” titles without a question, and unsupported promises. @@ -43,3 +43,117 @@ bd create "Clarify retry behavior" --type=task --priority=2 \ Before creating linked work, inspect the parent and verify dependency direction. Keep planning and implementation ownership distinct when the project assigns them to different people. + + +### Verbatim upstream excerpt: ISSUE_CREATION, When to Ask First vs Create Directly and Issue Quality + +## When to Ask First vs Create Directly {#when-to-ask} + +### Ask the user before creating when: +- Knowledge work with fuzzy boundaries +- Task scope is unclear +- Multiple valid approaches exist +- User's intent needs clarification + +### Create directly when: +- Clear bug discovered during implementation +- Obvious follow-up work identified +- Technical debt with clear scope +- Dependency or blocker found + +**Why ask first for knowledge work?** Task boundaries in strategic/research work are often unclear until discussed, whereas technical implementation tasks are usually well-defined. Discussion helps structure the work properly before creating issues, preventing poorly-scoped issues that need immediate revision. + +## Issue Quality {#quality} + +Use clear, specific titles and include sufficient context in descriptions to resume work later. + +### Field Usage + +**Use --design flag for:** +- Implementation approach decisions +- Architecture notes +- Trade-offs considered + +**Use --acceptance flag for:** +- Definition of done +- Testing requirements +- Success metrics + +**OpenCode adaptation:** Follow the existing assignment and permissions; quoted commands are historical illustrations, not copyable local commands. Use the actor-scoped examples above. + + +### Verbatim upstream excerpt: ISSUE_CREATION, Design vs Acceptance Criteria + +## Design vs Acceptance Criteria (Critical Distinction) {#design-vs-acceptance} + +Common mistake: Putting implementation details in acceptance criteria. Here's the difference: + +### DESIGN field (HOW to build it): +- "Use two-phase batchUpdate approach: insert text first, then apply formatting" +- "Parse with regex to find * and _ markers" +- "Use JWT tokens with 1-hour expiry" +- Trade-offs: "Chose batchUpdate over streaming API for atomicity" + +### ACCEPTANCE CRITERIA (WHAT SUCCESS LOOKS LIKE): +- "Bold and italic markdown formatting renders correctly in the Doc" +- "Solution accepts markdown input and creates Doc with specified title" +- "Returns doc_id and webViewLink to caller" +- "User tokens persist across sessions and refresh automatically" + +### Why this matters: +- Design can change during implementation (e.g., use library instead of regex) +- Acceptance criteria should remain stable across sessions +- Criteria should be **outcome-focused** ("what must be true?") not **step-focused** ("do these steps") +- Each criterion should be **verifiable** - you can definitively say yes/no + +### The pitfall + +Writing criteria like "- [ ] Use batchUpdate approach" locks you into one implementation. + +Better: "- [ ] Formatting is applied atomically (all at once or not at all)" - allows flexible implementation. + +### Test yourself + +If you rewrote the solution using a different approach, would the acceptance criteria still apply? If not, they're design notes, not criteria. + +### Example of correct structure + +✅ **Design field:** +``` +Two-phase Docs API approach: +1. Parse markdown to positions +2. Create doc + insert text in one call +3. Apply formatting in second call +Rationale: Atomic operations, easier to debug formatting separately +``` + +✅ **Acceptance criteria:** +``` +- [ ] Markdown formatting renders in Doc (bold, italic, headings) +- [ ] Lists preserve order and nesting +- [ ] Links are clickable +- [ ] Large documents (>50KB) process without timeout +``` + +❌ **Wrong (design masquerading as criteria):** +``` +- [ ] Use two-phase batchUpdate approach +- [ ] Apply formatting in second batchUpdate call +``` + +**OpenCode adaptation:** Follow the existing assignment and permissions; quoted commands are historical illustrations, not copyable local commands. Use the actor-scoped examples above. + + +### Verbatim upstream excerpt: ISSUE_CREATION, Quick Reference + +## Quick Reference + +**Creating good issues:** + +1. **Title**: Clear, specific, action-oriented +2. **Description**: Problem statement, context, why it matters +3. **Design**: Approach, architecture, trade-offs (can change) +4. **Acceptance**: Outcomes, success criteria (should be stable) +5. **Notes**: Implementation details, session handoffs (evolves over time) + +**OpenCode adaptation:** Follow the existing assignment and permissions; quoted commands are historical illustrations, not copyable local commands. Use the actor-scoped examples above. diff --git a/assets/oc-beads/resources/RESUMABILITY.md b/assets/oc-beads/resources/RESUMABILITY.md index fd4d278..02bf508 100644 --- a/assets/oc-beads/resources/RESUMABILITY.md +++ b/assets/oc-beads/resources/RESUMABILITY.md @@ -1,6 +1,6 @@ # Resumability and recovery -> Adapted from [Beads marketplace-main `RESUMABILITY.md`](https://github.com/gastownhall/beads/blob/4a67d0d0288c1b4ee23e17fc896f47616931ba2d/plugins/beads/skills/beads/resources/RESUMABILITY.md). +> Adapted from Beads [`RESUMABILITY.md`](https://github.com/gastownhall/beads/blob/5ac194105c138ca799bc2f6534c8f92712d8d782/plugins/beads/skills/beads/resources/RESUMABILITY.md) at `5ac194105c138ca799bc2f6534c8f92712d8d782`; see [third-party notices](../THIRD_PARTY_NOTICES.md). A future executor needs the state of the work, not a transcript. At meaningful transitions preserve: @@ -90,3 +90,75 @@ content back to the issue. This is not database backup recovery, Git history restoration or general store repair. Inspect installed help and report missing content or uncertainty honestly; conflicting compact/restore help does not establish guaranteed recovery or reversibility. + + +### Verbatim upstream excerpt: RESUMABILITY, When Resumability Matters + +## When Resumability Matters + +**Use enhanced documentation for:** +- Multi-session technical features with API integration +- Complex algorithms requiring code examples +- Features with specific output format requirements +- Work with "occult" APIs (undocumented capabilities) + +**Skip for:** +- Simple bug fixes with clear scope +- Well-understood patterns (CRUD operations, etc.) +- Single-session tasks +- Work with obvious acceptance criteria + +**The test:** Would a fresh Claude instance (or you after 2 weeks) struggle to resume this work from the description alone? If yes, add implementation details. + +**OpenCode adaptation:** Follow the existing assignment and permissions; quoted commands are historical illustrations, not copyable local commands. Use the actor-scoped examples above. + + +### Verbatim upstream excerpt: RESUMABILITY, Anti-Patterns + +## Anti-Patterns + +### ❌ Over-Documenting Simple Work +```markdown +Title: Fix typo in README +Notes: IMPLEMENTATION GUIDE +WORKING CODE: Open README.md, change "teh" to "the"... +``` +**Problem:** Wastes tokens on obvious work. + +### ❌ Design Details in Acceptance Criteria +```markdown +Acceptance: +- [ ] Use batchUpdate approach +- [ ] Call API with fields parameter +- [ ] Format as markdown with ## headers +``` +**Problem:** Locks implementation. Should be in Design/Notes, not Acceptance. + +### ❌ Raw JSON Dumps +```markdown +API RESPONSE: +{giant unformatted JSON blob spanning 100 lines} +``` +**Problem:** Hard to read. Extract relevant parts, show structure. + +### ✅ Right Balance +```markdown +API RESPONSE SAMPLE: +Returns dict with 49 entries. Example entries: +- 'text/markdown': ['application/vnd.google-apps.document'] +- 'text/plain': ['application/vnd.google-apps.document'] +- 'application/pdf': ['application/vnd.google-apps.document'] +``` + +**OpenCode adaptation:** Follow the existing assignment and permissions; quoted commands are historical illustrations, not copyable local commands. Use the actor-scoped examples above. + +## Append or replace + +Use `--append-notes` for incremental checkpoints. At a deliberate current-state handoff, replace working notes with `--notes`, carrying forward relevant decisions, rejected approaches and reasons, blockers, and the next action. Keep verified results distinct from hypotheses. + +```sh +bd update '' --append-notes="Result and evidence; next action" --actor='' --sandbox --json +bd update '' --notes="Current state; decisions; blockers; next action" --actor='' --sandbox --json +``` + +The typed `note` operation is append-only. When only typed operations are available, append a labelled current-state handoff and report the typed-only limitation; do not claim replacement occurred. Use the direct shell route only when available and permissioned. diff --git a/assets/oc-beads/resources/WORKFLOWS.md b/assets/oc-beads/resources/WORKFLOWS.md index 087b9c2..1ee143d 100644 --- a/assets/oc-beads/resources/WORKFLOWS.md +++ b/assets/oc-beads/resources/WORKFLOWS.md @@ -1,6 +1,6 @@ # Workflows and checkpoints -> Adapted from [Beads marketplace-main `WORKFLOWS.md`](https://github.com/gastownhall/beads/blob/4a67d0d0288c1b4ee23e17fc896f47616931ba2d/plugins/beads/skills/beads/resources/WORKFLOWS.md). The append policy below resolves conflicting upstream examples: checkpoints append; replacing notes is deliberate. +> Adapted from Beads [`WORKFLOWS.md`](https://github.com/gastownhall/beads/blob/5ac194105c138ca799bc2f6534c8f92712d8d782/plugins/beads/skills/beads/resources/WORKFLOWS.md) at `5ac194105c138ca799bc2f6534c8f92712d8d782`; see [third-party notices](../THIRD_PARTY_NOTICES.md). ## Begin with the current context @@ -62,3 +62,66 @@ the same review item through corrections and rechecks. Record actual reviewer actor/session, verdict, findings and evidence without retroactive claims. Planning/review closure needs its own evidence and owner acceptance; readiness alone never authorizes dispatch, implementation, release or deployment. + + +### Verbatim upstream excerpt: WORKFLOWS, Compaction Survival + +**Writing notes for compaction survival:** + +**Good note (enables recovery):** +``` +bd update issue-42 --append-notes "COMPLETED: User authentication - added JWT token +generation with 1hr expiry, implemented refresh token endpoint using rotating +tokens pattern. IN PROGRESS: Password reset flow. Email service integration +working. NEXT: Need to add rate limiting to reset endpoint (currently unlimited +requests). KEY DECISION: Using bcrypt with 12 rounds after reviewing OWASP +recommendations, tech lead concerned about response time but benchmarks show <100ms." +``` + +**Bad note (insufficient for recovery):** +``` +bd update issue-42 --append-notes "Working on auth feature. Made some progress. +More to do later." +``` + +The good note contains: +- Specific accomplishments (what was implemented/configured) +- Current state (which part is working, what's in progress) +- Next concrete step (not just "continue") +- Key context (team concerns, technical decisions with rationale) + +**OpenCode adaptation:** Follow the existing assignment and permissions; quoted commands are historical illustrations, not copyable local commands. Use the actor-scoped examples above. + + +### Verbatim upstream excerpt: WORKFLOWS, Notes Format + +### Notes Format (Current State, Not Cumulative) + +``` +Good handoff note (current state): +COMPLETED: Parsed markdown into structured format +IN PROGRESS: Implementing Docs API insertion +NEXT: Debug batchUpdate call - getting 400 error on formatting +BLOCKER: None +KEY DECISION: Using two-phase approach (insert text, then apply formatting) based on reference implementation + +Bad handoff note (not useful): +Updated some stuff. Will continue later. +``` + +**Rules for handoff notes:** +- Current state only (overwrite previous notes, not append) +- Specific accomplishments (not vague progress) +- Concrete next step (not "continue working") +- Optional: Blockers, key decisions, references +- Written for someone with zero conversation context + +**OpenCode adaptation:** Follow the existing assignment and permissions; quoted commands are historical illustrations, not copyable local commands. Use the actor-scoped examples above. + +**OpenCode adaptation:** This replacement is a deliberate current-state handoff; append incremental checkpoints between handoffs. Carry forward relevant decisions, rejected approaches with reasons, blockers and next action. Use the permissioned direct shell `--notes` route; with typed-only access append a labelled handoff and report the limitation. + +### Verbatim upstream excerpt: WORKFLOWS, Status Maintenance + +- [ ] During: Update acceptance criteria if requirements clarify + +**OpenCode adaptation:** Keep title, description and acceptance stable through lifecycle progress; factual corrections and genuine requirement clarification follow existing assignment and project authority. diff --git a/docs/beads-artifact-policy.md b/docs/beads-artifact-policy.md index 2dfe3ae..d06b142 100644 --- a/docs/beads-artifact-policy.md +++ b/docs/beads-artifact-policy.md @@ -1,6 +1,6 @@ # Beads Artifact Policy -Status: current policy for the published 2.x line. The package vendors no upstream Beads artifacts. It ships project-owned adaptations under `assets/oc-beads/` (one skill, 15 corpus resources, CODE_MODE and the adapted ADR, 17 explicit links), 30 native commands and the typed `beads` operations, rather than an upstream executable or host-specific integration. The installed `bd` CLI remains the execution and data owner, and `bd init` owns the shared `.agents/skills/beads`. The sections below are dated rationale and evidence: earlier stable exclusion and one-bead descriptions, and "candidate", "unpublished" or "withheld" wording, describe the state when they were written. Current behavior is defined by the canonical specs; see the [documentation index](README.md). +Status: current policy for the published 2.x line. The package includes attributed MIT-licensed excerpts in project-owned guidance; it redistributes no upstream executable, host integration or sync-managed vendor tree. See the [notice](../assets/oc-beads/THIRD_PARTY_NOTICES.md). It ships project-owned adaptations under `assets/oc-beads/` (one skill, 15 corpus resources, CODE_MODE and the adapted ADR, 17 explicit links), 30 native commands and the typed `beads` operations, rather than an upstream executable or host-specific integration. The installed `bd` CLI remains the execution and data owner, and `bd init` owns the shared `.agents/skills/beads`. The sections below are dated rationale and evidence: earlier stable exclusion and one-bead descriptions, and "candidate", "unpublished" or "withheld" wording, describe the state when they were written. Current behavior is defined by the canonical specs; see the [documentation index](README.md). Current maintenance: the daily/manual `beads-contract` workflow defines independent tagged-CLI and advisory MAIN source-comparison jobs, with collector JSON and exit status in the Actions summary. Completed source comparisons are informational successes; unavailable evidence fails only the independent source job, never a product/release prerequisite. Adoption and reviewed source-baseline changes require explicit human disposition under the [canonical upstream-review spec](../openspec/specs/upstream-review/spec.md). The [1.3.4 CLI review](beads-1.3.4-review-2026-11-09.md) leaves the historical 1.3.1 integration comparison and marketplace-main inventory intact. The dated source-only acceptance below remains historical evidence, not proof of workflow execution. diff --git a/docs/claude-code-integration-inventory.json b/docs/claude-code-integration-inventory.json index a22c46d..4631ab5 100644 --- a/docs/claude-code-integration-inventory.json +++ b/docs/claude-code-integration-inventory.json @@ -2421,6 +2421,13 @@ "installed_plugin_version": "1.3.0", "installed_match": "All 57 files under plugins/beads byte-match the installed cache; installation/discovery is not behavioral qualification.", "files": [ + { + "path": "LICENSE", + "category": "support", + "git_blob": "2a187917a0b9e8ea3ab3db2d9e60649f0e2e4ea5", + "sha256": "caa2c60efbbf71e18b45ef6006a18213f8a42554b235af88883f6f1ec240b7db", + "url": "https://github.com/gastownhall/beads/blob/4a67d0d0288c1b4ee23e17fc896f47616931ba2d/LICENSE" + }, { "path": ".claude-plugin/marketplace.json", "category": "manifest-or-hooks", diff --git a/docs/opencode-terra-qualification-ug9.md b/docs/opencode-terra-qualification-ug9.md new file mode 100644 index 0000000..c8cd75a --- /dev/null +++ b/docs/opencode-terra-qualification-ug9.md @@ -0,0 +1,24 @@ +# Terra task-agent qualification — 2026-11-10 + +Parent acceptance for `opencode-beads-ug9`, OpenSpec task 2.2. This record supplements the [accepted base integration qualification](opencode-22-qualification-5rj2.md); it does not repeat that campaign. + +## Observed result + +Actual OpenCode **2.2.6** loaded the exact prepared **2.1.0** package with `terra: true`. Native model discovery exposed enabled Terra with the `medium` variant, and the package registered the inherited default and Terra agents plus all 30 commands. + +- Parent `ses_e3a4da974ffeXLLwZBauh2kbmY`: `terra_qualification_parent`, `openai/gpt-6.1-sol` / `high`. +- One native subagent call created child `ses_e3a4d919bffd39dwywJDdOjp9H`: `beads-task-agent-terra`, `openai/gpt-6.1-terra` / `medium`. +- The child loaded the packaged skill, discovered `tools.beads.get`, read disposable issue `t21-bne`, and returned its actual title and `TERRA_UG9_READ_ONLY_OK` acceptance marker. +- The Beads result was acknowledged and complete, with no failures. Both sessions completed successfully; the parent remained on Sol/high after the child returned. +- Native assistant records and provider response IDs establish the actual routes. An observation-only context hook agrees; it is pre-serializer evidence, not a wire capture. +- Independent CLI readback found the entire fixture issue unchanged, including revision and timestamps. The three one-time permission grants covered only delegation, packaged skill access and the exact fixture read. No issue write, claim, synchronization or retry occurred. + +The disposable host used a previously user-authenticated native test profile in place, not an operator session. Credentials/databases were not copied, hashed, translated or exported. The owned server and listener were stopped, execution/permission inventories were empty, and transient server secrets/logs were removed. The native test profile remains privately retained in its original custody. + +## Artifact and evidence boundary + +The native run used archive SHA256 `b1e084f66f129ebbf2d857e2fb6b1179e6a427e50c647a9cf612ebbad9f73b89`; all 31 installed files matched. The parent verifier passed 50 assertions. That immutable archive retains the earlier README table saying “Terra qualification pending”; this dated record supersedes that historical status statement, not its runtime bytes. Subsequent release preparation may refresh the README, but must identify the new archive and verify unchanged executable and packaged-guidance bytes rather than relabeling it as the archive used by this run. + +Detailed native sessions, tool results, permissions, before/after issue records, archive inventory, preservation checks and cleanup receipts are retained outside the repository at `/opt/data/research/opencode-beads-terra-qualification/`, indexed by `qualification-report.md` and `analysis.json`. + +This is one representative read-only parent-to-Terra sample, not a model reliability benchmark, Luna requalification or a new permission/disposal campaign. Earlier deterministic source checks cover profile combinations and preserved shared mechanisms. The disclosed `opencode-beads-o66` limitation remains unresolved. Packaged-guidance follow-up `opencode-beads-gjk` is separate and nonblocking. No publication, consumer activation, or canonical specification archival is established by this record. diff --git a/docs/user-guide.md b/docs/user-guide.md index 008e286..4a07793 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -23,7 +23,7 @@ behavior is defined by the canonical specs listed in the Install the [`bd` CLI](https://github.com/gastownhall/beads/blob/main/docs/getting-started/installation.md) once on the host, then run `git init` (only when the directory is not already a Git worktree) and `bd init` in each project. `bd init` owns project initialization and creates the canonical shared Beads skill at `.agents/skills/beads`, which OpenCode discovers. It also writes a minimal Beads section to `AGENTS.md` that points to `bd prime`, the same pointer Beads gives Claude Code in `CLAUDE.md`. The plugin additionally owns its packaged `oc-beads` skill; it does not write startup files or change `.agents/skills/beads/SKILL.md`. The plugin does not install or upgrade `bd`. -An exact version pin such as `"plugins": ["@snarkipus/opencode-beads@2.0.0"]` is recommended. To follow stable releases, use `"plugins": ["@snarkipus/opencode-beads@latest"]` and check the resolved version before upgrading. `"plugins": ["@snarkipus/opencode-beads@next"]` is a separate historical beta channel, not a promise of a newer or compatible release. Update the pin explicitly when upgrading; an unpinned entry is less reproducible. OpenCode 1.x plugins are not supported; use 0.10.x or earlier there. +An exact version pin such as `"plugins": ["@snarkipus/opencode-beads@2.1.0"]` is recommended. To follow stable releases, use `"plugins": ["@snarkipus/opencode-beads@latest"]` and check the resolved version before upgrading. `"plugins": ["@snarkipus/opencode-beads@next"]` is a separate historical beta channel, not a promise of a newer or compatible release. Update the pin explicitly when upgrading; an unpinned entry is less reproducible. OpenCode 1.x plugins are not supported; use 0.10.x or earlier there. After installing, `opencode debug agents` lists `beads-task-agent`, and `/oc-beads:diagnostics` reports the loaded package and host versions, native registration and observed capabilities. Discover `beads` through `execute` on a host and agent with the required permissions. @@ -35,7 +35,7 @@ Plugin options use the object form: { "plugins": [ { - "package": "@snarkipus/opencode-beads@2.0.0", + "package": "@snarkipus/opencode-beads@2.1.0", "options": { "luna": true, "autoMigrate": false } } ] @@ -45,6 +45,7 @@ Plugin options use the object form: | Option | Default | Effect | | --- | --- | --- | | `luna` | `false` | Also register the `beads-task-agent-luna` profile. | +| `terra` | `false` | Also register the `beads-task-agent-terra` profile. | | `stealth` | `false` | Add `--stealth` to `bd prime` (no git operations in the session-close protocol), like `bd setup claude --stealth`. `bd config set no-git-ops true` is the project-level equivalent. | | `taskAgentSteps` | `100` | Interruption cap on task-agent steps per invocation. `0` removes the cap; neither value changes authorized scope or establishes completion. | | `refreshAfterIdleMinutes` | `30` | Re-run `bd prime` when a session resumes after this much inactivity, as Claude Code does on resume. `0` disables idle refresh. | @@ -82,7 +83,7 @@ The plugin runs `bd prime --full` in the project directory and attaches its outp While prime is attached, two bd-managed `AGENTS.md` blocks only repeat it: the full-profile section `bd setup opencode` writes and the Codex section `bd init` writes. The plugin replaces those marked blocks in the outgoing request with a one-line pointer. Your `AGENTS.md` file and any text outside those markers are not changed, and nothing is replaced when prime is withheld or unavailable. -Known regular subagents remain excluded, including `explore` and `general`, while `beads-task-agent` and `beads-task-agent-luna` remain eligible. If agent lookup fails, context injection fails open to preserve compatibility with unknown custom primary agents. +Known regular subagents remain excluded, including `explore` and `general`, while `beads-task-agent`, `beads-task-agent-luna` and `beads-task-agent-terra` remain eligible. If agent lookup fails, context injection fails open to preserve compatibility with unknown custom primary agents. If `bd` is unavailable or the project is uninitialized, nothing is added. If `bd prime` fails or times out, the agent gets a short `` saying context is unavailable and to run `bd prime`. The plugin retries after 30 seconds and logs `[opencode-beads]` warnings. The task agent retains standalone guidance for authorized scope, atomic claim, append checkpoints, validate before closure, and partial handoff under the caller's acceptance authority. @@ -129,10 +130,14 @@ OpenCode lets the plugin enforce parts of that contract: - **Context in the worker.** The worker runs in its own child session and receives `bd prime` there too. - **Beads state across compaction.** Compaction in sessions with Beads context asks the summarizer to keep bead IDs, claims and status changes, follow-ups, blockers and pending validation. -### Opt-in Luna Max profile +### Opt-in fixed profiles Set `"luna": true` to also register `beads-task-agent-luna`, which uses `openai/gpt-6-luna#max` with the same prompt, mode, step cap and permissions. The default `beads-task-agent` leaves its model unset and inherits the parent's model. Customizations to `beads-task-agent` are not copied to Luna. Ask the primary agent to delegate to `beads-task-agent-luna` by name; enabling Luna does not reroute existing calls. Luna requires access to that model in your provider setup; the plugin does not install models, configure authentication or silently fall back. The profile makes no model-quality guarantee. +Terra is introduced in `2.1.0`; published `2.0.0` does not include it. + +Set `"terra": true` to also register `beads-task-agent-terra` with `openai/gpt-6.1-terra#medium`. It has the same prompt, mode, step cap and permissions, and can be enabled independently or together with Luna. Ask for Terra by name; it does not change the parent route. Terra likewise requires provider access, has no silent fallback, and does not grant authority to execute work. Native overrides apply per agent; default-agent customizations are not copied to Terra. + ## Customization and removal Entries under `agents` in OpenCode configuration override the task-agent fields one by one, so a partial override keeps the bounded `system` prompt and subagent `mode`. OpenCode V2 does not expose configuration-only agents to plugins, so the plugin cannot warn about overrides. @@ -147,17 +152,18 @@ Remove the `plugins` entry to unload the plugin. Cleanup aborts owned context/pr | --- | --- | --- | | OpenCode (historical beta.5) | `>=2.1.1 <2.2` | 2.1.1 (bounded accepted evidence) | | OpenCode (2.0.0) | `>=2.2.6 <2.3` | 2.2.6 (accepted native and genuine-model qualification) | +| OpenCode (2.1.0 candidate) | `>=2.2.6 <2.3` | Unchanged base uses the 2.0.0 evidence; one read-only Terra Medium child dispatch on 2.2.6 | | OpenCode (stable 1.0.2 historical) | 2.0.26 | 2.0.26 | | `bd` CLI | 1.3.1 through 1.x | 1.3.4 | | Bun (OpenCode host runtime) | >=1.3.14 | 1.4.2 | -Version 2.0.0 type-checks against `@opencode/plugin` 2.2.6 and declares optional peer range `>=2.2.6 <2.3`. Admission does not qualify future patches. Native qualification used Beads 1.3.4 as its fixture CLI; the supported-minimum contract evidence remains 1.3.1. See the [2.2.6 qualification](opencode-22-qualification-5rj2.md) and the [OpenCode integration reference](opencode-sdk-contract.md). The current CLI baseline was reviewed against Beads v1.3.4; see the [2026-11-09 release review](beads-1.3.4-review-2026-11-09.md). The historical integration comparison remains Beads v1.3.1 (commit `c1c4b642ac1c08d8c828007a1c2f96e47e43ef7c`), separately from CLI validation and the reviewed marketplace-main inventory. +Version 2.1.0 type-checks against `@opencode/plugin` 2.2.6 and retains the optional peer range `>=2.2.6 <2.3`. The unchanged base integration reuses the accepted 2.0.0 qualification; the added Terra profile has one accepted read-only native parent-to-child dispatch, including actual Terra/medium routing, a Beads read and the unchanged parent route. See the [Terra qualification record](opencode-terra-qualification-ug9.md). This is a representative sample, not a reliability benchmark. Admission does not qualify future patches. Native qualification used Beads 1.3.4 as its fixture CLI; the supported-minimum contract evidence remains 1.3.1. See the [2.2.6 qualification](opencode-22-qualification-5rj2.md) and the [OpenCode integration reference](opencode-sdk-contract.md). The current CLI baseline was reviewed against Beads v1.3.4; see the [2026-11-09 release review](beads-1.3.4-review-2026-11-09.md). The historical integration comparison remains Beads v1.3.1 (commit `c1c4b642ac1c08d8c828007a1c2f96e47e43ef7c`), separately from CLI validation and the reviewed marketplace-main inventory. ## Tracking upstream Beads -The package vendors nothing from upstream. It depends on the installed `bd` CLI at runtime: `bd prime` supplies the current workflow, and the schema migration guard enforces the supported `bd` range. +The package includes attributed MIT-licensed excerpts in project-owned guidance; it redistributes no upstream executable, host integration or sync-managed vendor tree. See the [notice](../assets/oc-beads/THIRD_PARTY_NOTICES.md). It depends on the installed `bd` CLI at runtime: `bd prime` supplies the current workflow, and the schema migration guard enforces the supported `bd` range. -[`scripts/bd-contract.ts`](../scripts/bd-contract.ts) checks a real `bd` against everything the plugin relies on. CI runs it against the validated release from `package.json` (`beads.validated`). The scheduled `beads-contract` workflow runs it daily against the latest stable Beads release and fails if that release breaks the contract or is newer than the validated one. When a new release appears, review its upgrade notes, then update `beads.validated` and the compatibility table. The [artifact policy](beads-artifact-policy.md) records why upstream artifacts are not vendored. +[`scripts/bd-contract.ts`](../scripts/bd-contract.ts) checks a real `bd` against everything the plugin relies on. CI runs it against the validated release from `package.json` (`beads.validated`). The scheduled `beads-contract` workflow runs it daily against the latest stable Beads release and fails if that release breaks the contract or is newer than the validated one. When a new release appears, review its upgrade notes, then update `beads.validated` and the compatibility table. The [artifact policy](beads-artifact-policy.md) describes the project-owned adaptations and retired vendor tree. The daily/manual `beads-contract` workflow also has an independent source-comparison job using `scripts/check-beads-integration.ts`. Its step summary contains the collector JSON and exit status: immutable reviewed baseline/candidate commits, selected paths and source/diff links. Completed changed and unchanged comparisons succeed informationally; unavailable retrieval/comparison fails that job and is never reported as unchanged. Neither job depends on the other, and these maintenance checks are not product/release prerequisites. No GitHub issues, automatic adoption or baseline advancement occur. A maintainer must explicitly disposition changes before updating the reviewed inventory. Schedules use the default branch; an authorized manual run can select a published branch with `--ref` when the workflow exists on default. diff --git a/openspec/changes/add-terra-task-agent/.openspec.yaml b/openspec/changes/archive/2026-11-10-add-terra-task-agent/.openspec.yaml similarity index 100% rename from openspec/changes/add-terra-task-agent/.openspec.yaml rename to openspec/changes/archive/2026-11-10-add-terra-task-agent/.openspec.yaml diff --git a/openspec/changes/add-terra-task-agent/design.md b/openspec/changes/archive/2026-11-10-add-terra-task-agent/design.md similarity index 95% rename from openspec/changes/add-terra-task-agent/design.md rename to openspec/changes/archive/2026-11-10-add-terra-task-agent/design.md index 90f2fe0..f5d09a9 100644 --- a/openspec/changes/add-terra-task-agent/design.md +++ b/openspec/changes/archive/2026-11-10-add-terra-task-agent/design.md @@ -1,5 +1,7 @@ # Design +Historical planning rationale retained after implementation acceptance and archival. Source-baseline and future-tense statements below describe the original design context, not current release status. + ## Context See [proposal](proposal.md) for motivation and the [workflow-access delta](specs/workflow-access/spec.md) for behavior. Current source at `56e3a3bb4c261e500ce81b8c337073f1710eaa22` builds the inherited agent and optional Luna in `src/agents.ts`; `src/host.ts` forwards `luna`, and task-agent recognition uses the exported agent-name set. Native configuration already overrides registered fields. diff --git a/openspec/changes/add-terra-task-agent/proposal.md b/openspec/changes/archive/2026-11-10-add-terra-task-agent/proposal.md similarity index 90% rename from openspec/changes/add-terra-task-agent/proposal.md rename to openspec/changes/archive/2026-11-10-add-terra-task-agent/proposal.md index 8642e07..bdbdf66 100644 --- a/openspec/changes/add-terra-task-agent/proposal.md +++ b/openspec/changes/archive/2026-11-10-add-terra-task-agent/proposal.md @@ -1,5 +1,7 @@ # Proposal +Historical proposal retained after implementation acceptance and canonical specification synchronization. Its planning-time authority statements are not current execution status; release and activation remain separately authorized. + ## Why Offer Terra Medium as an optional implementation worker without taking Luna Max away from existing users or changing the normal model-inheriting task agent. An orchestrator should select a named worker while retaining the same Beads scope, permissions and acceptance boundaries. diff --git a/openspec/changes/add-terra-task-agent/specs/workflow-access/spec.md b/openspec/changes/archive/2026-11-10-add-terra-task-agent/specs/workflow-access/spec.md similarity index 100% rename from openspec/changes/add-terra-task-agent/specs/workflow-access/spec.md rename to openspec/changes/archive/2026-11-10-add-terra-task-agent/specs/workflow-access/spec.md diff --git a/openspec/changes/add-terra-task-agent/tasks.md b/openspec/changes/archive/2026-11-10-add-terra-task-agent/tasks.md similarity index 60% rename from openspec/changes/add-terra-task-agent/tasks.md rename to openspec/changes/archive/2026-11-10-add-terra-task-agent/tasks.md index f8eaf4a..4c9c781 100644 --- a/openspec/changes/add-terra-task-agent/tasks.md +++ b/openspec/changes/archive/2026-11-10-add-terra-task-agent/tasks.md @@ -1,18 +1,18 @@ # Tasks -Planning only: all tasks below are unexecuted and require owner acceptance plus a scoped implementation assignment. One cohesive implementation Bead can own these tasks after acceptance; do not create an epic or one ticket per checkbox. +The cohesive implementation Bead `opencode-beads-ug9` owns these tasks. Checkmarks record parent-accepted evidence; release and closeout authority remain separate. ## 1. Add the optional profile through the existing mechanism -- [ ] 1.1 Extend `src/agents.ts` and option forwarding in `src/host.ts` with `terra: true`, the explicit Terra Medium route and task-agent recognition. Add focused existing-fixture coverage for neither/Luna/Terra/both, unchanged inherited and Luna routes, shared guidance/permissions/steps, and actual Terra context eligibility; demonstrate new behavior fails before implementation and passes afterward. -- [ ] 1.2 Update current user-guide options/selection examples and any relevant profile enumeration in existing guidance/reference/package smoke assertions, preserving all existing command semantics and resource paths. Verify documented names and route match registration, native overrides/disposal remain covered and no dependency, compatibility or baseline changes occurred. +- [x] 1.1 Extend `src/agents.ts` and option forwarding in `src/host.ts` with `terra: true`, the explicit Terra Medium route and task-agent recognition. Add focused existing-fixture coverage for neither/Luna/Terra/both, unchanged inherited and Luna routes, shared guidance/permissions/steps, and actual Terra context eligibility; demonstrate new behavior fails before implementation and passes afterward. +- [x] 1.2 Update current user-guide options/selection examples and any relevant profile enumeration in existing guidance/reference/package smoke assertions, preserving all existing command semantics and resource paths. Verify documented names and route match registration, native overrides/disposal remain covered and no dependency, compatibility or baseline changes occurred. ## 2. Accept the integrated candidate -- [ ] 2.1 Run the inexpensive existing full tests, typecheck, exact-package smoke, strict change/canonical validation and whitespace checks; inspect the complete source delta against the accepted scope and record the tested candidate plus unresolved limitations. Reuse prior evidence for unchanged permission/lifecycle mechanisms instead of repeating their campaigns. -- [ ] 2.2 With separately authorized disposable host/provider access, verify the selected OpenCode catalog exposes Terra Medium, then record one representative read-only parent-to-Terra dispatch against disposable task data with actual model/variant, child Beads read results, unchanged parent route and no unauthorized writes. Record missing prerequisites honestly and obtain parent acceptance; do not copy credentials or use an operator session as the fixture. +- [x] 2.1 Run the inexpensive existing full tests, typecheck, exact-package smoke, strict change/canonical validation and whitespace checks; inspect the complete source delta against the accepted scope and record the tested candidate plus unresolved limitations. Reuse prior evidence for unchanged permission/lifecycle mechanisms instead of repeating their campaigns. +- [x] 2.2 With separately authorized disposable host/provider access, verify the selected OpenCode catalog exposes Terra Medium, then record one representative read-only parent-to-Terra dispatch against disposable task data with actual model/variant, child Beads read results, unchanged parent route and no unauthorized writes. Record missing prerequisites honestly and obtain parent acceptance; do not copy credentials or use an operator session as the fixture. -## Workflow follow-up +## Closeout -- After accepted implementation and authorized closeout, synchronize the added requirement into canonical `workflow-access`, archive this change, inspect the generated delta and validate again without changing reviewed runtime bytes. -- Release preparation (proposed 2.1.0), Git publication/merge, registry publication and consumer activation are separate owner decisions. Do not check these implementation boxes merely because the planning package exists. +- The added requirement is synchronized into canonical `openspec/specs/workflow-access/spec.md`, and this completed change is archived here. The generated delta and final validation preserve reviewed runtime and packaged-guidance bytes. +- Release preparation for 2.1.0, Git publication/merge, registry publication and consumer activation remain separate owner decisions. The checked implementation tasks above record accepted evidence, not planning-package presence or publication approval. diff --git a/openspec/specs/workflow-access/spec.md b/openspec/specs/workflow-access/spec.md index fda9554..43091d7 100644 --- a/openspec/specs/workflow-access/spec.md +++ b/openspec/specs/workflow-access/spec.md @@ -374,3 +374,38 @@ The package SHALL document unavailable historical workflow-snapshot recovery as - **THEN** it describes native compaction followed by an incompatible model switch, missing historical workflow instructions or captured reports, and unaffected Beads tracker data - **AND** it links OpenCode #57424 and identifies the unresolved local follow-up without requiring Beads access to understand the limitation - **AND** current 2.2 integration behavior is distinguished from the published beta's narrower host support + +### Requirement: Optional named task-agent profiles + +The integration SHALL offer independent opt-in Luna Max and Terra Medium task-agent profiles alongside its unchanged model-inheriting default. Fixed profiles SHALL select explicit provider, model and reasoning variant without changing the parent route or silently falling back. All profiles SHALL preserve existing Beads scope, permissions, context, ownership and lifecycle behavior and native user-configuration precedence. + +#### Scenario: Existing configuration remains unchanged + +- **WHEN** neither option is enabled, or only existing `luna: true` is enabled +- **THEN** the default `beads-task-agent` remains model-inheriting +- **AND** Luna is absent unless enabled, and enabled Luna retains `beads-task-agent-luna` with `openai/gpt-6-luna` at `max` +- **AND** Terra is not registered without `terra: true` + +#### Scenario: Terra is selected independently + +- **WHEN** `terra: true` is enabled and Luna is not enabled +- **THEN** `beads-task-agent-terra` is registered with `openai/gpt-6.1-terra` at `medium` alongside the unchanged default +- **AND** no Luna profile is added and the parent session route is unchanged + +#### Scenario: Both fixed profiles are selected + +- **WHEN** `luna: true` and `terra: true` are enabled together +- **THEN** the default, Luna and Terra profiles are independently selectable with their respective routing +- **AND** selecting a profile does not authorize additional work, synchronization, publication or closure + +#### Scenario: Terra participates in the existing task-agent lifecycle + +- **WHEN** a Terra task agent executes a permitted read-only assignment or authorized task +- **THEN** it receives the same applicable Beads context, guidance, interruption cap and permission rules as the other task-agent profiles, with identity derived from its actual invoking session and agent +- **AND** existing stop, partial-result, ownership and parent-acceptance requirements remain controlling +- **AND** native configuration overrides and plugin disposal apply without changing unrelated user artifacts + +#### Scenario: The configured provider route is unavailable + +- **WHEN** an enabled fixed profile cannot use its configured provider, model or variant +- **THEN** the host-reported inability is preserved without a plugin-selected substitute model or a claim of successful execution diff --git a/package.json b/package.json index f066b48..d06f4af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@snarkipus/opencode-beads", - "version": "2.0.0", + "version": "2.1.0", "type": "module", "description": "A maintained OpenCode V2 integration for the Beads issue tracker: bd prime context injection with a schema-migration guard, and a bounded task agent.", "author": "Matt Jackson", diff --git a/scripts/test-package.ts b/scripts/test-package.ts index db46880..c7861ca 100644 --- a/scripts/test-package.ts +++ b/scripts/test-package.ts @@ -439,6 +439,9 @@ try { if (!rules.includes("shell:git push *:ask") || taskAgent.steps !== 100) { throw new Error("Packed task agent lacks the no-push permission rules or the default steps cap"); } + if (vanilla.agents.has("beads-task-agent-terra")) { + throw new Error("Packed plugin enabled Terra without an opt-in"); + } if (vanilla.agents.has("beads-task-agent-luna")) { throw new Error("Packed plugin enabled Luna without an opt-in"); } @@ -450,6 +453,16 @@ try { ) { throw new Error("Packed plugin did not register the shared Luna Max profile"); } + const both = await setupPacked({ luna: true, terra: true }); + const terra = both.agents.get("beads-task-agent-terra"); + const terraModel = terra?.model as { providerID?: string; id?: string; variant?: string } | undefined; + if (terraModel?.providerID !== "openai" || terraModel.id !== "gpt-6.1-terra" || + terraModel.variant !== "medium" || terra?.system !== taskAgentPrompt || + terra?.mode !== "subagent" || terra?.steps !== taskAgent.steps || + JSON.stringify(terra?.permissions) !== JSON.stringify(taskAgent.permissions) || + !both.agents.has("beads-task-agent-luna")) { + throw new Error("Packed plugin did not register the shared Terra Medium profile alongside Luna"); + } const cli = path.join(consumerDir, "node_modules", ".bin", "opencode-beads"); if (await fs.exists(cli)) throw new Error("Packed package unexpectedly installed a companion CLI"); diff --git a/src/agents.ts b/src/agents.ts index 0905ca3..eeaaa72 100644 --- a/src/agents.ts +++ b/src/agents.ts @@ -3,9 +3,11 @@ import { BEADS_TASK_AGENT_DESCRIPTION, BEADS_TASK_AGENT_PROMPT } from "./guidanc export const BEADS_TASK_AGENT = "beads-task-agent"; export const BEADS_TASK_AGENT_LUNA = "beads-task-agent-luna"; +export const BEADS_TASK_AGENT_TERRA = "beads-task-agent-terra"; export const BEADS_TASK_AGENTS: ReadonlySet = new Set([ BEADS_TASK_AGENT, BEADS_TASK_AGENT_LUNA, + BEADS_TASK_AGENT_TERRA, ]); /** Default interruption cap on worker steps; never a completion target or authority to continue. */ @@ -35,16 +37,21 @@ export const TASK_AGENT_PERMISSIONS = [ /** Routing for the opt-in Luna profile, `provider/model#variant` in OpenCode terms. */ export const LUNA_MODEL = { providerID: "openai", id: "gpt-6-luna", variant: "max" } as const; +/** Routing for the opt-in Terra Medium profile. */ +export const TERRA_MODEL = { providerID: "openai", id: "gpt-6.1-terra", variant: "medium" } as const; + export interface BeadsAgentDefinition { description: string; system: string; - model?: typeof LUNA_MODEL; + model?: typeof LUNA_MODEL | typeof TERRA_MODEL; steps?: number; } export interface BeadsAgentOptions { /** Register the Luna Max profile alongside the default task agent. */ luna?: boolean; + /** Register the Terra Medium profile alongside the default task agent. */ + terra?: boolean; /** Interruption cap on worker steps; 0 removes the cap, never the assignment's scope limits. */ steps?: number; } @@ -59,6 +66,7 @@ export function beadsAgents(options: BeadsAgentOptions = {}): Record 0) base.steps = steps; const agents: Record = { [BEADS_TASK_AGENT]: base }; if (options.luna) agents[BEADS_TASK_AGENT_LUNA] = { ...base, model: LUNA_MODEL }; + if (options.terra) agents[BEADS_TASK_AGENT_TERRA] = { ...base, model: TERRA_MODEL }; return agents; } diff --git a/src/guidance.ts b/src/guidance.ts index e2c15ca..5b14452 100644 --- a/src/guidance.ts +++ b/src/guidance.ts @@ -15,9 +15,9 @@ For status or graph analysis, never claim, update, close, or modify a bead. Retu An exact assignment or explicit one-bead mode ends with that bead: report completion or a blocker and return without substitution. A single authorized operation ends with that operation; it does not authorize claiming ownership or selecting ready work. Only an already-authorized batch or goal allows continuation to another actionable bead within its stated scope. Readiness is not dispatch permission. If execution scope is missing or ambiguous, obtain it before claiming work. -For each bead authorized for task execution, first read the exact issue (typed get when available; direct shell equivalent \`bd show --json --sandbox\`); confirm it is open, actionable, within scope and appropriate; then claim atomically (typed claim when available; direct shell equivalent \`bd update --claim --json --actor='' --sandbox\`) and read back assignment. If the claim fails or readback does not confirm your assignment, stop. If an assigned bead is closed, blocked, unsuitable, missing, or otherwise not actionable, report and return without mutation or substitution. +For each bead authorized for task execution, first read the exact issue (typed get when available; direct shell equivalent \`bd show --json --sandbox\`) and verify its current scope, state and assignee. When starting new work, confirm it is open, actionable, within scope and appropriate; then claim atomically (typed claim when available; direct shell equivalent \`bd update --claim --json --actor='' --sandbox\`) and read back assignment. If the claim fails or readback does not confirm your assignment, stop. When resuming in_progress work assigned to your actual executor actor, verify ownership and authority and continue without reopening or claiming it again. A deliberate worker-to-parent handoff transfers custody explicitly and retains in_progress while qualification or review is outstanding; a worker process exiting does not complete or reset the task. If an assigned bead is closed, blocked, unsuitable, missing, or otherwise not actionable, report and return without mutation or substitution. -Implement within scope and run relevant authorized validation. Append per-bead checkpoints with \`--append-notes\`, preserving attempts, measured outcomes, rationale, validation, references, blockers and the next authorized action. Close only with acceptance evidence and closure authority; unresolved acceptance or failed validation remains incomplete. If the parent owns acceptance or closure, return evidence and leave the bead open. Continue within an authorized batch only after recording the current bead's outcome and confirming that continuation meets its acceptance and authority gates. +Implement within scope and run relevant authorized validation. Use \`--append-notes\` for incremental checkpoints; replace working notes with \`--notes\` via permissioned direct shell only for a deliberate current-state handoff carrying forward key decisions, rejected approaches, blockers and next action. Keep title, description and acceptance stable apart from authorized corrections or clarifications. See the packaged \`oc-beads\` skill for issue-writing and handoff examples. Close only with acceptance evidence and closure authority; unresolved acceptance or failed validation remains incomplete. If the parent owns acceptance or closure, return evidence and leave the bead open. Continue within an authorized batch only after recording the current bead's outcome and confirming that continuation meets its acceptance and authority gates. Discovery does not add execution authority. Report follow-ups; create them only when authorized, with \`discovered-from:\` and a parent only when structurally appropriate. Leave new work unassigned unless assignment is intentional. Never claim or implement discoveries merely because you recorded them. @@ -40,7 +40,7 @@ const BEADS_RECOVERY_GUIDANCE = `## Work continuity At the first eligible request after a fresh session, compaction, interruption, child handoff or important change, retrieve the assigned task and relevant reusable knowledge under the current permissions and guard. Re-read current state when external writers may have changed it; cached absence is not proof of absence. Missing, withheld, failed and intentionally empty workflow context are different outcomes; never bypass a hold with manual prime. -Append task-specific attempts, measured outcomes, rationale, blockers and the next authorized action at meaningful transitions. Keep hypotheses qualified. Reusable project memory is for validated findings with scope and evidence: search or recall relevant existing knowledge before adding or correcting it. No redundant write quota applies. +Use \`--append-notes\` for incremental checkpoints at meaningful transitions; a deliberate current-state handoff may replace working notes with \`--notes\` via permissioned direct shell while carrying forward relevant decisions, rejected approaches, blockers and next action. Keep title, description and acceptance stable apart from authorized corrections or clarifications. See the packaged \`oc-beads\` skill for field roles and examples. Keep hypotheses qualified. Reusable project memory is for validated findings with scope and evidence: search or recall relevant existing knowledge before adding or correcting it. No redundant write quota applies. Only actual CLI results acknowledge persistence. A timeout or interrupted append/remember is uncertain: inspect durable state before another write, with no blind retry. A landed memory with failed or indeterminate commit retains its reference and qualified status; do not force it or automatically commit. Empty found memory differs from a missing key. Every authorized write uses the actual executor's explicit Beads actor, separate from the host permission agent; never use human Git identity or a model-supplied impersonation. diff --git a/src/host.ts b/src/host.ts index 57fed1d..97662a1 100644 --- a/src/host.ts +++ b/src/host.ts @@ -125,6 +125,7 @@ export async function setupBeads( const stepsOption = ctx.options?.taskAgentSteps; const agents = beadsAgents({ luna: ctx.options?.luna === true, + terra: ctx.options?.terra === true, steps: typeof stepsOption === "number" && Number.isInteger(stepsOption) && stepsOption >= 0 ? stepsOption : undefined, }); diff --git a/src/workflows.ts b/src/workflows.ts index 0983693..8650e7f 100644 --- a/src/workflows.ts +++ b/src/workflows.ts @@ -41,7 +41,7 @@ export const WORKFLOWS = { stats: ["Report the issue-database overview using bd status (alias bd stats); use oc-beads:diagnostics for integration health. Do not claim work.", "CLI_REFERENCE"], sync: ["Perform supported bd sync --no-adopt using existing project configuration, actual executor actor and applicable sandbox policy, then report the observed outcome. A bare invocation requests synchronization; a missing configured remote is a blocker. Use an explicitly selected existing remote only when unambiguous; no --yes, adoption, provisioning, force resolution or manual pull/push repair loop. Explicit adoption is a distinct request, never inferred. Distinguish Dolt-remote synchronization from bd federation sync and removed JSONL sync.", "CLI_REFERENCE"], template: ["Discover actual available templates/formulas using supported installed commands, optionally inspect a requested one, and report entries or an honest unavailable result. Help inspection is preparation; do not instantiate or execute a formula automatically.", "MOLECULES"], - update: ["Apply only requested field changes; use an atomic claim for authorized execution and append-style progress notes. Replacement of notes is intentional, never routine.", "RESUMABILITY"], + update: ["Apply only requested field changes; use an atomic claim for authorized execution and append-style progress notes. Replace working notes only for a deliberate current-state handoff that preserves relevant learning.", "RESUMABILITY"], version: ["Report actual installed CLI, package and host versions and qualification limits; do not hardcode a latest version or install/upgrade anything.", "CLI_REFERENCE"], workflow: ["Guide native Beads work and recovery: inspect scope, read prior state, claim atomically, checkpoint meaningful learning, validate and return evidence. Continue only within an authorized batch/goal.", "WORKFLOWS"], } as const; diff --git a/tests/docs.test.ts b/tests/docs.test.ts index 1598201..0f26969 100644 --- a/tests/docs.test.ts +++ b/tests/docs.test.ts @@ -273,9 +273,10 @@ describe("documentation contracts", () => { expect(sdkHistory).toContain('Bun.spawn(["bd", "prime"]'); }); - test("keeps the compatibility record on the selected plugin 2.0 OpenCode baseline", () => { + test("separates accepted base compatibility from the representative Terra qualification", () => { expect(userGuide).toContain("| OpenCode (historical beta.5) | `>=2.1.1 <2.2` | 2.1.1 (bounded accepted evidence) |"); - expect(userGuide).toContain(`| OpenCode (${packageManifest.version}) | \`>=2.2.6 <2.3\` | 2.2.6 (accepted native and genuine-model qualification) |`); + expect(userGuide).toContain("| OpenCode (2.0.0) | `>=2.2.6 <2.3` | 2.2.6 (accepted native and genuine-model qualification) |"); + expect(userGuide).toContain(`| OpenCode (${packageManifest.version} candidate) | \`>=2.2.6 <2.3\` | Unchanged base uses the 2.0.0 evidence; one read-only Terra Medium child dispatch on 2.2.6 |`); expect(userGuide).toContain("| OpenCode (stable 1.0.2 historical) | 2.0.26 | 2.0.26 |"); expect(userGuide).toContain("| `bd` CLI | 1.3.1 through 1.x | 1.3.4 |"); expect(readme).toContain("| OpenCode | `>=2.2.6 <2.3` |"); @@ -315,7 +316,7 @@ describe("documentation contracts", () => { for (const heading of ["## Beyond Claude Code", "## Deliberate divergences", "## Not exercised"]) { expect(parity).toContain(heading); } - for (const option of ["refreshAfterIdleMinutes", "stealth", "taskAgentSteps", "autoMigrate", "luna"]) { + for (const option of ["refreshAfterIdleMinutes", "stealth", "taskAgentSteps", "autoMigrate", "luna", "terra"]) { expect(userGuide).toContain(`| \`${option}\` |`); } }); @@ -326,6 +327,10 @@ describe("documentation contracts", () => { expect(userGuide).toContain("`bd migrate schema`"); expect(userGuide).toContain("| `autoMigrate` | `false` |"); expect(userGuide).toContain("| `luna` | `false` |"); + expect(userGuide).toContain("| `terra` | `false` |"); + expect(userGuide).toContain("`openai/gpt-6.1-terra#medium`"); + expect(userGuide).toContain('"options": { "luna": true, "autoMigrate": false }'); + expect(userGuide).toContain("Terra is introduced in `2.1.0`; published `2.0.0` does not include it."); expect(userGuide).not.toContain('"beads-task-agent-luna": {}'); expect(artifactPolicy).toContain("schema migration guard"); }); @@ -342,11 +347,12 @@ describe("documentation contracts", () => { expect(artifactPolicy).toContain("eligible primary agents and `beads-task-agent`"); }); - test("records the retired vendoring decision and the historical baselines", () => { - expect(userGuide).toContain("The package vendors nothing from upstream."); + test("records the retired vendoring decision and the historical baselines", async () => { + expect(userGuide).toContain("attributed MIT-licensed excerpts"); expect(userGuide).toContain("The historical integration comparison remains Beads v1.3.1"); expect(userGuide).toContain("c1c4b642ac1c08d8c828007a1c2f96e47e43ef7c"); - expect(artifactPolicy).toContain("The package vendors no upstream Beads artifacts."); + expect(artifactPolicy).toContain("attributed MIT-licensed excerpts"); + expect(await fs.readFile("assets/oc-beads/THIRD_PARTY_NOTICES.md", "utf8")).toContain("Copyright (c) 2025 Beads Contributors"); expect(artifactPolicy).toContain("| `agents/task-agent.md` | Retired in 1.0.0 (`opencode-beads-w5y`) |"); expect(artifactPolicy).toContain("### Rationale for retiring vendoring"); expect(artifactPolicy).toContain("Codex ships skills and hooks but no agent."); diff --git a/tests/guidance.test.ts b/tests/guidance.test.ts index f1a4293..e83e59b 100644 --- a/tests/guidance.test.ts +++ b/tests/guidance.test.ts @@ -39,7 +39,10 @@ describe("project-owned task-agent contract", () => { expect(prompt).toContain("claim fails or readback does not confirm your assignment, stop"); expect(prompt).toContain("Discovery does not add execution authority"); expect(prompt).toContain("discovered-from:"); - expect(prompt).toContain("Append per-bead checkpoints"); + expect(prompt).toContain("current-state handoff"); + expect(prompt).toContain("--notes"); + expect(prompt).toContain("authorized corrections or clarifications"); + expect(prompt).toContain("oc-beads"); expect(prompt).toContain("unresolved acceptance or failed validation remains incomplete"); expect(prompt).toContain("If the parent owns acceptance or closure, return evidence and leave the bead open"); expect(prompt).toContain("permission denial, cancellation, deliberate stop"); @@ -48,6 +51,14 @@ describe("project-owned task-agent contract", () => { expect(prompt).not.toContain("otherwise choose one highest-priority ready bead"); }); + test("distinguishes new claims from resumption and parent handoff", () => { + for (const text of [BEADS_TASK_AGENT_PROMPT, beadsGuidance("primary")]) { + expect(text).toContain("When starting new work, confirm it is open"); + expect(text).toContain("continue without reopening or claiming it again"); + expect(text).toContain("retains in_progress while qualification or review is outstanding"); + } + }); + test("carries executor attribution and separates planning/review acceptance", () => { for (const text of [BEADS_TASK_AGENT_PROMPT, beadsGuidance("primary"), BEADS_TASK_AGENT_PROMPT + beadsGuidance("task-agent")]) { expect(text).toContain("command-scoped"); @@ -71,6 +82,11 @@ describe("project-owned task-agent contract", () => { const taskAgent = beadsGuidance("task-agent"); for (const guidance of [primary, taskAgent]) { expect(guidance).toMatch(/^\n[\s\S]*\n<\/beads-guidance>$/); + expect(guidance).toContain("--append-notes"); + expect(guidance).toContain("--notes"); + expect(guidance).toContain("current-state handoff"); + expect(guidance).toContain("authorized corrections or clarifications"); + expect(guidance).toContain("oc-beads"); expect(guidance).toContain("Native shell is direct-only"); expect(guidance).toContain("Do not commit, push, or run Dolt synchronization automatically"); expect(guidance).toContain("explicit command invocation is the invoking user's bounded request"); diff --git a/tests/host.test.ts b/tests/host.test.ts index bd8facd..3f830ec 100644 --- a/tests/host.test.ts +++ b/tests/host.test.ts @@ -463,6 +463,31 @@ describe("setupBeads", () => { }); + test("registers Terra independently and with Luna, with shared policy and context", async () => { + const ready = { runtime: { guard: async () => ({ kind: "ready" as const }), prime: async () => "PRIME" } }; + for (const luna of [false, true]) { + const f = fakeContext({ pluginOptions: { terra: true, luna, taskAgentSteps: 12 } }); + const cleanup = await setupBeads(f.ctx, ready); + expect([...f.agents.keys()]).toEqual(luna + ? ["beads-task-agent", "beads-task-agent-luna", "beads-task-agent-terra"] + : ["beads-task-agent", "beads-task-agent-terra"]); + const base = f.agents.get("beads-task-agent")!; + const terra = f.agents.get("beads-task-agent-terra")!; + expect(base.model).toBeUndefined(); + expect(terra.model).toEqual({ providerID: "openai", id: "gpt-6.1-terra", variant: "medium" }); + expect(terra.system).toBe(base.system); + expect(terra.description).toBe(base.description); + expect(terra.mode).toBe(base.mode); + expect(terra.permissions).toEqual(base.permissions); + expect(terra.steps).toBe(base.steps); + if (luna) expect(f.agents.get("beads-task-agent-luna")?.model).toEqual({ providerID: "openai", id: "gpt-6-luna", variant: "max" }); + expect(await f.request("terra-child", "beads-task-agent-terra")).toEqual([ + renderBeadsContext("PRIME", "task-agent", { sessionID: "terra-child", agent: "beads-task-agent-terra" }), + ]); + await cleanup(); + } + }); + test("appends rendered prime to eligible requests through the context hook only", async () => { const f = fakeContext(); const prime = mock(async (_directory: string) => "PRIME"); diff --git a/tests/upstream-review.test.ts b/tests/upstream-review.test.ts index 5d93166..42776e4 100644 --- a/tests/upstream-review.test.ts +++ b/tests/upstream-review.test.ts @@ -239,6 +239,8 @@ describe("advisory marketplace MAIN source collector", () => { const packagePath = resolve(import.meta.dir, "../package.json"); const actualPackage = await fs.readFile(packagePath, "utf8"); const main = JSON.parse(actualInventory).marketplace_main; + expect(main.commit).toBe("4a67d0d0288c1b4ee23e17fc896f47616931ba2d"); + expect(main.files.find((f: { path: string }) => f.path === "LICENSE")?.git_blob).toBe("2a187917a0b9e8ea3ab3db2d9e60649f0e2e4ea5"); const selected = main.files.map((f: { path: string; git_blob: string }) => ({ path: f.path, sha: f.git_blob, type: "blob", mode: "100644", })); diff --git a/tests/workflows.test.ts b/tests/workflows.test.ts index 57392d8..4a7dd08 100644 --- a/tests/workflows.test.ts +++ b/tests/workflows.test.ts @@ -88,6 +88,8 @@ describe("oc-beads guidance assets", () => { test("teaches append checkpoints, selective memory, and bounded actor-owned work", () => { const skill = readFileSync(skillPath, "utf8") const workflows = readFileSync(resolve(assetRoot, "resources/WORKFLOWS.md"), "utf8") + const resumability = readFileSync(resolve(assetRoot, "resources/RESUMABILITY.md"), "utf8") + const creation = readFileSync(resolve(assetRoot, "resources/ISSUE_CREATION.md"), "utf8") const guidance = `${skill}\n${workflows}` expect(guidance).toContain("--append-notes") @@ -97,7 +99,20 @@ describe("oc-beads guidance assets", () => { expect(guidance).toContain("assignee") expect(guidance).toContain("reusable knowledge") expect(guidance).toContain("authorized batch") - expect(guidance).not.toMatch(/bd update[^\n]*\s--notes\s/) + expect(guidance).toContain("--notes=") + expect(guidance).toContain("typed-only") + for (const text of [skill, workflows, resumability]) { + expect(text).toContain("--append-notes") + expect(text).toContain("--notes") + } + for (const text of [creation, resumability, workflows]) { + expect(text).toContain("Verbatim upstream excerpt") + expect(text).toContain("OpenCode adaptation") + expect(text).toContain("5ac194105c138ca799bc2f6534c8f92712d8d782") + } + expect(skill).toContain("acceptance states stable, verifiable outcomes") + expect(workflows).toContain("OpenCode adaptation") + expect(workflows).toContain("5ac194105c138ca799bc2f6534c8f92712d8d782") }) test("keeps current CLI access honest without claiming host prerequisites or automatic setup", () => { @@ -438,7 +453,7 @@ describe("packaged native workflows", () => { } actual[c.name] = createHash("sha256").update(JSON.stringify({ description: c.description, sent })).digest("hex"); } - expect(actual).toEqual(baseline.commands); + expect(actual).toEqual({ ...baseline.commands, "oc-beads:update": "b4f6a0e8b2729bab4361a6252a86217eac825b6c66f2db8d3dcc0f1803de7b25" }); }); test("forwards exact scope and partial-handoff authority cues without selecting or claiming work", async () => {