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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
MIT License
The MIT License

Copyright (c) 2026 John Dewey

Expand All @@ -9,13 +9,13 @@ 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 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.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
19 changes: 15 additions & 4 deletions openspec/changes/specify-agent-tool-invocation/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

## 2. Apply to each repository

- [ ] 2.1 `osapi` — blocked: it has no `AGENTS.md`, pending its CONTRIBUTING
conversion (`standardize-repository-layout` task 4.5)
- [x] 2.1 `osapi` — `AGENTS.md` written as part of its layout conversion
(osapi-io/osapi#450)
- [x] 2.2 `gohai`
- [x] 2.3 `nats-client`
- [x] 2.4 `nats-server`
Expand All @@ -16,5 +16,16 @@

## 3. Verification

- [ ] 3.1 Confirm every `AGENTS.md` states how tools are invoked
- [ ] 3.2 Confirm every repository declares the tools its recipes invoke
- [x] 3.1 Confirm every `AGENTS.md` states how tools are invoked. All seven
carry the `mise exec -- just test` form and the explanation of why a bare
`just` resolves differently for an agent
- [ ] 3.2 Confirm every repository declares the tools its recipes invoke. Six of
seven do. `osapi` was missing `uv`, which `just md-fmt` invokes through `uvx`;
it is now declared (osapi-io/osapi#450). One gap remains: `osapi`'s `generate`
recipe invokes `redocly`, which no repository file declares — it resolves from
whatever the developer installed globally. Declaring it is not a one-line fix:
the version mise supplies (2.46.1) quotes YAML scalars differently from the
version currently on the developer's path (2.19.1), so the committed combined
spec and both generated SDKs change the first time anyone runs `just generate`
against it. That regeneration is its own change, and nothing in continuous
integration runs `generate`, so the drift is invisible until someone does
17 changes: 10 additions & 7 deletions openspec/changes/specify-documentation-homes/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@
- [x] 3.5 `osapi` — propose a capability from `docs/sidebar/sdk/guidelines.md`;
"never expose generated types" and "JSON tags required" bind every consumer of
`pkg/sdk`, including `osapi-orchestrator`
- [ ] 3.6 `osapi` — resolve the three-way duplication of branching, commit
messages, linting, and test conventions across `CLAUDE.md`, `development.md`,
and `testing.md` before the root `CONTRIBUTING.md` is written, so the
conversion has one source to draw from
- [x] 3.6 `osapi` — the three-way duplication of branching, commit messages,
linting, and test conventions across `CLAUDE.md`, `development.md`, and
`testing.md` is resolved into the root `CONTRIBUTING.md`; the two site pages
are now pointers to it (osapi-io/osapi#450)
- [ ] 3.9 `osapi` — capture "job creation goes through domain endpoints" as a
requirement. Removing `docs/plans/` deletes its only written record: the rule
still binds (the sole `post:` on the job API is `/api/job/{id}/retry`, an
Expand All @@ -67,9 +67,12 @@
change before removal
- [x] 4.2 `osapi` — remove `docs/plans/` (70 documents)
- [x] 4.3 `osapi-orchestrator` — remove `docs/plans/` (6 documents)
- [ ] 4.4 Both — note in `CONTRIBUTING.md` that design records are changes in
the corpus. Done for `osapi-orchestrator`; `osapi` has no root
`CONTRIBUTING.md` until `standardize-repository-layout` task 4.5 writes one
- [x] 4.4 Both — `CONTRIBUTING.md` notes that design records are changes in the
corpus. `osapi-orchestrator` already did; `osapi`'s root `CONTRIBUTING.md` now
does (osapi-io/osapi#450). Applying this surfaced a stale pointer:
`osapi-orchestrator`'s `AGENTS.md` still sent readers to the `docs/plans/`
removed by task 4.3, contradicting its own `CONTRIBUTING.md`
(osapi-io/osapi-orchestrator#74)

## 4a. Make the corpus navigable

Expand Down
31 changes: 26 additions & 5 deletions openspec/changes/specify-go-code-standards/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,36 @@
- [x] 2.2 `nats-client` — `CONTRIBUTING.md`
- [x] 2.3 `nats-server` — `CONTRIBUTING.md`
- [x] 2.4 `osapi-orchestrator` — `CONTRIBUTING.md`
- [ ] 2.5 `osapi` — `CLAUDE.md` drops `Code Standards`, and the conventions
duplicated into `development.md` and `testing.md` resolve to one source
- [x] 2.5 `osapi` — `CLAUDE.md` dropped `Code Standards`, and the conventions
duplicated into `development.md` and `testing.md` now resolve to the root
`CONTRIBUTING.md`, which points at this capability rather than restating it
(osapi-io/osapi#450)

## 3. Verification

- [x] 3.1 Confirm no `types.go` contains a function
- [x] 3.2 Confirm no repository holds a generically named file
- [x] 3.3 Confirm every test package uses a table-driven suite
- [ ] 3.4 Confirm no mock is hand-written where an interface is mocked
- [ ] 3.4 Confirm no mock is hand-written where an interface is mocked. Three
remain, each a struct written to satisfy a project-owned interface:
`fakeCollector` in `gohai` (`internal/collector/registry_public_test.go`),
`mockRenderer` in `osapi-orchestrator`
(`pkg/orchestrator/orchestrator_test.go`), and `mockPKISigner` in `osapi`
(`internal/job/client/signing_public_test.go`). `mockPKISigner` signs with a
real ed25519 key, so it reads as a real implementation rather than a mock and
may fall under the carve-out; the other two do not. `gohai` and
`osapi-orchestrator` declare no mocking library, so satisfying this needs a
decision on introducing one, not just a regeneration
- [ ] 3.5 Confirm no test uses an exported alias to re-cover behavior the
caller's own test already reaches
- [ ] 3.6 Confirm no shared convention is stated in two places
caller's own test already reaches. Not yet established: 65 `export_test.go`
files exist (32 in `gohai`, 32 in `osapi`, 1 in `osapi-orchestrator`), and the
requirement turns on what each exposure is *for*, which no search can decide.
This needs a file-by-file audit
- [ ] 3.6 Confirm no shared convention is stated in two places. `nats-client`
and `nats-server` point at the capability without restating it, and `osapi`
now does the same. `gohai` and `osapi-orchestrator` point at it *and* restate
it — `osapi-orchestrator` under `Function Signatures`, `Testing`,
`Go Patterns`, and `Linting`; `gohai` under `Function Signatures`. Both say
the specification wins where they disagree, which acknowledges the duplication
rather than removing it. Resolving this means deleting the restatements, which
reverses a deliberate choice recorded when those repositories were converted
116 changes: 81 additions & 35 deletions openspec/changes/standardize-repository-layout/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ structure for its type.
- [x] 4.3 `nats-server` (Go library)
- [x] 4.4 `osapi-orchestrator` (Go library, pending the open question on its
type)
- [ ] 4.5 `osapi` (main product; file layout only, README exempt) — the only
repository with neither a root `CONTRIBUTING.md` nor `AGENTS.md`, a 917-line
`CLAUDE.md`, and three competing contributing documents:
`docs/CONTRIBUTING.md` (60 lines),
`docs/docs/sidebar/development/contributing.md` (109), and
`ui/docs/contributing.md`
- [x] 4.5 `osapi` (main product; file layout only, README exempt) — converted in
osapi-io/osapi#450. The 917-line `CLAUDE.md` split by audience: contributor
conventions to a root `CONTRIBUTING.md`, agent-specific guidance to
`AGENTS.md`, and the nine-step domain walkthrough to its own site page.
`CLAUDE.md` is now a pointer. Of the three competing contributing documents,
`docs/CONTRIBUTING.md` and `ui/docs/contributing.md` were removed and
`docs/docs/sidebar/development/contributing.md` reduced to a pointer.
`ui/docs/architecture.md` was kept: it holds a UI-primitives table, a `Text`
variant reference, and a hooks table the site's `ui.md` does not, so removing
it would lose content. Folding it in belongs to `specify-documentation-homes`
- [x] 4.6 `osapi-ui` — not converted; recorded as deprecated instead
- [x] 4.7 `specs` (documentation) — its `CODE_OF_CONDUCT.md` named no
enforcement contact, leaving no way to report a violation, and its `LICENSE`
Expand All @@ -59,48 +63,90 @@ structure for its type.

No workflow in any repository uses mise; all seven provision tools twice.

- [ ] 5.1 `osapi`, `gohai`, `osapi-orchestrator`, `nats-client`, `nats-server` —
declare `just` in `.mise.toml`. None does, so it comes from the developer's
system: Homebrew's 1.45.0 formats a boolean setting as `:= true` while the
version CI installs writes the bare form, and each rejects the other
- [ ] 5.1a Record which version `extractions/setup-just` installs, and declare
that version, so `mise install` and CI agree
- [x] 5.1 `osapi`, `gohai`, `osapi-orchestrator`, `nats-client`, `nats-server` —
all five now declare `just` in `.mise.toml`, so it no longer comes from the
developer's system. `osapi` was also invoking `uv` through `uvx` without
declaring it (osapi-io/osapi#450)
- [x] 5.1a Record which version `extractions/setup-just` installs. No workflow
in any repository passes `just-version`, so the action installs the latest
release, and every `.mise.toml` declares `just = "latest"`. Both paths already
float together, which is what the requirement asks for where nothing automates
the version — so the pin this task called for would violate it. Recorded
rather than applied
- [ ] 5.2 Confirm `.mise.toml` and the workflow resolve to the same version for
every tool, floating or pinned
- [ ] 5.3 Confirm no tool is pinned in one path and floating in the other
every tool, floating or pinned. `just`, `bun`, and `uv` float on both sides;
`node` is `22` in both. `go` does not agree: `.mise.toml` declares `1.25`
while every workflow sets `go-version: stable`. They resolve alike today and
diverge the day 1.26 ships
- [ ] 5.3 Confirm no tool is pinned in one path and floating in the other. `go`
fails it, in all five Go repositories. Fixing it is a choice the requirement
narrows but does not make: nothing bumps `.mise.toml`, so the requirement's
own answer is that both paths float, which means `go = "latest"` locally
rather than pinning CI to `1.25`. That changes which toolchain every developer
builds with, so it wants a decision rather than a sweep
- [x] 5.5 `osapi-orchestrator` — `actions/setup-go@v6` while every other
repository uses `@v7`
- [ ] 5.6 Confirm Dependabot raises each new pin, in both locations
- [x] 5.6 Confirm Dependabot raises each new pin, in both locations. It watches
`github-actions` in all seven repositories and `gomod` in the five Go ones. It
does not watch `.mise.toml`, and no ecosystem exists that would — which is why
the tools declared there float rather than pin

## 6. Resolve the deprecated repositories

- [ ] 6.1 `osapi-io-taskfiles` — record deprecation at the top of its README,
naming `osapi-justfiles` as the replacement. Blocked: the repository is now
archived and cannot be pushed to. Either unarchive briefly to add the notice,
or accept the archived state as the signal and drop this task
- [x] 6.1 `osapi-io-taskfiles` — dropped. The task was to record deprecation at
the top of its README, but the repository is archived and cannot be pushed to.
Of the two ways out the task offered, the archived state is accepted as the
signal: GitHub already marks it read-only and labels it archived, which is the
half of the requirement that changes what a reader sees. Unarchiving a
repository nothing consumes, to add a sentence, and re-archiving it buys a
line of prose at the cost of disturbing the signal that is already correct
- [x] 6.2 Archive `osapi-sdk` on GitHub
- [x] 6.3 Archive `osapi-ui` on GitHub
- [x] 6.4 Archive `osapi-io-taskfiles` on GitHub

## 6a. Correct the react module override

- [ ] 6a.1 `osapi-justfiles` — make the `react` module take its directory as
configuration instead of a shim setting a working directory
- [ ] 6a.2 `osapi` — drop the tracked `.just/remote/react.mod.just` and its
`.gitignore` exception once the module is configurable
- [x] 6a.1 `osapi-justfiles` — the `react` module takes `react_dir` as
configuration and fails at parse time when a consumer omits it, rather than
relying on a shim to set a working directory
- [x] 6a.2 `osapi` — `.just/remote/react.mod.just` is gone and nothing under
`.just/` is tracked; `.gitignore` ignores `.just/remote/*` with no exception.
The root justfile sets `react_dir := "ui"` directly

## 7. Verification

- [ ] 7.1 Confirm every in-scope repository carries the required files
- [ ] 7.2 Confirm no repository still contains `docs/contributing.md` or
`docs/development.md`
- [ ] 7.3 Confirm no cross-repository link still points at the old paths
- [ ] 7.4 Confirm each README uses only vocabulary sections, in order
- [ ] 7.5 Confirm `LICENSE`, `AI_POLICY.md`, and `CODE_OF_CONDUCT.md` are
byte-identical everywhere
- [x] 7.1 Confirm every in-scope repository carries the required files. All
seven carry `README.md`, `LICENSE`, `AI_POLICY.md`, `CODE_OF_CONDUCT.md`,
`CONTRIBUTING.md`, `AGENTS.md`, `CLAUDE.md`, and `.mise.toml`
- [x] 7.2 Confirm no repository still contains `docs/contributing.md` or
`docs/development.md`. None does. `osapi` was the last, and its two remaining
copies under `ui/docs/` went with the conversion (osapi-io/osapi#450)
- [x] 7.3 Confirm no cross-repository link still points at the old paths. The
inbound links in `osapi`'s two architecture pages now point at the root
`CONTRIBUTING.md`, and the site builds with no broken link. One stale pointer
was found and fixed in the other direction: `osapi-orchestrator`'s `AGENTS.md`
still named the removed `docs/plans/` (osapi-io/osapi-orchestrator#74)
- [ ] 7.4 Confirm each README uses only vocabulary sections, in order. Not yet
established for the six non-exempt repositories. `osapi` is exempt from the
section set as the main product, and it gained `## 🤝 Contributing` so the new
root guide is reachable from it
- [x] 7.5 Confirm `LICENSE`, `AI_POLICY.md`, and `CODE_OF_CONDUCT.md` are
byte-identical everywhere. `AI_POLICY.md` and `CODE_OF_CONDUCT.md` are, in all
seven. `LICENSE` was not: `specs` carried a differently titled and differently
wrapped variant, which this change replaces with the canonical copy. The rest
differ only on the copyright year, as the requirement allows — 2024 for
`osapi`, 2025 for the two NATS libraries, 2026 for the rest
- [ ] 7.6 Confirm no `.mise.toml` and no workflow floats a tool whose output a
check compares
- [ ] 7.7 Confirm `just test` locally and CI agree on every repository
- [ ] 7.8 Confirm every deprecated repository is archived on GitHub
- [ ] 7.9 Confirm no tracked file was removed on the basis of its path without
its content being read
check compares. Unresolved while 5.2 and 5.3 are: `go` is declared `1.25`
locally and `stable` in every workflow, and `go-fmt-check` compares its output
- [ ] 7.7 Confirm `just test` locally and CI agree on every repository. Not
established across all seven. The conversion ran `md-fmt-check`,
`docusaurus-fmt-check`, and `docusaurus-build` in `osapi` and `md-fmt-check`
in `osapi-orchestrator`; both pass
- [x] 7.8 Confirm every deprecated repository is archived on GitHub.
`osapi-sdk`, `osapi-ui`, and `osapi-io-taskfiles` all report archived
- [x] 7.9 Confirm no tracked file was removed on the basis of its path without
its content being read. Every file removed in osapi-io/osapi#450 was read
first, and that is what kept `ui/docs/architecture.md`: its path matched the
stale osapi-ui leftovers beside it, but its contents hold a component
reference the site does not carry