-
Notifications
You must be signed in to change notification settings - Fork 0
feat(spacecraft-steelbore-standard): §15.4/§15.5 — agent work log — v2.04 #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ description: > | |
| Spacecraft Software-umbrella project — even if the user doesn't explicitly mention the Standard. | ||
| If the user mentions "Spacecraft Software", a Spacecraft Software subproject name, or asks you to work on | ||
| anything in the Spacecraft Software ecosystem, consult this skill immediately. It encodes | ||
| The Steelbore Standard v2.03 (§19-§26 assurance + requirements + V&V; §13 design systems; §3.1.1 TypeScript; §5.7 AGENTS.md; §6.4 contribution targets; §5.6 skill packaging; §11 palettes + §11.6 system theme; §18 accessibility; §17 progress reporting; §3.3 security-by-design) so | ||
| The Steelbore Standard v2.04 (§19-§26 assurance + requirements + V&V; §13 design systems; §3.1.1 TypeScript; §5.7 AGENTS.md; §6.4 contribution targets; §5.6 skill packaging; §11 palettes + §11.6 system theme; §18 accessibility; §17 progress reporting; §3.3 security-by-design) so | ||
| you never need to ask for it or have it attached to a prompt again. | ||
| license: GPL-3.0-or-later | ||
| maintainer: Mohamed Hammad <Mohamed.Hammad@SpacecraftSoftware.org> | ||
|
|
@@ -17,7 +17,7 @@ website: https://Construct.SpacecraftSoftware.org/ | |
|
|
||
| # The Steelbore Standard — Compliance Reference | ||
|
|
||
| **Version:** 2.03 | **Date:** 2026-09-14 | **Author:** Mohamed Hammad | ||
| **Version:** 2.04 | **Date:** 2026-09-14 | **Author:** Mohamed Hammad | ||
| **Maintainer:** Mohamed Hammad | **Contact:** [Mohamed.Hammad@SpacecraftSoftware.org](mailto:Mohamed.Hammad@SpacecraftSoftware.org) | ||
| **Copyright:** Copyright (C) 2026 Mohamed Hammad & Spacecraft Software | **License:** GPL-3.0-or-later | ||
| **Website:** [https://Construct.SpacecraftSoftware.org/](https://Construct.SpacecraftSoftware.org/) | ||
|
|
@@ -1095,6 +1095,182 @@ SPDX headers (§4) cover license compliance mechanically; `CREDITS.md` is | |
| the human-readable narrative — who, what, and how the upstream work | ||
| shaped the Spacecraft Software artifact. | ||
|
|
||
| ### §15.4 — Authoring Model Attribution | ||
|
|
||
| §15.2 records who maintains a Spacecraft Software artifact and §15.3 records whose | ||
| work it stands on. Neither records *what produced it*. When a language model drafts | ||
| a requirements document, an implementation plan, or a task list — or codes a project | ||
| outright — that fact stays legible for about as long as the session lasts. Which | ||
| model, at what reasoning effort, served by which provider, driven by which harness: | ||
| the answer lives in the maintainer's memory of the session and decays quickly. | ||
|
|
||
| This section obligates a record. §15.5 specifies its form — an append-only log, | ||
| `.agent-log.jsonl`, written by the harness. | ||
|
|
||
| **The record is local, and deliberately so.** §15.5 requires the log to be | ||
| git-ignored, so it never reaches a clone and makes no published claim about the | ||
| artifact. It serves the working copy that produced the work: what the maintainer can | ||
| ask, months later, about which model and configuration did what, how often tests | ||
| passed on the first attempt, and what the work cost. An artifact that must tell | ||
| *consumers* who stands behind it uses §15.2, which is unchanged. | ||
|
|
||
| Commit trailers do not serve this purpose. A `Co-Authored-By` line is unstructured, | ||
| is lost to squash-merges and to the history rewrites §6.3 permits, and names a | ||
| product without the reasoning effort, the inference provider, the harness, or any | ||
| measurement of the work. The §15.5 log is machine-readable and carries all of them. | ||
| The two are independent, both MAY be used, and §15.4 does not displace the trailer | ||
| convention. | ||
|
|
||
| **Triggers** (any one obligates a record): | ||
|
|
||
| - A Product Requirements Document (PRD). | ||
| - An implementation plan. | ||
| - A TODO or task list that drives implementation. | ||
| - A project whose initial implementation was substantially produced by a model. | ||
|
|
||
| **Not triggered by:** | ||
|
|
||
| - Chat answers, scratch output, and anything that is not committed. | ||
| - A model that only reviewed, critiqued, or reformatted an artifact it did not author. | ||
|
|
||
| **Provider and harness are independent, and both are recorded.** The **provider** is | ||
| the service that served the inference — `Anthropic`, `zAI`, `Ollama Cloud`, | ||
| `OpenRouter`, `OpenCode Zen`, or a local `Ollama`. The **harness** is the agent | ||
| client that drove it — `Claude Code`, `OpenCode`, `Codex`, `Orca`, `OpenClaude`, | ||
| `ZCode`, `Antigravity IDE`, `Antigravity CLI`. The same model reaches a repository | ||
| through many combinations of the two, and it is the combination, not the model alone, | ||
| that makes a result reproducible. | ||
|
|
||
| **Reasoning effort is recorded separately** in the `reasoning_effort` field, not | ||
| folded into the model identifier. Where a model exposes a thinking or effort setting, | ||
| the bare identifier is incomplete — the same weights at a different level produce | ||
| materially different work. Where a model exposes no such setting, the field is omitted. | ||
|
|
||
| **A record is not an authorship claim.** The copyright holder and maintainer remain | ||
| as §15.2 states, and the artifact's license is unchanged. §15.4 records a production | ||
| fact, not legal authorship: it MUST NOT appear in an `SPDX-FileCopyrightText` tag, in | ||
| a `# Maintainer:` line, or in `--version` output, and it never displaces the §15.2 | ||
| attribution block. | ||
|
|
||
| ### §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 | ||
| created on first append; its absence is not an error, and a repository to which no | ||
| trigger has applied carries none. | ||
|
|
||
| **Append-only.** Each line is one complete JSON object, written once and never | ||
| rewritten, reordered, or deleted. The file is not a JSON array: there is no enclosing | ||
| bracket and no separating comma, so an append is a single write that cannot corrupt | ||
| what precedes it. A process that rewrites earlier lines has destroyed the only | ||
| property the format provides. | ||
|
|
||
| **Git-ignored, and excluded from agent context.** A `.gitignore` entry for | ||
| `.agent-log.jsonl` is REQUIRED. The log is working-copy state, not a published | ||
| artifact, and committing it makes every branch that runs an agent session conflict on | ||
| the same file. It SHOULD also be excluded from the file context agents are given | ||
| (`.cursorignore` and the equivalent for other harnesses): it grows without bound, and | ||
| an agent that reads its own log wastes context on data it cannot act upon. | ||
|
|
||
| This does not conflict with §5.7, which requires `AGENTS.md` and `CLAUDE.md` to be | ||
| tracked. Those are context files that carry project knowledge a fresh clone needs; | ||
| the log is a local measurement record that a fresh clone has no use for. | ||
|
|
||
| **The harness writes it, not the model.** Token counts are not observable by a model | ||
| during its own session, and a model instructed to report them will supply plausible | ||
| invented numbers. The log is therefore generated by the harness — a hook, wrapper, or | ||
| client feature with access to the real session record. **A field the harness cannot | ||
| determine is omitted, never estimated.** An absent field is a truthful statement that | ||
| the value is unknown; a guessed one silently corrupts every later query. | ||
|
|
||
| **Timestamps** are RFC 3339 UTC with a `Z` suffix, per §14.3, which already requires | ||
| UTC + `Z` for all `jsonl` machine output. | ||
|
|
||
| **Schema.** Unknown fields are permitted — a harness MAY record more than this table | ||
| names — but the required fields MUST be present on every line. | ||
|
|
||
| | Field | Type | Required | Example | | ||
| |-----------------------|-------------|----------|----------------------------| | ||
| | `task_id` | `string` | Yes | `"T-102"` | | ||
| | `timestamp` | `string` | Yes | `"2026-09-14T20:25:00Z"` | | ||
| | `model` | `string` | Yes | `"claude-opus-5"` | | ||
| | `provider` | `string` | Yes | `"Anthropic"` | | ||
| | `harness` | `string` | Yes | `"Claude Code"` | | ||
| | `files_touched` | `string[]` | Yes | `["src/adapters/db.rs"]` | | ||
| | `reasoning_effort` | `string` | No | `"high"` | | ||
| | `subagent_role` | `string` | No | `"implementer"` | | ||
| | `test_pass_first_try` | `boolean` | No | `true` | | ||
| | `iterations` | `integer` | No | `2` | | ||
| | `tokens_in` | `integer` | No | `12450` | | ||
| | `tokens_out` | `integer` | No | `890` | | ||
|
|
||
| `files_touched` holds repository-relative paths, so a log stays meaningful when the | ||
| working copy moves. A file edited outside the repository root is recorded by absolute | ||
| path instead: a relative path that escapes the root resolves nowhere once the working | ||
| copy has moved, which is the failure the relative form exists to avoid. `task_id` is | ||
| whatever identifier the surrounding process uses — an issue key, a plan milestone, or | ||
| the harness session id where nothing better exists. | ||
|
|
||
| **Example.** Two tasks, the second by a different model under a different harness: | ||
|
|
||
| ```jsonl | ||
| {"task_id":"T-102","timestamp":"2026-09-14T20:25:00Z","model":"claude-opus-5","provider":"Anthropic","harness":"Claude Code","reasoning_effort":"high","subagent_role":"implementer","files_touched":["src/adapters/db.rs"],"test_pass_first_try":true,"tokens_in":12450,"tokens_out":890} | ||
| {"task_id":"T-103","timestamp":"2026-09-14T21:10:00Z","model":"o3-mini","provider":"OpenAI","harness":"Codex","subagent_role":"auditor","files_touched":["tests/db_test.rs"],"test_pass_first_try":false,"iterations":2,"tokens_in":18200,"tokens_out":1450} | ||
| ``` | ||
|
|
||
| **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 | ||
|
Comment on lines
+1221
to
+1222
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do not equate every AGENTS.md reference: AGENTS.md:L47-L52 Useful? React with 👍 / 👎. |
||
| omits `model` if the transcript never names one: | ||
|
Comment on lines
+1221
to
+1223
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do not instruct the reference hook to omit AGENTS.md reference: AGENTS.md:L47-L52 Useful? React with 👍 / 👎. |
||
|
|
||
| ```python | ||
| #!/usr/bin/env python3 | ||
| """SessionEnd hook: append one .agent-log.jsonl line per session.""" | ||
| import datetime, json, os, sys | ||
|
|
||
| ev = json.load(sys.stdin) # session_id, transcript_path, cwd | ||
| tin = tout = 0 | ||
| model = None | ||
| files = set() | ||
|
|
||
| with open(ev["transcript_path"], encoding="utf-8") as fh: | ||
| for line in fh: | ||
| try: | ||
| rec = json.loads(line) | ||
| except ValueError: | ||
| continue # tolerate a torn final line | ||
| msg = rec.get("message") or {} | ||
| usage = msg.get("usage") or {} | ||
| tin += usage.get("input_tokens", 0) | ||
| tout += usage.get("output_tokens", 0) | ||
| model = msg.get("model") or model | ||
| 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: | ||
|
Comment on lines
+1246
to
+1249
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Filter by the tool operation before populating AGENTS.md reference: AGENTS.md:L47-L52 Useful? React with 👍 / 👎. |
||
| rel = os.path.relpath(path, ev["cwd"]) | ||
| # A file outside the repository has no meaningful | ||
| # relative path; record it absolute rather than as | ||
| # a ../../.. chain that resolves nowhere. | ||
| files.add(path if rel.startswith("..") else rel) | ||
|
|
||
| entry = { | ||
| "task_id": os.environ.get("AGENT_TASK_ID", ev["session_id"]), | ||
| "timestamp": datetime.datetime.now(datetime.timezone.utc) | ||
| .strftime("%Y-%m-%dT%H:%M:%SZ"), | ||
| "model": model, | ||
| "provider": "Anthropic", | ||
| "harness": "Claude Code", | ||
| "files_touched": sorted(files), | ||
| "tokens_in": tin, | ||
| "tokens_out": tout, | ||
| } | ||
|
|
||
| with open(os.path.join(ev["cwd"], ".agent-log.jsonl"), "a", | ||
| encoding="utf-8") as fh: | ||
|
Comment on lines
+1268
to
+1269
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Write relative to the Git repository root rather than AGENTS.md reference: AGENTS.md:L47-L52 Useful? React with 👍 / 👎. |
||
| fh.write(json.dumps({k: v for k, v in entry.items() | ||
| if v is not None}) + "\n") | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## §17 — Development Progress Tracking & Reporting | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 👍 / 👎.