fix(lanes): keep stage detection honest across rollbacks and feature switches
Three defects let a lane's pipeline map claim progress that was not this
pass's work, all of them on the "going back" path a new request takes:
- `setStage` cleared the detection columns on a real transition but never
pruned the `stages` records AHEAD of the new stage. A lane that ran through
`done` and was then declared back at `plan` rendered `plan` as `current`
while `tests`/`review`/`done` still read `done`, carrying the previous
pass's evidence, and contradicting `progress` (computed from the declared
index alone). A backwards declaration now drops every record it can prove
is ahead; a key matching no node is unplaceable and left alone.
- `activateFeature` rewrote the live lane row for the incoming feature but
carried the outgoing one's `detected_*` across. A never-seen slug starts at
`stage='idle'`/`stages={}`, exactly the shape `inferredDisplayStage` renders
from detection, so the new feature opened painted with the old one's
progress — and forward-only rejected every real detection for it until the
carried-over one aged past DETECTION_TTL_MS. Now cleared, like every other
real transition; deliberately not archived, since detection is live-only.
- `codex-ingest` classified a rollout journal by raw `now - mtime`, which goes
negative for a future mtime (clock stepped back, NTP correction, a restore
that preserved timestamps) and read as "written milliseconds ago". A
finished thread's journal could replay as live work; a file claiming to be
from the future is now idle.
Also fixes `check-headers.sh`, which audited via `find` and so reported local
gitignored runtime state (a lane's own `.ccam/profile/hooks/*.sh`) that is not
this repo's source and can never be made compliant here. It now lists files
through git (tracked + untracked-but-not-ignored), so a file an agent just
wrote is still caught before it is staged while ignored state is not.
Tests: 1359 pass (4 new). Header audit exits 0.
This commit is contained in:
@@ -24,8 +24,9 @@ that is missing the header, add it as part of the same change.
|
||||
| -------- | -------- |
|
||||
| `*.js`, `*.ts`, `*.tsx`, `*.cjs`, `*.mjs` | anything under `node_modules/`, `dist/`, `build/`, `data/` |
|
||||
| `*.py`, `*.sh` | vendored/minified files (`*.min.js`) |
|
||||
| `*.css` | generated files (they carry their own AUTO-GENERATED banner) |
|
||||
| `*.css` | generated files (they carry their own AUTO-GENERATED banner), including the committed `mcp/build/` |
|
||||
| | snapshots (`__snapshots__/`), lockfiles, JSON/YAML/Markdown |
|
||||
| | anything **gitignored** — local runtime state that happens to live in the checkout (a lane's own `.ccam/profile/hooks/*.sh`, a scratch venv) is not this repo's source and can never be made compliant here |
|
||||
|
||||
## Header formats by file type
|
||||
|
||||
@@ -106,6 +107,11 @@ bash skills/file-headers/scripts/check-headers.sh
|
||||
Exit code `0` = fully compliant; `1` = the printed files are missing headers.
|
||||
Run it before finishing any change-set that adds files, and during reviews.
|
||||
|
||||
It audits the files **git can see** — tracked plus untracked-but-not-ignored —
|
||||
so a file you just wrote is caught before it is staged, while gitignored local
|
||||
runtime state is not reported. It therefore needs to run inside a git work tree
|
||||
and exits `1` with a message if it is not.
|
||||
|
||||
On every pull request, GitHub Actions runs
|
||||
`skills/file-headers/scripts/check-headers-pr.sh` against only the
|
||||
files changed in the PR diff (added, copied, renamed, or modified). Test locally
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
# check-headers.sh — audit the repo for applicable source files missing the
|
||||
# mandatory copyright/authorship header (see skills/file-headers).
|
||||
# Prints each non-compliant file; exits 0 when fully compliant, 1 otherwise.
|
||||
#
|
||||
# The file list comes from git (tracked + untracked-but-not-ignored), never a
|
||||
# raw `find`: the header rule governs this repository's SOURCE, and a `find`
|
||||
# also walks local runtime state that happens to live in the checkout — a
|
||||
# lane's own `.ccam/profile/hooks/*.sh`, a scratch venv — which is gitignored,
|
||||
# differs per machine, and can never be made compliant here. Untracked files
|
||||
# are still audited, so a file an agent just wrote is caught before it is
|
||||
# staged. The extra excludes below are for paths git DOES track (or would list)
|
||||
# but the rule exempts — notably `mcp/build/`, which is committed on purpose
|
||||
# (plugin MCP servers start before anything could build them) yet is still
|
||||
# generated tsc output, and snapshots.
|
||||
# @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
|
||||
set -euo pipefail
|
||||
@@ -9,20 +20,22 @@ set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
||||
AUTHOR_MARK="@author Nguyễn Ngọc Trí Vĩ"
|
||||
|
||||
if ! git -C "$ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
echo "check-headers.sh: $ROOT is not a git work tree — nothing to audit against." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
missing=0
|
||||
while IFS= read -r f; do
|
||||
if ! grep -q "$AUTHOR_MARK" "$f"; then
|
||||
echo "MISSING HEADER: ${f#"$ROOT"/}"
|
||||
[ -f "$ROOT/$f" ] || continue # a staged deletion still lists
|
||||
if ! grep -q "$AUTHOR_MARK" "$ROOT/$f"; then
|
||||
echo "MISSING HEADER: $f"
|
||||
missing=1
|
||||
fi
|
||||
done < <(
|
||||
find "$ROOT" \
|
||||
\( -name node_modules -o -name dist -o -name build -o -name .git \
|
||||
-o -path "$ROOT/data" -o -path "$ROOT/monitoring/.bin" \
|
||||
-o -path "$ROOT/monitoring/.data" -o -name "__snapshots__" \) -prune -o \
|
||||
-type f \( -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.cjs" \
|
||||
-o -name "*.mjs" -o -name "*.py" -o -name "*.sh" -o -name "*.css" \) \
|
||||
! -name "*.min.js" -print
|
||||
git -C "$ROOT" ls-files --cached --others --exclude-standard |
|
||||
grep -E '\.(js|ts|tsx|cjs|mjs|py|sh|css)$' |
|
||||
grep -vE '\.min\.js$|(^|/)(__snapshots__|node_modules|dist|build)/|^(data|monitoring/\.(bin|data))/' || true
|
||||
)
|
||||
|
||||
if [ "$missing" -eq 0 ]; then
|
||||
|
||||
Reference in New Issue
Block a user