Files
Claude-Code-Monitor/docs/superpowers/specs/2026-08-05-integration-toggle-design.md
T
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

4.3 KiB

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.cwdlane.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).