feat(spacecraft-steelbore-standard): §15.4/§15.5 — agent work log — v2.04 - #70
Conversation
…2.04 Skill encoding of the Standard change landing as Spacecraft-Software/Standard#38, at the same version and date. §15.4 obligates a record of what produced an artifact; §15.5 specifies its form — an append-only `.agent-log.jsonl` at the repository root, one line per completed task, written by the harness. Replaces the never-landed v1.50 draft's committed-table mechanism (AUTHORS.md / a closing "Authoring Model" section). The log is per-task, structured, and git-ignored; §15.4 states that cost outright — the record never reaches a clone and makes no published claim. §15.2 remains the mechanism for anything aimed at consumers. Six required fields (task_id, timestamp, model, provider, harness, files_touched) and six optional. provider and harness are required because the rationale turns on the combination of the three being what makes a result reproducible. Timestamps are UTC + Z per §14.3. The harness writes the log, not the model — token counts are not observable by a model mid-session, so a field the harness cannot determine is omitted, never estimated. The reference SessionEnd hook is byte-identical to the Standard's copy. The frontmatter description takes only the version bump: it sits at 994/1000 against the §5.6 cap, and its section enumeration is illustrative rather than exhaustive. Both bundles rebuilt in this commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e9525c4d56
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ### §15.5 — Agent Work Log (`.agent-log.jsonl`) | ||
|
|
||
| The record §15.4 obligates is an append-only JSON Lines log at the repository root, | ||
| named `.agent-log.jsonl`. One line is appended per completed task. The file is |
There was a problem hiding this comment.
Add the work-log requirement to the §16 audit gate
Add a §15.4/§15.5 item to the compliance checklist: the new obligation is absent between the existing §15.3 and §17 entries, even though §16 is the audit gate agents use before finalizing artifacts. Consequently, an agent following the checklist can declare compliance without creating or ignoring .agent-log.jsonl; the v2.04 changelog also incorrectly claims that this bullet was added.
AGENTS.md reference: AGENTS.md:L47-L52
Useful? React with 👍 / 👎.
| **Reference implementation.** A Claude Code `SessionEnd` hook, treating one session | ||
| as one task. It reads the real transcript rather than asking the model anything, and | ||
| omits `model` if the transcript never names one: |
There was a problem hiding this comment.
Reconcile model omission with the required schema
Do not instruct the reference hook to omit model while the schema immediately above marks it required and says every required field MUST be present. In the explicitly anticipated case where the transcript lacks a model, this hook emits a schema-invalid line that validators or consumers expecting all six required fields must reject; either make the field optional or define compliant missing-model handling.
AGENTS.md reference: AGENTS.md:L47-L52
Useful? React with 👍 / 👎.
| for block in msg.get("content") or []: | ||
| if isinstance(block, dict) and block.get("type") == "tool_use": | ||
| path = (block.get("input") or {}).get("file_path") | ||
| if path: |
There was a problem hiding this comment.
Record only files actually modified
Filter by the tool operation before populating files_touched. This loop accepts every tool_use block with a file_path, so a read-only Read call is logged as a modification, while edits performed through Bash have no file_path and are omitted. Sessions that inspect one file and modify another through a command therefore produce a materially false work record.
AGENTS.md reference: AGENTS.md:L47-L52
Useful? React with 👍 / 👎.
| with open(os.path.join(ev["cwd"], ".agent-log.jsonl"), "a", | ||
| encoding="utf-8") as fh: |
There was a problem hiding this comment.
Resolve the repository root before writing the log
Write relative to the Git repository root rather than ev["cwd"]. When Claude Code is started from a repository subdirectory, this creates a nested .agent-log.jsonl and computes every supposedly repository-relative path from that subdirectory, violating the single root-level log contract and allowing multiple logs in one working copy.
AGENTS.md reference: AGENTS.md:L47-L52
Useful? React with 👍 / 👎.
| **Reference implementation.** A Claude Code `SessionEnd` hook, treating one session | ||
| as one task. It reads the real transcript rather than asking the model anything, and |
There was a problem hiding this comment.
Filter sessions to completed triggering tasks
Do not equate every SessionEnd with one completed task. The hook unconditionally appends for chat-only, review-only, uncommitted, or abandoned sessions—which §15.4 explicitly excludes—and collapses multiple completed tasks performed in one session into a single record. This corrupts task counts and any derived first-pass or cost metrics rather than implementing the promised one-line-per-completed-task log.
AGENTS.md reference: AGENTS.md:L47-L52
Useful? React with 👍 / 👎.
Skill encoding of Spacecraft-Software/Standard#38, landing at the same version and date (v2.04, 2026-09-14).
What
§15.2 records who maintains an artifact and §15.3 whose work it stands on. Neither records what produced it. §15.4 obligates that record; §15.5 specifies its form — an append-only
.agent-log.jsonlat the repository root, one line per completed task, written by the harness.This revives the v1.50 draft on
feat/standard-15-4-authoring-model-attribution(never opened as a PR), with the mechanism replaced. That draft required a committed table — anAUTHORS.md, or a closingAuthoring Modelsection — written once per artifact. The log is per-task, structured, and git-ignored instead, and §15.4 states the cost rather than burying it: the record never reaches a clone and makes no published claim. §15.2 remains the mechanism for anything aimed at consumers.The
Co-Authored-Bytrailer is compared and kept. §15.4 faults it for being unstructured, lost to squash-merges and the rewrites §6.3 permits, and naming a product without reasoning effort, provider, harness, or any measurement — not for recording activity, which the log does too.Schema
Required:
task_id,timestamp,model,provider,harness,files_touched. Optional:reasoning_effort,subagent_role,test_pass_first_try,iterations,tokens_in,tokens_out.providerandharnessare required because the rationale turns on the combination of the three being what makes a result reproducible. Timestamps are UTC +Z, per §14.3.The harness writes it, not the model — token counts are not observable by a model during its own session, so a field the harness cannot determine is omitted, never estimated.
Note on the frontmatter description
It takes only the version bump (
v2.03→v2.04, length-neutral). It sits at 994/1000 against the §5.6 cap, and its section enumeration is illustrative rather than exhaustive — it already omits §14, §4, and §2 — so §15.4/§15.5 are not added to it.Verification
check-skill-refs.pycheck-palette-single-source.pycheck-agents-inventories.pycheck-skill-frontmatter.pycheck-license-files.pyAlso verified: both JSONL examples parse with all required fields and
Ztimestamps; the hook block compiles; and the hook and examples are byte-identical to the Standard's copies.The reference hook was run against a real transcript during authoring, which caught a defect now fixed in both repos —
os.path.relpathturned a file edited outside the repo into a../../../../../../etc/...chain, contradicting §15.5's "repository-relative paths". In-repo paths are now relative, out-of-repo absolute.Both bundles rebuilt in the same commit.
🤖 Generated with Claude Code