PR #119 — BS-12: The Agent Autonomy Bridge
Date: 2026-07-05
PR: #119
Branch: feat/bs12-agent-autonomy-bridge → main
The Goal at the End of the Previous PR
After Vizor's Efficiency tab shipped (BS-22, PR #118), every partially-visible feature in the HUD was complete enough for Developer Preview. The outstanding strategic gap was the trust boundary between synlynk and its agents: synlynk could dispatch agents and watch them run, but it had no way to control what they were allowed to do, adjust their configuration per-project, recover when they stalled, guide users through fixing health check failures, or guarantee that agents had internalized the workflow discipline needed to operate autonomously.
That gap is BS-12.
What Moved the Goalpost in This PR
Brainstorming BS-12 surfaced a scope question: the original ticket covered only permissions and harness config. But the session also identified that agent directive files (CLAUDE.md, GEMINI.md, AGENTS.md, GROK.md) were missing explicit SOP coverage for the six workflow disciplines the team had committed to — PR review discipline, brainstorm-first policy, design-spec sequencing, capability-based allocation, cost visibility, and repo hygiene.
These SOPs weren't in a separate ticket. They belong in BS-12 because synlynk init and synlynk sync are the delivery mechanism, and the doctor wizard (Scope D) is the enforcement surface. Adding them as Scope E made BS-12 the complete trust-boundary release.
The session also produced a firm priority for the two engagement drivers:
- Completeness of every visible feature — no skeleton tabs, no placeholder commands
- No drop in engagement — every new command and surface should make agents easier to use, not harder
Both shaped scope decisions throughout. The handoff protocol (Scope C) addresses engagement continuity when agents stall. The doctor wizard (Scope D) addresses completeness of the health-check experience.
What Shipped
Scope A — Permission Grants
Role entries in .synlynk/config.json now carry a default permission set, defined in synlynk/_constants.py as _ROLE_PERMISSION_DEFAULTS. Twelve roles are mapped to named capability tiers: pm/review/deploy get read:*; implement/test/refactor get read:*,write:src/,run:tests; css/templates/content add write:docs/; canvas/js/infra add run:shell.
synlynk dispatch gains --grant <perm> and --revoke <perm> flags for per-task overrides. Resolution order: role defaults → .agents/<agent>.json grants/revokes → per-call flags.
Translation to agent CLI flags via _permissions_to_flags() in synlynk/dispatch.py:
- Claude:
--allowedToolslist - Codex:
--approval-policy(none/untrusted/all) - Agy: injected as a
## Permissionssection in the task context header (no CLI flag available)
Scope B — Per-Project Harness Config
New subcommand: synlynk configure agent <name> [--flag k=v] [--env K=V] [--network-dep host:port]
Writes to .agents/<agent>.json under a new harness_overrides key. dispatch_agent() merges at call time: baseline → .agents/harness_overrides → per-call grant/revoke. synlynk doctor TC-2 now reads the merged config rather than the hardcoded baseline.
Scope C — Handoff Protocol
When a running job accumulates a STALL_NO_OUTPUT, FLATLINE, or QUOTA_EXHAUSTED sentinel, synlynk now writes a HANDOFF_PENDING sentinel and surfaces the job in:
synlynk jobs --stalled
The stalled view shows: job ID, agent, failure sentinel, elapsed time, and the recommended next agent derived from the cycle-capability matrix.
Transfer command:
synlynk jobs handoff <job_id> [--to <agent>]
On handoff:
- Job context file (
.synlynk/contexts/<job_id>.md) gets a## Handoff Noteappended with failure reason + previous agent jobs.handoff_countincremented,jobs.previous_agents(JSON array) updated- New dispatch launched with the updated context file + new agent
HANDOFF_PENDINGsentinel cleared
Schema additions:
ALTER TABLE jobs ADD COLUMN handoff_count INTEGER DEFAULT 0;
ALTER TABLE jobs ADD COLUMN previous_agents TEXT; -- JSON array
Both columns are added via migration in _get_db() on first access — no manual migration required.
Scope D — Doctor Guided Fix Wizard + Escalate
After each TC check failure, synlynk doctor now enters an interactive fix loop rather than just printing and exiting. The wizard uses the existing termios-based TUI pattern from cmd_wizard.
Structured fix paths per TC:
| TC | Failure | Fix offered |
|---|---|---|
| TC-1 | Requires PTY | Show PTY workaround + offer to write config note |
| TC-2 | Bad flags | Apply recommended flags to .agents/<agent>.json |
| TC-3 | Network unreachable | Show endpoint list, offer to skip or proxy |
| TC-4 | Missing verbs | Run synlynk configure agent <name> |
| TC-5 | Missing SOP sections | Run synlynk sync --repair-sops (targeted, not full sync) |
Always-available escape: "I'm stuck" — assembles a failure context string from TC results + agent config + last 5 telemetry rows, then calls dispatch_agent("claude", task=<context>). Claude handles the diagnosis conversationally from the same terminal.
Scope E — SOP Codification
Six SOP string constants added to synlynk/probe.py:
| Constant | Section header |
|---|---|
_PR_REVIEW_SOP |
## PR Review Discipline |
_BRAINSTORM_SOP |
## Brainstorm-First Policy |
_DESIGN_SEQUENCE_SOP |
## Design → Plan → Build Sequence |
_CAPABILITY_ALLOCATION_SOP |
## Capability-Based Task Allocation |
_COST_VISIBILITY_SOP |
## Cost Visibility |
_REPO_HYGIENE_SOP |
## Repo Hygiene |
All six are injected into CLAUDE.md, GEMINI.md, AGENTS.md, and GROK.md at synlynk init and synlynk sync time via _build_templates().
TC-5 in synlynk doctor: Scans each directive file for all six section headers. Warning (not failure) if absent — non-blocking, matches the existing status philosophy.
synlynk sync --repair-sops: Reads the existing harness fence body, appends only the missing SOP sections, writes back the merged body. Idempotent: running twice produces no change on the second run.
Tests
28 new tests added; suite went from 837 → 868 passing (including 3 added in the review fix pass).
Review Fixes Applied
A code review after initial implementation caught 6 issues fixed before merge:
- Blocking:
--repair-sopscalled_upsert_harness_fencewith only the missing block as body, replacing the entire existing fence. Fixed: reads existing fence body, merges missing sections in. - Blocking: TC-5 result omitted from
all_passedincmd_doctor. Doctor exited 0 despite SOP failures. Fixed:all_passednow includestc5['passed']. - Warning: Handoff note appended to context file but not included in
handoff_tasksent to new agent. Fixed:handoff_taskrebuilt after append. - Warning: TC-5 fix menu appeared for every agent in the loop, even those with no missing sections. Fixed: check
tc5['missing'].get(agent)per-agent. - Warning:
--flag KEY(boolean flag without=) insynlynk configure agentraisedValueError. Fixed:item.partition('=')withTrueas fallback value. - Warning: TC-5 doctor fix called full
cmd_syncinstead of targeted SOP repair. Fixed: extracted_repair_sops_only()helper.
Brainstorm Visuals
The architecture, scope decisions, and task allocation were developed in a visual brainstorm session. Key frames:
- Architecture overview — 5 scopes, 3 shared data foundations, 5-phase delivery
- Task allocation — Codex owns Python/TUI/CLI plumbing, Agy owns SOP prose and UX copy
- Handoff option selection — prompt-then-handoff chosen over silent auto-handoff
Full brainstorm HTML: docs/brainstorm/bs12-agent-autonomy-bridge/
What This Achieved
BS-12 closes the trust boundary. synlynk can now:
- Control what agents can do — role defaults prevent accidental writes or shell execution by review-only agents
- Configure agents per project — no more editing source to adjust a flag for a specific repo
- Recover from stalls — HANDOFF_PENDING +
jobs handoffkeeps work moving when an agent quota-exhausts or flatlines - Guide users through failures — the doctor wizard replaces manual diagnosis with structured fix paths and a Claude escalation escape hatch
- Enforce workflow discipline at init time — every new repo gets the full SOP playbook baked into all four directive files
Combined with the Live Job Observatory (BS-13) and Vizor (BS-21/22), the Developer Preview now has a complete operational layer: dispatch, observe, diagnose, repair, and hand off — all from the CLI.
The New Goalpost
BS-12 and BS-22 together represent the completion of the v0.11.0 milestone: the Agent Ecosystem Operational Layer. The next focus is the v0.11.0 named release — CHANGELOG entry, VERSION bump, GitHub Release, and a release blog post capturing the full arc from BS-13 through BS-12.
After that: chore/modularise-init (prerequisite for BS-16), then BS-16 Ecosystem Status + Capacity to replace the is_placeholder data paths in Vizor with live telemetry.