Follow-up from Codex review on PR #103 (P2, lib/clauck:459).
Problem
PR #103 replaced the filename-suffix exclusion with a manifest-based check: treat a log as a DAG orchestration log if the job name in the filename does NOT appear in the manifest. This is better than the naive `.endswith("-dag")` but introduces a new edge case.
If a user installs two jobs — `standup` (root of a DAG) and `standup-dag` (a real, separate job that happens to be named `-dag` of another job) — the DAG runner writes `standup-dag--.log` for the `standup` DAG run. The parser sees the name segment `standup-dag`, finds it in the manifest, and classifies the orchestration log as a real job log for `standup-dag`. Pollution: DAG orchestration records pollute `standup-dag`'s cost/history metrics.
Fix
Make the DAG log pattern distinguishable from regular job logs by the timestamp position, not the suffix:
- Regular log: `-<8+digit-ts>Z-.log`
- DAG log: `-dag-<8+digit-ts>Z-.log`
Anchor on `\b-dag-\d{8}T\d{6}Z-\d+\.log$` for DAG logs. This survives jobs actually named `*-dag` because the detection is "literal `-dag-` followed immediately by the timestamp", which a job named `standup-dag` won't match (its log would be `standup-dag-Z-.log` — same pattern, collision remains). Hmm.
Real fix: make dag-runner write orchestration logs to a distinct subdirectory (`~/.clauck/.dag-logs/`) or a distinct prefix that can never collide with a job name (e.g., `dag-...`). This is a small change in dag-runner.py and cleanly separates concerns.
Acceptance
- Jobs literally named `*-dag` appear correctly in `clauck history` and `clauck cost` with accurate counts.
- DAG orchestration logs remain excluded from per-job metrics.
- Test covering: install jobs `standup` + `standup-dag`, run a DAG of `standup`, verify `clauck cost standup-dag` does not double-count.
Follow-up from Codex review on PR #103 (P2, lib/clauck:459).
Problem
PR #103 replaced the filename-suffix exclusion with a manifest-based check: treat a log as a DAG orchestration log if the job name in the filename does NOT appear in the manifest. This is better than the naive `.endswith("-dag")` but introduces a new edge case.
If a user installs two jobs — `standup` (root of a DAG) and `standup-dag` (a real, separate job that happens to be named `-dag` of another job) — the DAG runner writes `standup-dag--.log` for the `standup` DAG run. The parser sees the name segment `standup-dag`, finds it in the manifest, and classifies the orchestration log as a real job log for `standup-dag`. Pollution: DAG orchestration records pollute `standup-dag`'s cost/history metrics.
Fix
Make the DAG log pattern distinguishable from regular job logs by the timestamp position, not the suffix:
Anchor on `\b-dag-\d{8}T\d{6}Z-\d+\.log$` for DAG logs. This survives jobs actually named `*-dag` because the detection is "literal `-dag-` followed immediately by the timestamp", which a job named `standup-dag` won't match (its log would be `standup-dag-Z-.log` — same pattern, collision remains). Hmm.
Real fix: make dag-runner write orchestration logs to a distinct subdirectory (`~/.clauck/.dag-logs/`) or a distinct prefix that can never collide with a job name (e.g., `dag-...`). This is a small change in dag-runner.py and cleanly separates concerns.
Acceptance