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
8 changes: 1 addition & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,10 @@ jobs:
with:
go-version-file: go.mod
cache: true
- name: Check Go formatting and shipped logic size
- name: Check Go formatting
run: |
files=$(find . -type f -name '*.go' ! -path './.git/*' ! -path './.worktrees/*' | sort)
test -z "$(printf '%s\n' "$files" | xargs gofmt -l)"
production=$(printf '%s\n' "$files" | awk '!/_test\.go$/')
go_lines=$(printf '%s\n' "$production" | xargs wc -l | awk 'END { print $1 }')
shell_lines=$(wc -l < install.sh | tr -d ' ')
lines=$((go_lines + shell_lines))
echo "shipped logic lines: $lines (1,500 target; 2,000 absolute ceiling)"
test "$lines" -le 2000
- run: go test ./...
- run: go vet ./...
- name: Validate experiment registry
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/release-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ on:
workflow_call:
inputs:
tag:
description: Published stable-shaped release tag (vN.N.N)
description: Published current release tag (vN.N.N)
required: true
type: string
workflow_dispatch:
inputs:
tag:
description: Published stable-shaped release tag (vN.N.N)
description: Published current release tag (vN.N.N)
required: true
type: string

Expand All @@ -31,7 +31,7 @@ jobs:
RELEASE_TAG: ${{ inputs.tag }}
run: |
if ! printf '%s\n' "$RELEASE_TAG" | awk '/^v[0-9]+\.[0-9]+\.[0-9]+$/ { ok=1 } END { exit(ok ? 0 : 1) }'; then
echo "release smoke requires an already-published stable-shaped vN.N.N tag" >&2
echo "release smoke requires the published current stable-shaped vN.N.N tag" >&2
exit 1
fi
echo "tag=$RELEASE_TAG" >> "$GITHUB_OUTPUT"
Expand All @@ -51,8 +51,8 @@ jobs:
echo "- Release: \`$RELEASE_TAG\`"
echo "- Result: \`$SMOKE_OUTCOME\`"
echo "- Runner architecture: \`$(uname -m)\`"
echo "- Proved: live release manifest, checksum, candidate self-test, binary install, native PreToolUse/PostToolUse title finalization, settled state and inventory, prepared active-task uninstall, fixture-simulated archived-control cleanup/restoration, completed-controller preservation, and binary-last teardown. Real native archive control remains a separate release canary."
echo "- Not proved: real Codex auth, rendered Desktop titles, Luna behavior, or architectures other than this runner."
echo "- Proved: published bootstrap, manifest, checksum, candidate version and self-test; dry-run collision refusal; exact 2.2.1 reset fingerprint, --reset gate, filesystem reset, and teardown; title-core readiness without the updater; a two-page sorted current-title plan with zero production title writes, installed decoder presence, and a simulated raw JSON-string mounted setter result plus one-attempt failure; complete multi-page onboarding preview with deduplication and failure-before-writes; uncapped complete-snapshot subject preparation with zero per-target production RPCs, followed by simulated serial mounted read-before-set revalidation using raw JSON-string tool results, drift and wrong-task-ID skipping, one-attempt writes, exact accounting, and no retry; no hooks.json mutation or SQLite dependency; real-launchd automatic and direct current updates with restart reporting; an update/uninstall overlap; and complete uninstall JSON with binary-last teardown and unrelated-content preservation."
echo "- Not proved: real Codex auth, native automation deletion or exact-task unpin, rendered Desktop repaint, clean-restart persistence, native timeout behavior, a newer-version partial update, or architectures other than this runner. Those seams require the recorded local Desktop and fault-injection canaries."
echo "- Deployment timing: a Pages/CDN lag can make the live bootstrap older than the release commit; that red result still requires operator investigation."
echo "- A red result marks the published release for operator action; this workflow does not delete, demote, or retry a release."
} >> "$GITHUB_STEP_SUMMARY"
8 changes: 1 addition & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,10 @@ jobs:
in_section && /^## / { exit }
in_section { print }
' CHANGELOG.md > release-notes.md
- name: Check Go formatting and shipped logic size
- name: Check Go formatting
run: |
files=$(find . -type f -name '*.go' ! -path './.git/*' ! -path './.worktrees/*' | sort)
test -z "$(printf '%s\n' "$files" | xargs gofmt -l)"
production=$(printf '%s\n' "$files" | awk '!/_test\.go$/')
go_lines=$(printf '%s\n' "$production" | xargs wc -l | awk 'END { print $1 }')
shell_lines=$(wc -l < install.sh | tr -d ' ')
lines=$((go_lines + shell_lines))
echo "shipped logic lines: $lines (1,500 target; 2,000 absolute ceiling)"
test "$lines" -le 2000
- run: go test ./...
- run: go vet ./...
- name: Validate experiment registry
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

## Unreleased

## v3.0.0 - 2026-08-08

### Changed

- Reset ThreadBear to one terminal local title command that preserves exact subjects, changes only the status icon, keeps actions in response prose, and leaves unsafe titles unchanged.
- Made one short-lived official Codex App Server the read/planning authority and the mounted app-native setter the sole title writer: one prepared current-task title, one-time decoding of native JSON-text results, at most one native call, and exact returned ID/title validation, with no SQLite access, detached write, fallback, or retry.
- Replaced controller migration with explicit, uncapped onboarding that prepares a fresh complete snapshot, immediately checks each app-native task ID and title before its one possible write, reports honest updated, skipped, unchanged, and unconfirmed counts, and discloses that cached historical rows may redraw on project reopen or restart.
- Removed title interception and configuration dependencies; installation now manages only the binary, subject records, guidance, skill, and daily update-only LaunchAgent.
- Separated title-core readiness from updater health, made successful updates report restart requirements, made uninstall wait for any in-flight updater before teardown, and made queued updater processes reject a replaced installed binary; pre-install failures preserve the old install while later local write failures report a rerunnable partial with the binary last.
- Made 2.2.1 upgrades an explicit reset that previews the exact automation and former persistent task, verifies deletion and unpinning before filesystem mutation, imports no state, and performs no heuristic title cleanup.
- Made install, onboarding, manual update, and uninstall guidance friendly and plain: each action now previews what changes and what stays untouched, clearly discloses verified automatic updates, distinguishes safe skips from uncertain writes, and leaves a durable final-response recap with the result and next step.

### Removed

- Removed the running-title call, Post hook, persistent ThreadBear task, migration/controller/classifier machinery, archive maintenance, pending title transactions, repair flows, and global title-failure states.

## v2.2.1 - 2026-08-07

### Fixed
Expand Down
5 changes: 2 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

@docs/README.md

ThreadBear is a playful, token-conscious Codex title manager for macOS: one small on-demand Go binary and two native title hooks keep visible Desktop titles current without a daemon.
ThreadBear is a playful, token-conscious Codex title manager for macOS: one small Go binary uses the official local App Server to keep visible Desktop titles current without a daemon or model call.

- Current work is tracked in live Linear issues. The evergreen product contract is `README.md` plus `docs/architecture.md`; dated files in `docs/plans/` are historical evidence, not current architecture.
- Before title-path architecture or live experiments, run `python3 scripts/validate-experiments.py`, consult `docs/experiments/registry.json`, and satisfy the preflight in `docs/experiments/README.md`. Contradictory records remain conditional until one changed variable is isolated. Automation proves mechanical integrity; the active issue and pull-request review judge whether the unknown and changed variable are meaningful.
- Private eval corpus: `ericlitman/threadbear-eval` (real user messages — must never enter this public tree).
- Voice: playful, bear-themed, never at the expense of operational clarity.
- Shipped-logic target is 1,500 physical lines and CI rejects more than the 2,000-line absolute ceiling; stay as small as the product permits without compressing code to game the count. Size-policy changes require a live issue to record the measured baseline and ratify the new bounds before implementation.
- The only scheduler is the consented `threadbear-maintenance` Codex heartbeat attached to the persistent task. Do not add a LaunchAgent, second schedule, pending-title queue, detached title writer, or background classifier.
- The only scheduler is the daily `sh.threadbear.update` LaunchAgent. It may run only the verified update command; it never reads tasks, invokes a model, onboards titles, or archives anything. Do not add another schedule, persistent ThreadBear task, pending-title queue, detached title writer, or background classifier.
- Changelog: every PR with user-visible changes must append a concise entry under `CHANGELOG.md`'s `Unreleased` section. Release preparation renames that section to `vN.N.N - YYYY-MM-DD` and adds a fresh `Unreleased` section; the release workflow rejects stable tags without the matching version section.
- Shipping evidence: unit and fixture tests are necessary but never sufficient. Before calling a native lifecycle or release path shippable, exercise the reviewed candidate end to end against the real supported native control or official release service in an isolated, recoverable canary, record exact candidate/ref/results, and clean up the canary without visual inspection.
Loading
Loading