Skip to content

Commit b80a005

Browse files
committed
Preserve orchestration audit truth under concurrent execution
Keep team fan-out complete while enforcing concurrency as a limit, make swarm context bus state run-scoped, and preserve blocked audit evidence when policy denials are surfaced as pending approval. Refresh acceptance/docs evidence to match the expanded coverage. Constraint: Project tests require audit completeness, docs count freshness, and Lore commit trailers. Rejected: Truncating teams at max_concurrent | max_concurrent is a scheduling limit, not a specialist selection limit. Confidence: high Scope-risk: moderate Directive: Preserve both tool_call_blocked and pending approval events for denied tool calls so audit consumers and UX state stay consistent. Roadmap-Status: unchanged Tested: ruff check .; ruff format --check .; mypy teaagent/ tests/ --explicit-package-bases; scripts/audit_test_quality.py --fail-on severe; bash scripts/verify_docs.sh; scripts/run_test_tier.py --tier smoke; scripts/run_acceptance_tier.py --tier all; split pytest chunks across integration/lifecycle/policy/regression/e2e and tests/test_[a-d,e-h,i-m,n-r,s-z]*.py Not-tested: Single-process python3 -m pytest -q completes; this environment terminated it with exit code 152 around 37%, so the suite was verified in bounded chunks instead.
1 parent bb9fb1b commit b80a005

19 files changed

Lines changed: 1012 additions & 189 deletions

docs/acceptance.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
> **Does not own:** Full-suite CI results (see dated evidence) or roadmap priorities.
88
>
99
> **Review trigger:** Acceptance test inventory or count changes.
10-
> **Last reviewed:** 2026-06-12
10+
> **Last reviewed:** 2026-06-17
1111
1212
## Suite Tiers (WDG-002)
1313

@@ -42,7 +42,7 @@ acceptance flow writes the user TUI state file. In sandboxed environments, run
4242
them with permission to bind localhost ports and write the TeaAgent state
4343
directory.
4444

45-
**Current acceptance test count: `646 passed`** (pytest-collected guard target)
45+
**Current acceptance test count: `654 passed`** (pytest-collected guard target)
4646

4747
Keep historical acceptance-count snapshots in dated analysis or roadmap docs.
4848
This file only owns the live guard target.

docs/generated/docs-aging-dashboard.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
**Stale threshold:** 90 days since `Last reviewed`
66
**Current-truth docs scanned:** 17
7-
**Needs attention (working tier only):** 2
7+
**Needs attention (working tier only):** 3
88
**Archive-tier docs (exempt from staleness):** 1
99

1010
Regenerate: `python3 scripts/report_docs_aging.py`
@@ -17,6 +17,12 @@ Regenerate: `python3 scripts/report_docs_aging.py`
1717
| --- | --- | --- | --- | --- |
1818
| `docs/architecture.md` | stale_by_mtime | 2026-06-06 | 2026-06-07 | Missing owner banner; File modified after last reviewed date |
1919

20+
### cli
21+
22+
| Document | Status | Last reviewed | File mtime | Notes |
23+
| --- | --- | --- | --- | --- |
24+
| `docs/cli.md` | stale_by_mtime | 2026-06-06 | 2026-06-14 | Missing owner banner; File modified after last reviewed date |
25+
2026
### docs
2127

2228
| Document | Status | Last reviewed | File mtime | Notes |

docs/generated/docs-inventory.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Do not edit this file manually — regenerate instead.
1010

1111
| Path | Tier | Bytes | SHA256 (12) |
1212
| --- | --- | ---: | --- |
13-
| `acceptance.md` | constitution | 20769 | `57763445502f` |
13+
| `acceptance.md` | constitution | 20769 | `9441254f9c46` |
1414
| `adr/0001-p0-framework.md` | working | 3225 | `d0666420a497` |
1515
| `adr/0002-p1-primitives.md` | working | 2877 | `d50c03f403a6` |
1616
| `adr/0003-p2-code-mode-sandbox.md` | working | 3153 | `594b44eb1569` |
@@ -233,8 +233,8 @@ Do not edit this file manually — regenerate instead.
233233
| `error-reference.md` | working | 4897 | `4d8a143b3322` |
234234
| `gateway-oauth-tenants.md` | working | 1818 | `0ff9c7df4652` |
235235
| `generated/command-snippet-inventory.md` | working | 8128 | `5256119bb8fe` |
236-
| `generated/docs-aging-dashboard.md` | working | 3141 | `03454afd0476` |
237-
| `generated/release-docs-evidence.md` | working | 3621 | `3eacf81cef02` |
236+
| `generated/docs-aging-dashboard.md` | working | 3366 | `5144b27ce9fd` |
237+
| `generated/release-docs-evidence.md` | working | 1860 | `e88529c2f38e` |
238238
| `governance-compliance.md` | constitution | 1648 | `031cfe1796cd` |
239239
| `governance/code-review-checklist.md` | working | 4379 | `f580da208c75` |
240240
| `governance/command-snippet-registry.md` | working | 3023 | `2e6c2b337773` |

docs/generated/release-docs-evidence.json

Lines changed: 27 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,74 @@
11
{
22
"ok": true,
3-
"created_at": "2026-06-06T04:14:55+00:00",
3+
"created_at": "2026-06-16T17:24:52+00:00",
44
"repo_root": "/Users/teee/dev/teaagent",
55
"git": {
66
"branch": "main",
7-
"commit": "b0b3054f49231598c378d031dc0feef03e87bd32",
7+
"commit": "bb9fb1b73df7c6ed909925d6358aa6b22d53139e",
88
"dirty": true
99
},
1010
"commands": [],
1111
"docs_freshness": {
1212
"scanned": 17,
13-
"needs_attention": 0,
14-
"by_owner": {},
13+
"needs_attention": 3,
14+
"by_owner": {
15+
"docs": 1,
16+
"cli": 1,
17+
"architecture": 1
18+
},
1519
"stale_threshold_days": 90
1620
},
1721
"roadmap_excerpt": {
1822
"horizons": [
1923
{
2024
"id": "H0",
2125
"name": "Claim and risk hygiene",
22-
"status": "In Progress",
23-
"confidence": "Medium",
24-
"next_gate": "DOCOPT-012 generalized guarded-claim registry"
26+
"status": "Complete",
27+
"confidence": "High",
28+
"next_gate": "H1"
2529
},
2630
{
2731
"id": "H1",
2832
"name": "Daily operator loop",
29-
"status": "In Progress",
33+
"status": "Complete",
3034
"confidence": "High",
31-
"next_gate": "M1 complete"
35+
"next_gate": "H2"
3236
},
3337
{
3438
"id": "H2",
3539
"name": "Multi-surface continuity",
36-
"status": "Pending",
40+
"status": "Partially fixed — M2 foundation wired",
3741
"confidence": "Medium",
38-
"next_gate": "M2 complete"
42+
"next_gate": "WDA-002"
3943
},
4044
{
4145
"id": "H3",
4246
"name": "Ecosystem trust",
43-
"status": "Pending",
47+
"status": "Partially fixed — M3 tests pass",
4448
"confidence": "Medium",
45-
"next_gate": "M3 complete"
49+
"next_gate": "WDC-002"
4650
},
4751
{
4852
"id": "H4",
49-
"name": "Durable team operations",
50-
"status": "Pending",
53+
"name": "Durable owner/agent operations",
54+
"status": "Partially fixed — shadow wired",
5155
"confidence": "Low",
52-
"next_gate": "M4 complete"
56+
"next_gate": "WDA-004"
5357
},
5458
{
5559
"id": "H5",
5660
"name": "Quality and eval loop",
57-
"status": "Pending",
61+
"status": "Partially fixed — release gate wired",
5862
"confidence": "Low",
59-
"next_gate": "M5 complete"
63+
"next_gate": "WDA-005"
6064
}
6165
],
6266
"milestones": [
6367
{
6468
"id": "M0",
6569
"target": "1-2 weeks",
66-
"status": "Medium",
67-
"next_gate": "`validate_docs_consistency.py`, `refresh_competitive_docs.py --check`, `teaagent tool lint --root .` pass"
70+
"status": "High",
71+
"next_gate": "All 3 checks pass: `validate_docs_consistency.py`, `refresh_competitive_docs.py --check`, `teaagent tool lint --root .`"
6872
},
6973
{
7074
"id": "M1",
@@ -75,103 +79,18 @@
7579
{
7680
"id": "M2",
7781
"target": "4-10 weeks",
78-
"status": "Medium",
82+
"status": "High",
7983
"next_gate": "Long-session context guard acceptance, scope budget acceptance, plan revision acceptance"
8084
},
8185
{
8286
"id": "M3",
8387
"target": "8-14 weeks",
84-
"status": "Medium",
88+
"status": "High",
8589
"next_gate": "Extension activation explain acceptance, MCP trust onboarding acceptance, subagent review/merge acceptance"
8690
}
8791
]
8892
},
89-
"open_risks": [
90-
{
91-
"id": "SEC-05",
92-
"category": "Budget",
93-
"description": "Cost accounting reads `context['_cost_cents']` written by the LLM adapter — injectable by malicious adapter or prompt-injected response",
94-
"status": "**OPEN**",
95-
"priority": "P2"
96-
},
97-
{
98-
"id": "SEC-09",
99-
"category": "Multi-sig",
100-
"description": "Multi-sig approval hash uses 1-hour time bucket (`int(time.time()/3600)`); captured signature replayable for up to 59:59 within same window; hash logic duplicated in two files",
101-
"status": "**OPEN**",
102-
"priority": "P2"
103-
},
104-
{
105-
"id": "SEC-11",
106-
"category": "Undo",
107-
"description": "`UndoJournal._PATH_WRITE_TOOLS` covers file tools only; `workspace_run_shell_mutate` not tracked — UI shows \"undo available\" but shell side-effects are unrecoverable",
108-
"status": "**OPEN**",
109-
"priority": "P2"
110-
},
111-
{
112-
"id": "SEC-12",
113-
"category": "Audit",
114-
"description": "`os.fsync()` failure caught and silenced; audit degrades to in-memory only with no operator notification; disk-full attack eliminates all log persistence",
115-
"status": "**OPEN**",
116-
"priority": "P2"
117-
},
118-
{
119-
"id": "SEC-13",
120-
"category": "Testing",
121-
"description": "Critical security paths (cost tracking, audit HMAC, approval denial) mocked out in tests — bugs live undetected (confirmed: CG-03 lived months this way)",
122-
"status": "**OPEN** — remediation plan in §9; target tests include `tests/test_chat_agent.py`, audit HMAC persistence/wrong-key tests, and MCP trust-expiry enforcement tests",
123-
"priority": "P1"
124-
},
125-
{
126-
"id": "SEC-14",
127-
"category": "Permission",
128-
"description": "`preapproved_call_ids` deprecated but still functional — old integrations or adversarial callers can pre-approve arbitrary call IDs without HMAC digest verification",
129-
"status": "**OPEN**",
130-
"priority": "P3"
131-
},
132-
{
133-
"id": "SEC-15",
134-
"category": "Multi-sig",
135-
"description": "`TEAAGENT_ALLOW_DEV_SIGNATURES=1` accepts SHA-256 of `(message+pubkey)` as valid signature; no runtime guard prevents this in production WAN deployment",
136-
"status": "**OPEN**",
137-
"priority": "P2"
138-
},
139-
{
140-
"id": "SEC-16",
141-
"category": "Code Quality",
142-
"description": "Dead code at `budget_monitor.py:104-119` after early return — maintenance hazard that could accidentally activate on refactor",
143-
"status": "**OPEN**",
144-
"priority": "QW"
145-
},
146-
{
147-
"id": "DS-04",
148-
"category": "Audit",
149-
"description": "Stale `audit_trail` dict in suspension JSON predates CG-10 fix; forensic tooling may prefer the stale copy over the real RunStore events",
150-
"status": "**OPEN**",
151-
"priority": "P3"
152-
},
153-
{
154-
"id": "SC-01",
155-
"category": "Dependencies",
156-
"description": "Two alpha packages in production lock (`opentelemetry-exporter-gcp-logging==1.12.0a0`, `opentelemetry-resourcedetector-gcp==1.12.0a0`) can break between lock refreshes",
157-
"status": "**OPEN**",
158-
"priority": "P2"
159-
},
160-
{
161-
"id": "SC-02",
162-
"category": "Dependencies",
163-
"description": "`anthropic` SDK and `pyyaml` imported at runtime but undeclared in `pyproject.toml` — silent `ImportError` on installs without `google-cloud-aiplatform` or `pre-commit`",
164-
"status": "**OPEN** — TASK-DD2-015 dependency declaration/import-check follow-up; fix target: `pyproject.toml`",
165-
"priority": "P1"
166-
},
167-
{
168-
"id": "SC-03",
169-
"category": "Dependencies",
170-
"description": "`aiohttp` and `mcp` SDK in lock as orphans — not declared, not imported in core; add 22 transitive packages to attack surface unnecessarily",
171-
"status": "**OPEN**",
172-
"priority": "P2"
173-
}
174-
],
93+
"open_risks": [],
17594
"regenerate_commands": [
17695
"python3 scripts/build_release_docs_evidence_bundle.py",
17796
"python3 scripts/validate_docs_consistency.py",
Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Release Documentation Evidence Bundle (Generated)
22

3-
**Generated:** 2026-06-06T04:14:55+00:00
4-
**Git commit:** `b0b3054f49231598c378d031dc0feef03e87bd32` on `main`
3+
**Generated:** 2026-06-16T17:24:52+00:00
4+
**Git commit:** `bb9fb1b73df7c6ed909925d6358aa6b22d53139e` on `main`
55
**Working tree dirty:** yes
66

77
Regenerate: `python3 scripts/build_release_docs_evidence_bundle.py`
@@ -15,35 +15,25 @@ Regenerate: `python3 scripts/build_release_docs_evidence_bundle.py`
1515
## Documentation Freshness
1616

1717
- Current-truth docs scanned: **17**
18-
- Needs attention: **0** (>90 days)
19-
- All scanned current-truth docs are fresh.
18+
- Needs attention: **3** (>90 days)
19+
- Stale by owner surface:
20+
- `architecture`: 1
21+
- `cli`: 1
22+
- `docs`: 1
2023

2124
## Roadmap Excerpt
2225

23-
- `H0` Claim and risk hygiene: **In Progress** (confidence Medium, next gate DOCOPT-012 generalized guarded-claim registry)
24-
- `H1` Daily operator loop: **In Progress** (confidence High, next gate M1 complete)
25-
- `H2` Multi-surface continuity: **Pending** (confidence Medium, next gate M2 complete)
26-
- `H3` Ecosystem trust: **Pending** (confidence Medium, next gate M3 complete)
27-
- `H4` Durable team operations: **Pending** (confidence Low, next gate M4 complete)
28-
- `H5` Quality and eval loop: **Pending** (confidence Low, next gate M5 complete)
29-
- `M0` (1-2 weeks): **Medium** (next gate `validate_docs_consistency.py`, `refresh_competitive_docs.py --check`, `teaagent tool lint --root .` pass)
26+
- `H0` Claim and risk hygiene: **Complete** (confidence High, next gate H1)
27+
- `H1` Daily operator loop: **Complete** (confidence High, next gate H2)
28+
- `H2` Multi-surface continuity: **Partially fixed — M2 foundation wired** (confidence Medium, next gate WDA-002)
29+
- `H3` Ecosystem trust: **Partially fixed — M3 tests pass** (confidence Medium, next gate WDC-002)
30+
- `H4` Durable owner/agent operations: **Partially fixed — shadow wired** (confidence Low, next gate WDA-004)
31+
- `H5` Quality and eval loop: **Partially fixed — release gate wired** (confidence Low, next gate WDA-005)
32+
- `M0` (1-2 weeks): **High** (next gate All 3 checks pass: `validate_docs_consistency.py`, `refresh_competitive_docs.py --check`, `teaagent tool lint --root .`)
3033
- `M1` (2-6 weeks): **High** (next gate CLI/TUI cockpit parity acceptance, run evidence summary acceptance, guided recovery acceptance)
31-
- `M2` (4-10 weeks): **Medium** (next gate Long-session context guard acceptance, scope budget acceptance, plan revision acceptance)
32-
- `M3` (8-14 weeks): **Medium** (next gate Extension activation explain acceptance, MCP trust onboarding acceptance, subagent review/merge acceptance)
34+
- `M2` (4-10 weeks): **High** (next gate Long-session context guard acceptance, scope budget acceptance, plan revision acceptance)
35+
- `M3` (8-14 weeks): **High** (next gate Extension activation explain acceptance, MCP trust onboarding acceptance, subagent review/merge acceptance)
3336

3437
## Open Residual Risks
3538

36-
| ID | Category | Priority | Description |
37-
| --- | --- | --- | --- |
38-
| SEC-05 | Budget | P2 | Cost accounting reads `context['_cost_cents']` written by the LLM adapter — injectable by malicious adapter or prompt... |
39-
| SEC-09 | Multi-sig | P2 | Multi-sig approval hash uses 1-hour time bucket (`int(time.time()/3600)`); captured signature replayable for up to 59... |
40-
| SEC-11 | Undo | P2 | `UndoJournal._PATH_WRITE_TOOLS` covers file tools only; `workspace_run_shell_mutate` not tracked — UI shows "undo ava... |
41-
| SEC-12 | Audit | P2 | `os.fsync()` failure caught and silenced; audit degrades to in-memory only with no operator notification; disk-full a... |
42-
| SEC-13 | Testing | P1 | Critical security paths (cost tracking, audit HMAC, approval denial) mocked out in tests — bugs live undetected (conf... |
43-
| SEC-14 | Permission | P3 | `preapproved_call_ids` deprecated but still functional — old integrations or adversarial callers can pre-approve arbi... |
44-
| SEC-15 | Multi-sig | P2 | `TEAAGENT_ALLOW_DEV_SIGNATURES=1` accepts SHA-256 of `(message+pubkey)` as valid signature; no runtime guard prevents... |
45-
| SEC-16 | Code Quality | QW | Dead code at `budget_monitor.py:104-119` after early return — maintenance hazard that could accidentally activate on ... |
46-
| DS-04 | Audit | P3 | Stale `audit_trail` dict in suspension JSON predates CG-10 fix; forensic tooling may prefer the stale copy over the r... |
47-
| SC-01 | Dependencies | P2 | Two alpha packages in production lock (`opentelemetry-exporter-gcp-logging==1.12.0a0`, `opentelemetry-resourcedetecto... |
48-
| SC-02 | Dependencies | P1 | `anthropic` SDK and `pyyaml` imported at runtime but undeclared in `pyproject.toml` — silent `ImportError` on install... |
49-
| SC-03 | Dependencies | P2 | `aiohttp` and `mcp` SDK in lock as orphans — not declared, not imported in core; add 22 transitive packages to attack... |
39+
No OPEN rows found in the risk register.

teaagent/audit.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ def _apply_audit_level(self, payload: dict[str, Any]) -> dict[str, Any]:
353353
return payload
354354

355355
def add_sink(self, sink: Callable[[AuditEvent], None]) -> None:
356+
if not callable(sink):
357+
raise TypeError('audit sink must be callable')
356358
self._sinks.append(sink)
357359

358360
def enable_opentelemetry(

teaagent/cli/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ def _ferr(msg: str) -> None:
9090
chat_command,
9191
ci_review_command,
9292
clarify_command,
93+
classify_command,
9394
cloud_cancel_command,
9495
cloud_capabilities_command,
9596
cloud_list_command,
@@ -370,6 +371,7 @@ def build_parser() -> argparse.ArgumentParser:
370371
from teaagent.cli._cloud_parsers import register as register_cloud
371372
from teaagent.cli._consensus_parsers import register as register_consensus
372373
from teaagent.cli._control_plane_parsers import register as register_control_plane
374+
from teaagent.cli._coordinator_parsers import register as register_coordinator
373375
from teaagent.cli._cost_parsers import register as register_cost
374376
from teaagent.cli._ergonomics_parsers import register as register_ergonomics
375377
from teaagent.cli._gateway_parsers import register as register_gateway
@@ -556,6 +558,10 @@ def build_parser() -> argparse.ArgumentParser:
556558
'relay_submit': consensus_relay_submit_command,
557559
},
558560
)
561+
register_coordinator(
562+
subparsers,
563+
{'classify': classify_command},
564+
)
559565
register_sandbox(
560566
subparsers,
561567
{
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""Coordinator CLI argument parsers."""
2+
3+
from __future__ import annotations
4+
5+
import argparse
6+
from typing import Any
7+
8+
9+
def register(
10+
subparsers: argparse._SubParsersAction,
11+
handlers: dict[str, Any],
12+
) -> None:
13+
"""Register coordinator subcommands."""
14+
classify_cmd = subparsers.add_parser(
15+
'classify', help='Classify a task by type and complexity'
16+
)
17+
classify_cmd.add_argument('task', help='Task description to classify')
18+
classify_cmd.set_defaults(func=handlers['classify'])

teaagent/cli/_handlers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
consensus_wait_command,
7878
)
7979
from ._control_plane import control_plane_serve_command
80+
from ._coordinator import classify_command
8081
from ._cost import cost_report_command
8182
from ._doctor import (
8283
doctor_aigateway,
@@ -348,6 +349,7 @@
348349
'skill_verify_tsb_command',
349350
'chat_command',
350351
'clarify_command',
352+
'classify_command',
351353
'completion_command',
352354
'configure_command',
353355
'init_command',

0 commit comments

Comments
 (0)