# Deploy Status Filesystem Integrity

audience: AI coding agents first.

status: ACTIVE
task IDs: #33, #8
source request: Fix confirmed filesystem false greens in commit `4bcd0d9eb19669a226756bdf146dc8c119559ead`. Own only deploy-status adapter/tests and adapter index test. Distinguish absent lock from inaccessible/error; errors => unknown/incomplete. Validate `req-*` exact grammar and regular non-symlink files using `lstat`; malformed entries => incomplete, never authoritative queue depth. Held lock without authoritative lifecycle/progress => unknown/incomplete, not running. Do not invent events or touch packaging. Add negative tests. Run focused, full collector tests, typecheck with zero warnings. Commit fix.

Correction after commit `675a9d115`: `readLock` currently classifies any `ENOENT` caught while reading lock state as an absent lock, including `readFile("/proc/locks")`. Absence applies only when `lstat(lockPath)` returns `ENOENT`; every later failure, including `ENOENT` from `/proc/locks`, is unavailable/unknown/incomplete. Add negative regression coverage distinguishing those paths. Preserve WIP; edit and commit only this plan receipt plus `collector/src/adapters/deploy-status.ts` and `collector/src/adapters/deploy-status.test.ts`. Run focused deploy-status and adapter-index tests, full collector suite, and collector typecheck with zero warnings.

## Outcome

Eliminate false green deploy-status results from untrusted, malformed, inaccessible, or lifecycle-incomplete filesystem data.

## Acceptance criteria

- Missing lock remains distinct from filesystem access/error states.
- Filesystem errors yield unknown/incomplete status.
- Only `req-*` entries matching exact accepted grammar and regular non-symlink files verified with `lstat` affect queue depth.
- Malformed entries yield incomplete status; never authoritative queue depth.
- Held lock without authoritative lifecycle/progress yields unknown/incomplete, never running.
- Negative adapter and adapter-index tests cover these cases.
- Focused tests, full collector tests, and collector typecheck pass with zero warnings.
- Commit contains only deploy-status adapter/tests, adapter-index test, and this plan/index receipt.

## Preserved WIP

Worktree `/home/user/Projects/overdeck/.worktrees/ci-status-collector` was clean before work. No unrelated WIP touched.

## Constraints

- Scope: `collector/src/adapters/deploy-status.ts`, `collector/src/adapters/deploy-status.test.ts`, `collector/src/adapters/index.test.ts`; plan registry required by project policy.
- Do NOT invent events or modify packaging.
- Validate filesystem trust boundary with `lstat`; do NOT follow symlinks.
- Treat failures conservatively. No authoritative queue depth or running status from incomplete evidence.

## Execution steps

1. Inspect commit `4bcd0d9eb19669a226756bdf146dc8c119559ead`, current adapter contract, and tests.
2. Add narrow filesystem classification and exact lock-entry validation.
3. Add negative tests for inaccessible/error, malformed/symlink entries, and lifecycle-incomplete held locks.
4. Run focused adapter tests, full collector tests, and typecheck; resolve every signal.
5. Update receipt and commit scoped repair.

## Current receipt

DONE — commit `2f2bcdba25940191c41071c6314d854155c45675` restricts absent lock classification to `lstat(lockPath)` `ENOENT`. Every post-`lstat` error, including `/proc/locks` `ENOENT`, now yields `deploy lock unavailable`, `unknown`, and incomplete. Regression coverage distinguishes these paths. Verification: deploy-status 13/13 pass; adapter index 6/6 pass; full collector suite 726 pass, 2 documented live-Kanboard skips, 0 fail; collector typecheck clean. Full-suite output contains six test names using `warn`, not runtime warnings. `git diff --check` clean. Commit contains only owned adapter, adapter test, and plan receipt.

## Next executable action

Orchestrator lands and deploys this collector change with its broader delivery lane.
