Files
Claude-Code-Monitor/docs/superpowers/specs/2026-08-05-integration-toggle-design.md
nntrivi2001 4b3a1e3d25 docs(lanes): design F3a — ccam lanes integration toggle reader (F)
Scopes down F3 to just the generic <name>_ENABLED toggle-check primitive
(ccam lanes integration <name>) — ticketer/dev-qc agents stay deferred,
same reasoning E3 already used for qc-local's credential gap: no tracker/
dev-QC MCP configured anywhere, no per-lane credential source to consume.
2026-08-05 16:04:39 +07:00

38 lines
4.3 KiB
Markdown

# F3a — `ccam lanes integration <name>` toggle reader
**Status:** approved 2026-08-05. Roadmap it belongs to:
`docs/superpowers/plans/2026-08-03-shipyard-parity-lanes.md` (subsystem **F**).
## Problem
`SKILL.md`'s Setup section hardcodes tracker/dev-QC/CI-wait as permanently off ("treat all three as permanently off for this run") because F's `integrations.env` toggle system doesn't exist in CCAM yet. Shipyard's source, `lane-env.sh --check NAME`, is the reference primitive: read one `<NAME>_ENABLED` flag from a profile's `integrations.env`, exit 0/1.
This is a narrow slice of F, not all of F3. `ticketer` (the agent that would actually consume `TRACKER_ENABLED`) is explicitly deferred — no tracker MCP is configured for any lane yet, and CCAM has no per-lane credential source (same gap E3 already documented for `qc-local`). This task only builds the toggle-reading primitive itself, so `SKILL.md`'s hardcoded-off text can become a real check instead of a permanent assumption, once something exists to check.
## Scope
**In scope:**
1. `<repo>/.ccam/profile/integrations.env` — a new, optional profile file (same directory as `profile.env`), parsed with the EXISTING `parseEnvFile` helper in `server/lib/lane-profile.js` (comments/quotes/`export` already handled — no new parser).
2. `isIntegrationEnabled(lane, name)` in `server/lib/lane-profile.js` — reads `integrations.env` (falling back `lane.cwd``lane.source_repo`, same two-location search `resolveProfile` already does for `profile.env`), returns `true` iff `<NAME_UPPER>_ENABLED === "1"`. A missing file or missing key is `false` — off by default, consistent with A2's declarations.
3. `GET /api/lanes/:id/integrations/:name` route — `{enabled: boolean}`.
4. `ccam lanes integration <name> [<id>]` CLI — exit `0` when enabled, `1` when disabled (the exit-code contract Shipyard's `--check` already established, and what a skill's `&&`-gated stage-skip logic needs).
**Explicitly out of scope:**
- `ticketer.md` / `dev-qc.md` agents — deferred pending a tracker/dev-QC MCP and credential source.
- Every other field `integrations.env` can declare (`TRACKER_URL`, `TRACKER_PROJECT`, `DEV_SITE_URL`, `CI_REPO`, etc.) — only the `<NAME>_ENABLED` flags matter for this primitive; the rest is read by whatever later task actually consumes a specific integration (F3/F4's real agent work), not by this generic toggle check.
- Surfacing toggle state in `GET /api/lanes/:id/runtime` — that endpoint is polled and broadcast on every hook; adding fields nothing consumes yet is premature. `GET /:id/integrations/:name` is its own lightweight endpoint instead.
- `lane-env.sh`'s default (no `--check`) mode — dumping the full per-lane runtime env as `export` lines exists in Shipyard because bash/zsh sourcing has a HARNESS_ROOT resolution footgun CCAM's cwd-based lane resolution doesn't have. Nothing in CCAM needs this.
## Decisions
| | Choice | Rationale |
|---|---|---|
| Reuse `parseEnvFile` | Yes, from `lane-profile.js`, unexported currently — export it | `integrations.env` is the same `KEY=VALUE` shape `profile.env` already is; a second parser for an identical format would be pure duplication. |
| Two-location search (cwd then source_repo) | Same as `profile.env` | A worktree lane's branch may have changed integration config; the source-repo fallback covers a gitignored `integrations.env` the same way it does for `profile.env`. |
| Missing file / missing key | `false` (off) | Matches every other optional profile declaration's off-by-default shape already established across A2/E1/E2. |
| Case handling | `name` argument lowercased by convention (`tracker`, `dev_qc`, `ci_wait`), uppercased + `_ENABLED` appended to build the env key | Matches Shipyard's own naming (`TRACKER_ENABLED`, `DEV_QC_ENABLED`, `CI_WAIT_ENABLED`) — the CLI argument is the lowercase, readable form; the env var stays the exact Shipyard name so a ported `integrations.env` file (if a user copies one from Shipyard) needs no field renaming. |
## Verify
Unit tests: a profile with `TRACKER_ENABLED=1` reads enabled for `tracker`, a profile with no `integrations.env` reads disabled for anything, `DEV_QC_ENABLED=0` reads disabled, the source-repo fallback works when the lane's own `cwd` has no file. CLI exit-code test via the route/CLI's own manual smoke check (no automated HTTP harness in this repo, same as every other F/E route).