test-log-centralizer
Singleton dependency for all testing skills in this repo. Provides a uniform path
convention and three small bash entrypoints under scripts/ so every test layer
(unit, integration, browser, orchestrator, skill, setup, teardown) writes into the
same <project>/.test-runs/<run-id>/ folder. Output structure is documented in
docs/ARCHITECTURE.md §(b).
When to use
Activate only when invoked as a sub-step of another testing skill — typically
auto-test, unit-test-runner, browser-test, integration-test-runner,
flaky-detector, or coverage-reporter. Concretely:
- A caller skill needs to start a fresh run → run
scripts/init-run.sh. - A caller skill needs to append stdout/stderr to a per-layer stream → run
scripts/append-log.sh. Each emitted line is prefixed with an ISO-8601 UTC timestamp (ms-precision whenpython3is available, second-precision otherwise). - A caller skill needs to finalize the run (merge streams →
run.log, emitsummary.json(final form) +manifest.json+run.json, re-pointlatest) → runscripts/finalize-run.sh.
Do not activate when the user message is about reading or tailing existing
logs — that is a plain Read / Grep of <project>/.test-runs/latest/run.log
and does not need this skill.
Do not activate for non-test logging (general application logs, build output, lint output, deployment output). Those belong elsewhere.
How to use
SKILL_DIR="$(dirname "$0")/.." # caller adjusts to its own layout
# 1. Start a new run — echoes the absolute run-folder path on stdout.
RUN=$("$SKILL_DIR/scripts/init-run.sh" "<project-root>" "<runner>" "<command>")
# RUN now points to <project-root>/.test-runs/<UTC-ts>/.
# Initial folder contents (T-1.1):
# run.log (empty file; finalize-run.sh fills via stream merge)
# meta.json (run_id, start_ts, project_dir, runner, command, schema_version)
# summary.json (placeholder; finalize-run.sh promotes to final form)
# streams/ (per-layer log files; written by append-log.sh)
# screenshots/ (browser-test artifacts — Phase 2)
# 2. Append per-layer log lines.
# Inline form:
"$SKILL_DIR/scripts/append-log.sh" "$RUN" unit "starting suite tests/auth"
# Stdin form (stream a runner's stdout/stderr line-buffered):
bun test 2>&1 | "$SKILL_DIR/scripts/append-log.sh" "$RUN" unit
# Each appended line is also tee-ed to streams/all.log for live tail.
# 3. Finalize — merge streams into run.log, write final summary/manifest/run.json,
# re-point <project>/.test-runs/latest. Counts are caller-supplied (T-1.4 parsers
# fill them later); pass 0/0/0/0 for a placeholder.
"$SKILL_DIR/scripts/finalize-run.sh" "$RUN" "$EXIT_CODE" "$TOTAL" "$PASSED" "$FAILED" "$SKIPPED"
# 4. (Optional) Trigger retention sweep at end-of-run by exporting TEST_LOG_RETAIN=1
# before finalize. Default OFF so test suites for T-1.1..T-1.5 stay isolated; the
# auto-test orchestrator opts in. Equivalent to invoking retain.sh directly:
"$SKILL_DIR/scripts/retain.sh" "<project-root>/.test-runs"
# Policy: keep newest 10 plain, gzip the next 2 (run.log → run.log.gz, drop
# streams/ + screenshots/, keep run.json + manifest.json + summary.json + meta.json),
# delete anything older. Idempotent on re-run.
The <runner> and <command> arguments to init-run.sh are optional — when
omitted, meta.runner defaults to "tbd" and meta.command to the empty
string. They are filled later by the caller skill once framework detection
has run. See references/schema.md for the full JSON shape contract that
downstream skills + agents can rely on.
Examples
User says: "run the unit tests" → Claude invokes auto-test, which calls
unit-test-runner, which calls this skill's init-run.sh to scaffold the run
folder before spawning the framework.
User says: "show me the latest test log" → Claude does not invoke this skill;
it calls Read on <project>/.test-runs/latest/run.log directly.
Files
scripts/
init-run.sh — T-1.1: scaffold run folder + meta.json + summary.json placeholder
append-log.sh — T-1.2: per-layer stream append with ISO-8601 UTC ts prefix
finalize-run.sh — T-1.2: merge streams → run.log, write summary/manifest/run.json,
re-point .test-runs/latest atomically; optional retain hook (T-1.6)
retain.sh — T-1.6: count-based retention sweep (10 plain + 2 gz + prune)
references/
schema.md — T-1.2: contract for meta.json, summary.json, manifest.json, run.json
tests/
test-init-run.sh — T-1.1 acceptance (35 assertions)
test-append-log.sh — T-1.2 acceptance (36 assertions)
test-finalize-run.sh — T-1.2 acceptance (55 assertions, incl. golden compare)
test-retention.sh — T-1.6 acceptance (71 assertions, incl. 12-/14-/5-run scenarios + idempotency + finalize wiring)
goldens/
manifest.golden.json — normalized golden for finalize-run shape stability
run-all.sh — convenience runner; bash run-all.sh exits 0 when everything green
See also
docs/ARCHITECTURE.md§(b) — folder layout, retention policy,latestsymlink.docs/ARCHITECTURE.md§(f) — TestRun data-model (run.jsonschema).spike/code/log-centralizer/— Phase 0 prototype (frozen reference).