Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
4d7171c
fix(desktop): dialogs render above windows, and mint shows the URL an…
jaylfc Jul 21, 2026
f769049
feat(agents): project_tasks_create scope so an external agent can aut…
jaylfc Jul 21, 2026
39fc23f
feat(library): item card component with thumbnail, status, artifacts,…
jaylfc Jul 22, 2026
f3e983c
feat(agents): enforce files_read/files_write so member agents can acc…
jaylfc Jul 22, 2026
794a151
feat(providers): add Nous Portal as a cloud model provider (#2102)
jaylfc Jul 22, 2026
b4f2b1c
feat(desktop): Assistant Studio - a workspace for a personal-assistan…
jaylfc Jul 22, 2026
6393200
feat(agents): request additional scopes for an existing agent identit…
jaylfc Jul 22, 2026
5829b9e
fix(apps): register assistant-studio as an installable optional app (…
jaylfc Jul 22, 2026
8a8b6cb
fix(shortcuts): resolve the container's real incus project (and start…
jaylfc Jul 22, 2026
bc8b0d6
test(scope-requests): add grant-enforcement E2E, tighten approve tole…
hognek Jul 26, 2026
f9478d0
chore(deps): bump actions/setup-python from 6 to 7 (#2109)
dependabot[bot] Jul 26, 2026
267e740
chore(deps): bump the python-deps group with 2 updates (#2110)
dependabot[bot] Jul 26, 2026
197ce7b
chore(release): v1.0.0-beta.44 version bump + changelog (#2121)
jaylfc Jul 26, 2026
b1831a7
test(desktop): add unit tests for AssistantStudioApp (#2116)
jaylfc Jul 26, 2026
aa9f91d
fix(library): wire up the unused source ingest option (#2117)
jaylfc Jul 26, 2026
428d5d5
chore(deps): bump the spa-deps group in /desktop with 17 updates (#2111)
dependabot[bot] Jul 26, 2026
4e10a84
fix(agents): bind project_tasks_create and files scopes to a project …
jaylfc Jul 26, 2026
c1d388b
ci: raise the test timeout above the actual suite runtime (#2134)
jaylfc Jul 26, 2026
6946e43
feat(feedback): add per-user 24h submission cap (#2131)
jaylfc Jul 26, 2026
860adb9
test: replace always-true assert with issubclass check in test_instal…
hognek Jul 26, 2026
d541e43
feat(wallpaper): add Wallhaven proxy route + sectioned picker integra…
hognek Jul 26, 2026
6e55a28
fix(gpu-arbiter): clamp drain_tick_seconds floor + remove double _sig…
hognek Jul 26, 2026
4bef161
fix(peer): address Kilo WARNINGs — os.environ leak, design doc, rate …
hognek Jul 26, 2026
262ba07
fix(notifications): show approve/deny for scope-request notifications…
hognek Jul 26, 2026
f419780
fix(csrf): merge CSRF token into effectiveInit for Request inputs (bo…
hognek Jul 26, 2026
0b8a5d1
fix(canvas): make the .tldr export a file tldraw can actually open (#…
jaylfc Jul 26, 2026
13f0afa
a broken thumbnail currently disappears silently and leaves blank spa…
jaylfc Jul 26, 2026
defaa39
tsk-ihf2vw [OPEN] Library UI: storage accounting view (#2099)
jaylfc Jul 26, 2026
c5b1a6f
ci(coderabbit): stop spending the review quota on generated diffs (#2…
jaylfc Jul 26, 2026
148a964
feat(collab): E1 — DM schema migration (remote_msg_id, delivered_at, …
hognek Jul 27, 2026
dfb043a
ci: shard the test suite across parallel jobs (#2135) (#2137)
jaylfc Jul 27, 2026
b791c1a
docs: mark superseded designs after the 2026-07-26 decisions (#2157)
jaylfc Jul 27, 2026
93b4082
docs: harden agent token storage + fix confirmed doc drift (#2159)
jaylfc Jul 27, 2026
aad155c
docs(agents): realtime A2A connection guide for deployed agents (#2161)
jaylfc Jul 27, 2026
912d54d
docs: write down the verification and collision rules we work by (#2163)
jaylfc Jul 27, 2026
da1c28a
feat(hub): add X25519 sealed-envelope relay for store-and-forward thr…
hognek Jul 19, 2026
4b5bd3b
fix(hub): validate relay recipient and fix envelope size doc
hognek Jul 19, 2026
f5b1af3
fix(hub): guard against non-dict JSON body in relay drop
hognek Jul 19, 2026
4222739
fix(hub): measure base64-encoded envelope size + bind relay drop reci…
hognek Jul 27, 2026
e932ef6
feat(todo): Notes/Todo split — final integration pass (C5) (#2033)
hognek Jul 27, 2026
a044718
feat(community): add collaborator community view (stats + leaderboard…
hognek Jul 27, 2026
da63d28
feat(memory): show taOSmd running mode, reachability, tier + switch-t…
hognek Jul 27, 2026
c0ff22c
fix(hub): address CodeRabbit findings on relay PR #2034
hognek Jul 27, 2026
06f2d4a
tsk-kqebl2 [OPEN] taOStalk: theme-token migration (30 hardcoded uti…
jaylfc Jul 27, 2026
b5b2d75
taOStalk s1: content_blocks types + renderContent dispatcher (#2154)
jaylfc Jul 27, 2026
45d17f5
tsk-gp5xrq [OPEN] S2A: GET /api/share/destinations (authorization-f…
jaylfc Jul 27, 2026
d3ccf22
fix(push): VAPID key format broke every web-push send, silently (#2166)
jaylfc Jul 27, 2026
f551e63
tsk-55xqwq [OPEN] Land #2167: rebase the duplicate-channel-header f…
jaylfc Jul 27, 2026
ca1d2fe
tsk-mz3diu [OPEN] Project create: name uniqueness + dup auto-reject…
jaylfc Jul 27, 2026
077105e
chore(security): ignore key material so an identity file cannot be co…
jaylfc Jul 27, 2026
e521099
chore(security): ignore creds bundles, the shape the first pass misse…
jaylfc Jul 27, 2026
768aad5
fix(security): install auth guard in all SPA entry points (#2174)
jaylfc Jul 27, 2026
af08174
feat(library): P2 rebased — YouTube + Web processors with streaming, …
hognek Jul 28, 2026
905b632
docs(agent-coordination): spend model tokens on judgement, not on wai…
jaylfc Jul 28, 2026
630177b
tsk-vkdf7k [OPEN] BUG (Jay): tapping a push notification never open…
jaylfc Jul 28, 2026
5184970
Allow agents to mirror answers, read own decisions, and filter pendin…
jaylfc Jul 28, 2026
7c8bee8
tsk-bgznuk [OPEN] Agents can ASK a Decision but cannot MIRROR the an
jaylfc Jul 28, 2026
3ec0ff3
tsk-2vptcw [OPEN] App tiering S1: registry tier/group/handler field…
jaylfc Jul 28, 2026
87ac931
fix(store): fail-closed on sign_manifest failure — prevent install-ga…
hognek Jul 28, 2026
f955400
Add project_tasks_update agent scope so leads can edit their own boar…
jaylfc Jul 28, 2026
d728dd8
ci: run the dependency audit on dev pull requests (#2189)
jaylfc Jul 28, 2026
5013f5c
fix(store): resolve Kilo WARNING+SUGGESTION — date-safe canonicalisat…
hognek Jul 19, 2026
cb62fed
fix(store): drop default=str from canonicalisation, fail-closed on Ty…
hognek Jul 28, 2026
17efc01
fix(store): address CodeRabbit findings — BLE001, error msg, root guard
hognek Jul 28, 2026
32ec9c9
test(store): add TOCTOU date-field fail-closed regression test
hognek Jul 28, 2026
3b71df0
fix(store_install): replace os.geteuid with getattr guard for Windows…
hognek Jul 28, 2026
2a4b8c8
fix(hub): remove recipient binding from relay drop, pass data_dir to …
hognek Jul 28, 2026
777d097
Merge pull request #2186 from hognek/fix/2027-signing-fail-closed
jaylfc Jul 28, 2026
e8272c8
refactor(projects): remove the chat pane from the Workspace tab
jaylfc Jul 28, 2026
6b59221
chore(deps): bump pillow to 12.3.0 and dompurify to 3.4.12 (security)
jaylfc Jul 28, 2026
2c1b25a
fix(decisions): repair agent mirror path — middleware regex, identity…
hognek Jul 28, 2026
9c98087
Merge pull request #2192 from jaylfc/feat/workspace-remove-chat-pane
jaylfc Jul 28, 2026
f6555ac
Merge pull request #2193 from jaylfc/chore/security-bumps-pillow-domp…
jaylfc Jul 28, 2026
5e6dcaa
Merge pull request #2034 from hognek/feat/hub-relay
jaylfc Jul 28, 2026
6410e3c
fix(decisions): harden agent mirror path — reject source spoofing, sk…
hognek Jul 28, 2026
5d207ec
fix(decisions): address CodeRabbit findings — JWT-first oracle, test …
hognek Jul 28, 2026
b870745
fix(decisions): refuse agent mirror-answer for gate-kind decisions
hognek Jul 28, 2026
b37c296
fix(decisions): restore project-scoped agent auth for read/answer end…
hognek Jul 28, 2026
d9f83a7
fix(lists): add ProjectListsStore and fix ProjectListEntriesStore
jaylfc Jul 28, 2026
9b78b84
fix(lists): call _get_next_position when add_entry position is None
hognek Jul 28, 2026
7340c2a
Merge pull request #2200 from hognek/fix/lists-add-entry-position
jaylfc Jul 28, 2026
b5f5edb
fix(decisions): close cross-project leak, collapse 403 to 404, drop u…
hognek Jul 28, 2026
27a6b1b
tsk-bhw3pm [OPEN] Observatory routes: make observatory_control grant
jaylfc Jul 28, 2026
7179efb
Merge pull request #2203 from jaylfc/exec/tsk-bhw3pm
jaylfc Jul 28, 2026
6018bef
fix(decisions): unify answer route 404 body with GET route idiom
hognek Jul 28, 2026
6dda472
Merge pull request #2194 from hognek/exec/tsk-bgznuk
jaylfc Jul 28, 2026
f67e67a
chore: gitignore data/hub/ (runtime identity keys must never be commi…
jaylfc Aug 2, 2026
a68d206
chore: drop duplicate data/hub/ gitignore entry (already covered sinc…
jaylfc Aug 2, 2026
24e1d96
tsk-gr56lr [OPEN] store_install: unsigned-manifest policy contradic…
jaylfc Aug 2, 2026
3155fd0
Add route tests for mail endpoints (#2216)
jaylfc Aug 2, 2026
23910e3
chore: move dev deps to [dependency-groups] so uv sync gives a workin…
jaylfc Aug 2, 2026
47d170f
feat(browser): default agent sessions to mobile viewport flag (latent…
hognek Aug 2, 2026
e76a8b6
Add route tests for the themes API (#2206)
jaylfc Aug 2, 2026
1c9486a
add route tests for canvas endpoints (#2209)
jaylfc Aug 2, 2026
a5030d5
Log unknown task request-body keys (observation phase, tsk-kqzpjt) (#…
jaylfc Aug 2, 2026
3954890
fix(tasks): bound the unknown-key warning log (cap key count and leng…
jaylfc Aug 2, 2026
c0c2353
chore(deps): bump the spa-deps group in /desktop with 8 updates (#2221)
dependabot[bot] Aug 2, 2026
8de1e92
chore(deps): bump the python-deps group across 1 directory with 2 upd…
dependabot[bot] Aug 2, 2026
ab4afc9
test(installed_apps): add _post_init white-box tests and timestamp mo…
jaylfc Aug 2, 2026
4deec4c
tsk-6v5j75 [OPEN] Fix-forward PR 2190: new-contract tests for A2A s…
jaylfc Aug 2, 2026
f9f82d7
fix(deleted-symbols): replace predicate with base_tip - HEAD, drop me…
jaylfc Aug 2, 2026
64e9e63
tsk-3salz6 [OPEN] Fix-forward PR 2197 (design law docs): manual siz…
jaylfc Aug 2, 2026
0c99f04
tsk-rll2pj [OPEN] Fix-forward PR 2202 (S2A follow-ups): slug fallba…
jaylfc Aug 2, 2026
09be5f7
tsk-xexpx3 [OPEN] Fix-forward PR 2219 (theme tokens): backend schem…
jaylfc Aug 2, 2026
ff37e10
fix-forward: retrofit-migrations gate handles AnnAssign + wiring (#2228)
jaylfc Aug 2, 2026
c26e1c9
fix: resolve watch projection issues (#2230)
jaylfc Aug 2, 2026
7c3c036
docs(design): bounded Postgres adoption proposal + 8GB hardware floor…
jaylfc Aug 2, 2026
c4964b1
docs(design): decouple the hardware floor from Postgres adoption, 4GB…
jaylfc Aug 2, 2026
efad7a8
fix(desktop): stop squashing the wallpaper on square and odd-ratio sc…
jaylfc Aug 2, 2026
3b662c5
fix(desktop): same wallpaper stretch in browser mode, sweep the pattern
jaylfc Aug 2, 2026
2b4eb4d
test(user_shares): add store + route tests with conftest integration …
hognek Aug 2, 2026
1011742
tsk-k5diis [OPEN] S4d: device-bearer self-service (push-token rotat…
jaylfc Aug 2, 2026
0d97121
docs(design): move work and comms into taOS - notes, agent-state badg…
jaylfc Aug 2, 2026
102506b
docs(design): measured headless cost on subscription, session lifecyc…
jaylfc Aug 2, 2026
c6eb3d8
docs(design): deliver by injecting into open sessions (herdr), not by…
jaylfc Aug 2, 2026
cb6e247
docs(design): delivery must be tooling-agnostic - agent pulls from ta…
jaylfc Aug 2, 2026
c13c5ca
docs(design): name the A2A bus as the transport, map the taosmd depen…
jaylfc Aug 2, 2026
d1fc599
docs(design): cost discipline as a first-class constraint - checking …
jaylfc Aug 2, 2026
39894de
docs(design): Postgres adoption DEFERRED per Jay's decision, wait for…
jaylfc Aug 2, 2026
4bf465d
check_doc_gate: add opt-in on_modify per-rule and extend tests (#2236)
jaylfc Aug 2, 2026
ad7e4fe
reserve user-, human-, admin-, taos- prefixes at agent registration (…
jaylfc Aug 2, 2026
1193b6b
chore(release): v1.0.0-beta.45 version bump + changelog (#2239)
jaylfc Aug 2, 2026
ac56654
Merge master into dev for the beta.45 promote
jaylfc Aug 2, 2026
a4994e0
fix(spa): restore the docReviews client + types dropped in conflict r…
jaylfc Aug 2, 2026
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
45 changes: 45 additions & 0 deletions .claude/skills/taos-development-skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,25 @@ I have read the CLA Document and I hereby sign the CLA
3. Once code is done and local tests pass, `gh pr ready`. Address review feedback with additional
commits on the same branch. The maintainer merges upstream.

### Do not spend turns waiting

You pay per turn. Spend them on judgement (reading a diff, diagnosing a failure,
deciding whether a green check is trustworthy), not on waiting or repetition.

- **Do not poll CI in a loop.** `gh pr checks <PR#> --watch` blocks in one call
and returns when the run finishes. Re-running `gh pr checks` every minute
costs a turn each time and tells you nothing new. (A malformed watch once
exited early and reported success while shards were still running, so read
the final status rather than trusting that the command returned.)
- **If you have hand-verified the same property twice, write the test.** Two
manual checks is the signal. A test costs nothing per run; re-reading costs
every time.
- **Ask the narrow question.** A targeted `grep` or a symbol-level diff against
`origin/dev` usually decides the matter far more cheaply than reading a whole
diff. Work out what single fact settles it, then fetch only that.
- **Do not re-poll a blocked run.** See `action_required` above: surface it and
stop. Repeatedly checking a run that is waiting on a human is pure cost.

## Post-Push Bot Review Cycle

After pushing a PR and marking it ready, automated bots review it. The reliable gate is
Expand Down Expand Up @@ -429,6 +448,32 @@ Run `scripts/install-git-hooks.sh` to enable local hooks (`.githooks/pre-commit`
are available. Most modules use `from __future__ import annotations`.
- Code style: match surrounding code, one concern per module
- Use `uv` for dependency management and test running: `uv sync --extra dev`, `uv run pytest`
- **Read `CONTRIBUTING.md` sections "Verifying your work" and "Avoiding collisions with
other contributors".** They are the canonical statement of both; this file does not
restate them so the two cannot drift. What follows is only the part specific to
working here as an agent.

## Verification (agent specifics)

Green is a claim, not evidence. The repo-level cases are in CONTRIBUTING.md. These are
the ones that bite agents in particular:

- **Do not report work as done without a PR link.** A branch with commits and no PR is
not delivered. A lane once announced completion on an empty branch; the check now runs
before any completion is claimed, and the same standard applies to you.
- **A PR that passes CI can still be empty.** Before saying a card is finished, look at
the actual diff and confirm it contains the change described.
- **Never infer merge conflicts from `git merge-tree`** against branches you have not
fetched; it produces confident nonsense. Use GitHub's `mergeable_state`, and treat
`unknown` as "not computed yet" and re-query rather than as an answer.
- **Check the exit status of the command that matters**, not the last one in a pipe.
`cmd | tail && echo OK` prints OK when `cmd` failed.
- **An empty fetch is not a match.** If two files that cannot be identical hash the same,
your request failed rather than the contents agreeing.
- **Verify a bot finding against the code before folding it.** Automated review is often
wrong and always confident. Fold what is real, say plainly what is not.
- **Report honestly.** If tests fail, include the output. If a step was skipped, name it.
"Done" means verified.

## Desktop SPA build + test

Expand Down
25 changes: 25 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,28 @@ reviews:
base_branches:
- master
- dev
# The plan has a finite review quota, and it was being spent in the wrong
# places: repeatedly "review limit reached" on real code PRs while lockfile
# bumps consumed reviews. #2127 and #2131 both went unreviewed for this
# reason on the day this was written.
#
# Dependabot PRs are version bumps plus a regenerated lockfile. There is no
# human-authored logic for a reviewer to reason about, and CI already gates
# them, so they are the cheapest thing to stop spending quota on.
ignore_usernames:
- dependabot
- dependabot[bot]
# A draft is explicitly not ready. Reviewing it burns a review that will be
# burned again when it is marked ready.
drafts: false
# Generated artefacts dominate the diff without carrying reviewable intent.
# A single spa-deps bump is a 2000+ line package-lock diff.
path_filters:
- "!**/package-lock.json"
- "!**/uv.lock"
- "!desktop/dist/**"
# Only the BUILT desktop bundle under static/, not all of static/: sw.js and
# the PWA manifests there are human-authored runtime behaviour and exactly
# the kind of change a reviewer should see (Qodo caught the over-broad
# original).
- "!static/desktop/**"
78 changes: 69 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,15 @@ jobs:
# run at once instead of queueing behind the 2 self-hosted boxes. The VPS +
# Fedora runners stay free for the kilo lane and GPU/bench work.

test:
# Renamed from "test" to "shards" because sharding changes the check-run names
# this job reports. Branch protection matches required checks by NAME, so the
# sharded jobs report "test (3.12, 1)" etc and the required contexts
# "test (3.12)" / "test (3.13)" would never be reported again. Protection then
# waits forever on checks that cannot exist and blocks every PR, including the
# one that would fix it. The aggregate "test" job below keeps reporting those
# two exact names, so no protection change is needed and there is no window
# where dev is wedged.
shards:
runs-on: ubuntu-latest
# Measured 2026-07-26 over the last 12 job records: 3.13 runs 31-35 min and
# 3.12 runs 38-41 min. The previous comment claimed "~16 min", which had
Expand All @@ -55,6 +63,15 @@ jobs:
# PR + push runs cover the latest two; the daily cron run
# below adds 3.11 so the minimum-supported version stays tested.
python-version: ${{ github.event_name == 'schedule' && fromJSON('["3.11", "3.12", "3.13"]') || fromJSON('["3.12", "3.13"]') }}
# Shard the suite across parallel jobs. xdist parallelises WITHIN a job,
# but a hosted runner is 2 vCPU, so -n auto caps at 2 workers however
# many tests exist -- and the suite has grown 4845 -> 10250 (#2135).
# Cores per job were the bottleneck, not the tests.
#
# A public repo gets ~20 concurrent jobs free and we were using 2, so
# this costs nothing. 2 versions x 4 shards = 8 jobs on PR/push, and
# 12 on the scheduled run that adds 3.11.
shard: [1, 2, 3, 4]

steps:
- uses: actions/checkout@v7
Expand All @@ -78,20 +95,63 @@ jobs:
# not from a fresh unpinned resolve that can pull in a regressed
# release (see the fastapi 0.137 incident, #903).
- name: Install dependencies
run: uv sync --frozen --extra dev --python ${{ matrix.python-version }}
run: uv sync --frozen --python ${{ matrix.python-version }}

# SPA bundle is stubbed by tests/conftest.py — see pytest_configure.
# The real build is exercised in the spa-build job below.

- name: Run tests
# Run across all runner cores. The serial suite (4845 tests) took
# ~22 min; -n auto cuts it to a few minutes so "merge on green" is
# practical. Dropped -v so xdist worker output stays readable.
run: uv run --no-sync pytest tests/ --tb=short --ignore=tests/e2e -n auto

- name: Run tests (shard ${{ matrix.shard }}/4)
# --splits/--group partition the suite deterministically and exactly:
# verified that the 4 groups union to all 10250 collected tests with no
# duplicates and, critically, no drops. A sharding bug that silently
# skipped tests would leave CI green while testing less, which is the
# one failure mode worth checking rather than assuming.
#
# -n auto still uses both cores inside each shard.
run: >-
uv run --no-sync pytest tests/ --tb=short --ignore=tests/e2e
-n auto --splits 4 --group ${{ matrix.shard }}

# Import smoke check: identical in every shard, so run it once per Python
# version (shard 1 only) rather than in all 4 shards.
- name: Verify app starts
if: matrix.shard == 1
run: uv run --no-sync python -c "from tinyagentos.app import create_app; print('OK')"

# Aggregate gate. Reports the exact check names branch protection requires
# ("test (3.12)", "test (3.13)") so the required-context list does not have to
# change when the shard count does. An explicit `name:` is used verbatim by
# GitHub rather than having the matrix values appended, which is what makes
# reproducing the old names possible at all.
#
# `if: always()` is load-bearing. Without it this job is SKIPPED when the
# shards fail, and GitHub treats a skipped required check as satisfied -- so a
# red suite would report a green gate. It must run and fail explicitly.
test:
name: test (${{ matrix.python-version }})
needs: shards
if: always()
runs-on: ubuntu-latest
strategy:
# Both gates must report their own conclusion. With the default
# fail-fast, the first gate to fail CANCELS its sibling, so a red suite
# reported "test (3.12) failure, test (3.13) cancelled" -- observed on a
# deliberate-failure branch. Cancelled is not success so protection still
# blocks, but which version broke becomes a coin flip, and a required
# check whose conclusion depends on scheduling order is not a gate worth
# trusting.
fail-fast: false
matrix:
python-version: ["3.12", "3.13"]
steps:
- name: Gate on shard results
run: |
echo "shards concluded: ${{ needs.shards.result }}"
if [ "${{ needs.shards.result }}" != "success" ]; then
echo "::error::test shards did not all pass"
exit 1
fi

lint:
runs-on: ubuntu-latest
steps:
Expand All @@ -108,7 +168,7 @@ jobs:
enable-cache: true

- name: Install dependencies
run: uv sync --frozen --extra dev --python 3.12
run: uv sync --frozen --python 3.12

- name: Check for syntax errors
run: uv run --no-sync python -m compileall tinyagentos/ -q
Expand Down
41 changes: 41 additions & 0 deletions .github/workflows/deleted-symbols-gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Deleted symbols gate

# Detects PRs that silently delete Python symbols (def/class/test names) that
# landed on the target branch after the PR's merge base. A PR cut before
# hardening commits landed on dev would silently delete them when merged --
# git reports "Automatic merge went well" with no conflict because the PR
# branch simply wins on files dev touched after the branch point.
#
# This check fails such PRs and names the deleted symbols and the commits that
# added them. A "Removes-Intentionally: <symbol>" trailer in the PR body
# waives named symbols, making deliberate deletions a conscious, auditable act.
#
# See scripts/check_deleted_symbols.py for the implementation.

on:
pull_request:
branches: [master, dev]

jobs:
deleted-symbols-gate:
runs-on: ubuntu-latest
permissions:
contents: read
env:
BASE_REF: ${{ github.base_ref }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- uses: actions/setup-python@v7
with:
python-version: "3.12"

- name: Fetch base branch
run: git fetch origin "$BASE_REF"

- name: Check for silently deleted symbols
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: python scripts/check_deleted_symbols.py --base "origin/$BASE_REF"
3 changes: 3 additions & 0 deletions .github/workflows/doc-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ jobs:
- name: Schema-migration guard (#1865)
run: python scripts/check_schema_migrations.py

- name: Retrofit-migration guard (#2188)
run: python scripts/check_retrofit_migrations.py

- name: Diff gate (Layer B)
env:
BASE_REF: ${{ github.base_ref }}
Expand Down
18 changes: 17 additions & 1 deletion .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,27 @@ name: Security
on:
push:
branches: [master]
# dev is where work actually lands: every exec PR targets dev, and master only
# receives it later at a release promotion. Auditing master-only meant the
# dependency audit NEVER ran on a pull request, so a vulnerable dependency
# could merge into dev and ship in a beta without anything looking at it. The
# weekly cron still covers master, but that is after the fact and on the wrong
# branch. Verified clean on dev before enabling: pip-audit reports no known
# vulnerabilities, so this does not block the open queue.
pull_request:
branches: [master]
branches: [master, dev]
schedule:
- cron: "0 6 * * 1"

# Mirror ci.yml: this now runs on every dev PR update, so superseded runs must
# cancel or each push leaves an orphaned audit burning runner minutes. Pushes to
# master and dev are deliberately NOT cancelled, so the branch record stays
# complete. (qodo on #2189, verified: ci.yml carries this block and security.yml
# did not, which only started to matter once the dev trigger was added.)
concurrency:
group: security-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' && github.ref != 'refs/heads/dev' }}

permissions:
contents: read

Expand Down
48 changes: 48 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ screenshots.zip
data/.auth_user.json
data/browser_cookie_key.hex

# Hub identity — runtime state, never track (contains generated keypairs)
data/hub/

# Vite/TS incremental build artifact — regenerated on every build, must not be tracked
# (a tracked copy dirties the tree and blocks the in-app git-pull update).
desktop/tsconfig.tsbuildinfo
Expand Down Expand Up @@ -128,3 +131,48 @@ data/pending-restart.json
# Stray dev screenshot artifacts
desktop-initial.png
venv/

# Credential material must never be committable. An agent stored a registry
# token at /opt/taos/secrets/ on 2026-07-27 - correct permissions, but inside the
# deployed git checkout and one "git add -A" away from a public repo.
secrets/
*.token
*.cred

# Credential material under data/. On 2026-07-27 three of these sat UNTRACKED in
# the deployed checkout - one 'git add -A' from a public repo. Never committed
# (verified against full history), but untracked is not the same as safe.
#
# Deliberately NOT using 'data/*' deny-all: data/archive, data/sessions and
# data/guides.yaml are legitimately tracked, and a blanket rule would silently
# ignore NEW files there - trading a credential risk for a data-loss-by-
# invisibility one. Enumerate the secrets instead, and keep this list current.
data/.secrets_key
data/.seeded-agent-tokens.json
data/secrets.db*
data/*.key
data/*.token

# Key material and secrets. Added 2026-07-27 after data/hub/identity.json was
# committed to PR #2043 with signing_private and encryption_private in
# PLAINTEXT. data/hub/ is already covered above; these patterns close the REST
# of the surface, which was open: an identity.json or a *.key written anywhere
# outside data/hub/ had nothing stopping it. Pattern-based on purpose, since a
# per-file allowlist cannot catch a file that does not exist yet.
# Verified against every tracked file: none become ignored.
*.key
*_private.pem
*_private.key
*_private.json
*_private_key*
identity.json
*.p8
*credentials.json

# Credential bundles. Added 2026-07-27: @taOS-website-dev ran the same audit
# on its repo and found shapes my first pass (PR #2171) missed. Verified on
# origin/dev: creds.json, my_creds.json and data/creds.json were all NOT
# ignored, while *credentials.json already was. Matching the *creds* stem
# closes the shorter spelling, which is the one people actually type.
# Verified against every tracked file on origin/dev: 0 become ignored.
*creds*.json
Loading