From 443fc1af0e8b91904d83b6d8924f4d8add729da6 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 7 Oct 2026 12:02:34 +0200 Subject: [PATCH] spec: rename specs to issue-based IDs Specs are now named after their parent GitHub issue instead of a sequential number, so parallel spec PRs cannot take the same number. Headings and cross-references are updated to the new IDs. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Miguel Martinez Trivino --- .../internal/trace/cursor/announce_test.go | 2 +- app/cli/pkg/action/trace_agent_hook_test.go | 2 +- app/cli/pkg/action/trace_spec_test.go | 2 +- ... => issue-3063-attestation-repo-config.md} | 2 +- ....md => issue-3495-session-spec-capture.md} | 2 +- ...issue-3515-spec-capture-during-session.md} | 28 +++++++++---------- ...der.md => issue-3520-pi-trace-provider.md} | 8 +++--- ...role.md => issue-3531-spec-source-role.md} | 12 ++++---- 8 files changed, 29 insertions(+), 29 deletions(-) rename docs/specs/{001-attestation-repo-config.md => issue-3063-attestation-repo-config.md} (99%) rename docs/specs/{002-session-spec-capture.md => issue-3495-session-spec-capture.md} (99%) rename docs/specs/{003-spec-capture-during-session.md => issue-3515-spec-capture-during-session.md} (73%) rename docs/specs/{005-pi-trace-provider.md => issue-3520-pi-trace-provider.md} (96%) rename docs/specs/{004-spec-source-role.md => issue-3531-spec-source-role.md} (89%) diff --git a/app/cli/internal/trace/cursor/announce_test.go b/app/cli/internal/trace/cursor/announce_test.go index 078c70229..094a99a5e 100644 --- a/app/cli/internal/trace/cursor/announce_test.go +++ b/app/cli/internal/trace/cursor/announce_test.go @@ -80,7 +80,7 @@ func TestAnnounceSessionStart(t *testing.T) { } // TestAnnouncePromptSubmit pins that Cursor gets no reminder: it documents no -// channel that adds context at prompt submit (D-008 of Spec 003). +// channel that adds context at prompt submit (D-008 of Spec issue-3515). func TestAnnouncePromptSubmit(t *testing.T) { out := captureStdout(t, func() { require.NoError(t, New().AnnouncePromptSubmit("Chainloop spec capture.")) diff --git a/app/cli/pkg/action/trace_agent_hook_test.go b/app/cli/pkg/action/trace_agent_hook_test.go index 4664f88d5..ee3b95651 100644 --- a/app/cli/pkg/action/trace_agent_hook_test.go +++ b/app/cli/pkg/action/trace_agent_hook_test.go @@ -198,7 +198,7 @@ func TestHandleAgentSessionStart(t *testing.T) { }) } -// TestHandleAgentPromptSubmit covers R-002 of Spec 003: the reminder comes at +// TestHandleAgentPromptSubmit covers R-002 of Spec issue-3515: the reminder comes at // each user prompt, also in a resumed session whose folder holds files. func TestHandleAgentPromptSubmit(t *testing.T) { const sessionID = "abc-123" diff --git a/app/cli/pkg/action/trace_spec_test.go b/app/cli/pkg/action/trace_spec_test.go index fea09d33b..72ba2d35a 100644 --- a/app/cli/pkg/action/trace_spec_test.go +++ b/app/cli/pkg/action/trace_spec_test.go @@ -180,7 +180,7 @@ func TestSessionSpecReminder(t *testing.T) { }) } -// TestSessionSpecsAcrossPushes covers R-004 of Spec 003: a file that an +// TestSessionSpecsAcrossPushes covers R-004 of Spec issue-3515: a file that an // earlier push recorded stays in the evidence of later pushes, also when the // agent overwrote it and the session went over the limit. func TestSessionSpecsAcrossPushes(t *testing.T) { diff --git a/docs/specs/001-attestation-repo-config.md b/docs/specs/issue-3063-attestation-repo-config.md similarity index 99% rename from docs/specs/001-attestation-repo-config.md rename to docs/specs/issue-3063-attestation-repo-config.md index 2fb808419..7a09947d2 100644 --- a/docs/specs/001-attestation-repo-config.md +++ b/docs/specs/issue-3063-attestation-repo-config.md @@ -5,7 +5,7 @@ ticket: https://github.com/chainloop-dev/chainloop/issues/3063 prd: --- -# Spec 001: Project and Organization from .chainloop.yml in Attestations +# Spec issue-3063: Project and Organization from .chainloop.yml in Attestations ## Summary diff --git a/docs/specs/002-session-spec-capture.md b/docs/specs/issue-3495-session-spec-capture.md similarity index 99% rename from docs/specs/002-session-spec-capture.md rename to docs/specs/issue-3495-session-spec-capture.md index 51aa94ac6..98b1306a5 100644 --- a/docs/specs/002-session-spec-capture.md +++ b/docs/specs/issue-3495-session-spec-capture.md @@ -5,7 +5,7 @@ ticket: https://github.com/chainloop-dev/chainloop/issues/3495 prd: --- -# Spec 001: Spec capture for AI coding sessions +# Spec issue-3495: Spec capture for AI coding sessions ## Summary An AI coding session record shows what the agent changed, but not what the user asked for. This spec adds the spec of the session to its evidence. At session start, the trace hook tells the agent to write each source that sets the task into a session folder. At push time, the CLI stores each file as its own material in the attestation. The session material keeps only references to these materials. Reviewers and scoring tools can then compare the change with the request. diff --git a/docs/specs/003-spec-capture-during-session.md b/docs/specs/issue-3515-spec-capture-during-session.md similarity index 73% rename from docs/specs/003-spec-capture-during-session.md rename to docs/specs/issue-3515-spec-capture-during-session.md index c13578c0e..213ea2959 100644 --- a/docs/specs/003-spec-capture-during-session.md +++ b/docs/specs/issue-3515-spec-capture-during-session.md @@ -4,10 +4,10 @@ ticket: https://github.com/chainloop-dev/chainloop/issues/3515 prd: --- -# Spec 003: Spec capture during the session +# Spec issue-3515: Spec capture during the session ## Summary -This spec changes the spec capture of [Spec 002](002-session-spec-capture.md). It does not replace it. Today the agent captures the spec only at session start. It also captures the user prompt, which the transcript already holds. With this change, the agent does not capture the user's request prompt, because the transcript holds it. A short reminder at each user turn tells the agent to capture a new spec or image from the user. It also tells the agent to capture an approved plan, and a changed spec again. The limit on spec files for each session goes from 10 to 25. +This spec changes the spec capture of [Spec issue-3495](issue-3495-session-spec-capture.md). It does not replace it. Today the agent captures the spec only at session start. It also captures the user prompt, which the transcript already holds. With this change, the agent does not capture the user's request prompt, because the transcript holds it. A short reminder at each user turn tells the agent to capture a new spec or image from the user. It also tells the agent to capture an approved plan, and a changed spec again. The limit on spec files for each session goes from 10 to 25. ## Problem - The agent captures the user prompt as a spec of kind `text`. The prompt is the first message of the transcript, so the spec material adds no information. The spec list then shows a duplicate as if it were external context. @@ -19,11 +19,11 @@ This spec changes the spec capture of [Spec 002](002-session-spec-capture.md). I - Goal: the spec materials of a session do not hold the user's request prompt. - Goal: the evidence holds each spec or image that the user gives after the start, and each plan that the user approves. It holds each changed spec with its content at push time. - Goal: the reminder is short and narrow, so that it does not overload the session. -- Goal: the agent still decides what a spec is, as Spec 002 decided (D-001 of Spec 002). +- Goal: the agent still decides what a spec is, as Spec issue-3495 decided (D-001 of Spec issue-3495). - Non-goal: a list of known spec locations, or rules in the CLI that decide if a file is a spec. - Non-goal: a new attestation when only the specs changed. A push records new specs only with a new AI-assisted commit, as today. -- Non-goal: a spec for a push after the session ends. Spec 002 accepted this loss, and this spec keeps it. -- Non-goal: changes to the materials, the redaction, or the storage that Spec 002 defines. +- Non-goal: a spec for a push after the session ends. Spec issue-3495 accepted this loss, and this spec keeps it. +- Non-goal: changes to the materials, the redaction, or the storage that Spec issue-3495 defines. ## Requirements @@ -47,7 +47,7 @@ For a changed spec, the agent MUST overwrite its spec file with the current cont - Done when: the user approves a plan in the session. The push records that plan as a `text` spec. ### R-004: Higher file limit -The push MUST record at most 25 spec files for each session. When there are more, it MUST record a warning, as Spec 002 does today. The push MUST NOT drop a file that an earlier push of the session recorded, also when the agent overwrote that file later. New files fill the remaining places, oldest first. The order of files on disk changes when the agent overwrites a file, so it MUST NOT decide which files the push keeps. +The push MUST record at most 25 spec files for each session. When there are more, it MUST record a warning, as Spec issue-3495 does today. The push MUST NOT drop a file that an earlier push of the session recorded, also when the agent overwrote that file later. New files fill the remaining places, oldest first. The order of files on disk changes when the agent overwrites a file, so it MUST NOT decide which files the push keeps. - Done when: a session goes over 25 files after the agent overwrites its starting ticket. The push still records the starting ticket. ## Constraints @@ -58,13 +58,13 @@ The push MUST record at most 25 spec files for each session. When there are more ## Proposal The user does nothing new. -At session start, the trace hook gives the full capture instruction, as in Spec 002. The instruction no longer lists "a written prompt" as a source. It tells the agent that the transcript already holds the conversation, so a prompt is not a spec. Kind `text` stays for a plan that the user approved in the session and for spec text that came from outside the conversation. +At session start, the trace hook gives the full capture instruction, as in Spec issue-3495. The instruction no longer lists "a written prompt" as a source. It tells the agent that the transcript already holds the conversation, so a prompt is not a spec. Kind `text` stays for a plan that the user approved in the session and for spec text that came from outside the conversation. At each user prompt, the trace hook adds a short reminder to the agent context. The reminder names the session folder and covers four cases. When the user pastes or gives a new spec, copy it. When the user gives an image file or URL, copy it. When the user approves a plan, write it as kind `text`. When a spec changes, copy it again. The reminder says nothing else. A spec that the session writes, for example a design note in a local notes folder, is a spec that changes. Its local path is the source address. The push records the content on disk at push time, so the final version of a plan replaces its drafts. The reminder replaces the old rule that gave the session-start instruction only while the folder was empty. A resumed session gets the reminder at its first user prompt, so it does not need the full instruction again. -The push keeps the rules of Spec 002, with a limit of 25 files instead of 10. Over the limit, it never drops a file that an earlier push of the session recorded. A push with no new AI-assisted commits still sends no attestation. The next AI-assisted commit records a spec that the agent added after the last push. The session-end hook still deletes the folder. +The push keeps the rules of Spec issue-3495, with a limit of 25 files instead of 10. Over the limit, it never drops a file that an earlier push of the session recorded. A push with no new AI-assisted commits still sends no attestation. The next AI-assisted commit records a spec that the agent added after the last push. The session-end hook still deletes the folder. Each agent receives the reminder through its own channel: @@ -95,7 +95,7 @@ sequenceDiagram end User->>CLI: git push CLI->>Folder: Read up to 25 spec files, earlier recorded files first - CLI->>CLI: Redact, upload, reference (as in Spec 002) + CLI->>CLI: Redact, upload, reference (as in Spec issue-3495) ``` ## Decision Record @@ -103,14 +103,14 @@ sequenceDiagram | ID | Decision | Choice | Why (and what we rejected) | Source | |----|----------|--------|----------------------------|--------| | D-001 | Capture of a user prompt | Do not capture the user's request prompt. Capture a spec that the user pastes | The transcript is already part of the session evidence, so the spec material is a duplicate. Rejected: keep it and label it "prompt" in the user interface (more data and UI work for no new information). | drafting | -| D-002 | How the system finds specs after session start | A short reminder at each user prompt, with four cases: a new spec, a new image, an approved plan, a changed spec. The agent decides what a spec is | Simple, and it keeps D-001 of Spec 002. It covers resumed sessions. Four narrow cases keep the reminder short, so it does not overload the session. Rejected: a general rule to capture anything that looks like a spec (too much capture). Rejected: a list of known spec locations that a hook watches (a new configuration, and it misses specs at other paths). Rejected: the hook copies matching files itself (the CLI decides what a spec is, and captures noise). Rejected: a check at push time against the transcript (needs transcript analysis for each agent). Rejected: a reminder after each Markdown write (misses a spec that the agent only reads, and more hook logic). | drafting | +| D-002 | How the system finds specs after session start | A short reminder at each user prompt, with four cases: a new spec, a new image, an approved plan, a changed spec. The agent decides what a spec is | Simple, and it keeps D-001 of Spec issue-3495. It covers resumed sessions. Four narrow cases keep the reminder short, so it does not overload the session. Rejected: a general rule to capture anything that looks like a spec (too much capture). Rejected: a list of known spec locations that a hook watches (a new configuration, and it misses specs at other paths). Rejected: the hook copies matching files itself (the CLI decides what a spec is, and captures noise). Rejected: a check at push time against the transcript (needs transcript analysis for each agent). Rejected: a reminder after each Markdown write (misses a spec that the agent only reads, and more hook logic). | drafting | | D-003 | A spec added after the last push, with no new AI-assisted commit | Record it with the next AI-assisted commit, as today | An attestation with no new commit is a duplicate of the session. Rejected: push a new attestation when the set of spec digests changed. | drafting | -| D-004 | A push after the session ends | No change: the session-end hook deletes the folder, and that push holds no spec | Accepted in Spec 002. Rejected: keep the folder until the next push, with an age limit (state to track and clean for a rare case). | drafting | +| D-004 | A push after the session ends | No change: the session-end hook deletes the folder, and that push holds no spec | Accepted in Spec issue-3495. Rejected: keep the folder until the next push, with an age limit (state to track and clean for a rare case). | drafting | | D-005 | Spec file limit | Raise from 10 to 25. Never drop a file that an earlier push recorded. New files fill the remaining places, oldest first | The reminder makes more spec files likely in a long session. The oldest files are the sources the session started from. An overwrite changes the modification time of a file, so an order by modification time can drop an edited start ticket. Rejected: keep the newest files (the start ticket can drop). Rejected: keep the oldest files by modification time only (an overwritten file moves to the end). | [PR comment](https://github.com/chainloop-dev/chainloop/pull/3516#discussion_r4182950724) | -| D-006 | Relation to Spec 002 | This spec changes Spec 002 and does not supersede it | Most of the capture design does not change. | drafting | +| D-006 | Relation to Spec issue-3495 | This spec changes Spec issue-3495 and does not supersede it | Most of the capture design does not change. | drafting | | D-007 | Control of overcapture from the reminder | Measure the number of spec files for each session after release. Make the reminder narrower if the number grows | The four cases are already narrow. Data from real sessions shows if more limits are necessary. | drafting | | D-008 | Cursor | The session-start instruction only, until Cursor documents a channel that adds context at prompt submit | No channel to use today. | drafting | -| D-009 | Pasted images | Do not capture a pasted image. Record it as a known limitation | The agent cannot copy the bytes of a pasted image into the folder. A description that the agent writes is not the image, so it adds little value. Rejected: a description of kind `image` (D-010 of Spec 002). This spec changes that decision. | [PR comment](https://github.com/chainloop-dev/chainloop/pull/3516#discussion_r4183303763) | +| D-009 | Pasted images | Do not capture a pasted image. Record it as a known limitation | The agent cannot copy the bytes of a pasted image into the folder. A description that the agent writes is not the image, so it adds little value. Rejected: a description of kind `image` (D-010 of Spec issue-3495). This spec changes that decision. | [PR comment](https://github.com/chainloop-dev/chainloop/pull/3516#discussion_r4183303763) | ## Open Questions None. @@ -119,7 +119,7 @@ None. | Risk | Mitigation | |------|------------| -| The agent ignores the reminder, as it ignored the instruction to add a file when the task changed. | The reminder comes at each turn, near the work, and not only at session start. The capture rate of Spec 002 (R-010) stays measurable. | +| The agent ignores the reminder, as it ignored the instruction to add a file when the task changed. | The reminder comes at each turn, near the work, and not only at session start. The capture rate of Spec issue-3495 (R-010) stays measurable. | | A spec written and pushed in the same turn is not captured, because the next reminder comes later. | The session-start instruction still says to update the folder when the task changes. The next push with a new commit records it. | | The reminder adds tokens to each turn. | Keep it to a few lines. The full instruction stays at session start only. | | Known limitation: the evidence does not hold a pasted image as a spec (D-009). | The transcript still holds the conversation. A later version can take the image bytes from the transcript at push time. | \ No newline at end of file diff --git a/docs/specs/005-pi-trace-provider.md b/docs/specs/issue-3520-pi-trace-provider.md similarity index 96% rename from docs/specs/005-pi-trace-provider.md rename to docs/specs/issue-3520-pi-trace-provider.md index 7af3cde10..a8f560039 100644 --- a/docs/specs/005-pi-trace-provider.md +++ b/docs/specs/issue-3520-pi-trace-provider.md @@ -4,7 +4,7 @@ ticket: https://github.com/chainloop-dev/chainloop/issues/3520 prd: --- -# Spec 005: Pi coding agent support in Chainloop Trace +# Spec issue-3520: Pi coding agent support in Chainloop Trace ## Summary @@ -98,7 +98,7 @@ Invalid negative, non-finite, or overflowing usage values MUST be ignored with a The Pi extension MUST deliver the full session-start instruction to the model once for each persisted Pi session ID. On the first `before_agent_start`, it MUST return a hidden persistent `custom_message` whose marker includes the current session-header ID. On reload or resume, it MUST scan all session entries for a marker matching the current ID and MUST keep an in-memory guard against duplicate full-instruction injection. A fork or clone has a new header ID, so a marker copied from its parent MUST NOT suppress the new session's instruction. -As required by Spec 003, every `before_agent_start` MUST also add the short per-turn spec-capture reminder, including after resume and after the full instruction has already been recorded. The first turn MAY combine the full instruction and reminder into one hidden message. +As required by Spec issue-3515, every `before_agent_start` MUST also add the short per-turn spec-capture reminder, including after resume and after the full instruction has already been recorded. The first turn MAY combine the full instruction and reminder into one hidden message. When `ctx.hasUI` is true, the extension MUST show the existing Trace banner and all pending post-push session links through Pi's UI. Without UI, it MUST write all pending post-push session links to stderr, never stdout. JSON mode MUST remain valid JSONL, and neither JSON nor print mode may receive extension diagnostics on stdout. @@ -162,7 +162,7 @@ sequenceDiagram **Transcript parsing.** The parser reads the v3 header and tree entries as typed structures while retaining raw valid unknown entries. The last persisted entry is the terminal leaf because each `/tree` event immediately appends a marker to the selected branch. Following parents excludes abandoned branches. Aggregation uses selected assistant and user messages; malformed selected structure skips only that session, never the push. -**User and model messages.** Session-start returns one JSON response. Before the first agent turn, the extension returns the full instruction and Spec 003 reminder as hidden model context; later turns receive only the reminder. The extension shows the start banner and all pending post-push links through Pi UI when available, and sends the links to stderr in headless modes. +**User and model messages.** Session-start returns one JSON response. Before the first agent turn, the extension returns the full instruction and Spec issue-3515 reminder as hidden model context; later turns receive only the reminder. The extension shows the start banner and all pending post-push links through Pi UI when available, and sends the links to stderr in headless modes. ## Decision Record @@ -175,7 +175,7 @@ sequenceDiagram | D-005 | Attribution scope | Built-in `write`, `edit`, and `bash` | They have documented payloads and map to existing snapshot paths. Custom tools have no common mutation contract. | Pi extension docs | | D-006 | Transcript source | Copied Pi JSONL v3 | It is authoritative for provider, model, usage, tool, and conversation data. Rejected: a duplicate extension transcript. | Pi session format | | D-007 | Branch selection | Append a plain custom marker on `session_tree`, then parse from the last persisted entry | The marker makes `/tree` durable before later work and naturally becomes an ancestor of later entries. Rejected: treating the marker's parent as the terminal leaf, which drops later work; and a new Trace-store active-leaf protocol. | Pi session manager | -| D-008 | Model communication | Full hidden instruction once per session ID, short Spec 003 reminder every turn | The marker avoids duplicate full instructions across reload while forks receive their own. The per-turn reminder preserves the behavior required for all agents with a prompt-submit channel. | Pi extension docs; Spec 003 | +| D-008 | Model communication | Full hidden instruction once per session ID, short Spec issue-3515 reminder every turn | The marker avoids duplicate full instructions across reload while forks receive their own. The per-turn reminder preserves the behavior required for all agents with a prompt-submit channel. | Pi extension docs; Spec issue-3515 | | D-009 | Headless behavior | Hooks run; UI-only banners are omitted and pending links use stderr | JSON stdout stays valid JSONL, print stdout receives no extension diagnostics, and links still reach the user. | Pi mode docs | | D-010 | Evidence schema | Existing AI coding-session material | Provider differences fit the existing model. | Chainloop provider architecture | | D-011 | Sessions whose hooks never ran | Do not discover them at pre-push; add only temporary interface stubs if #3536 has not removed them | Pre-push starts from recorded sessions and has no provider identity for an untracked session. Production does not call the current discovery methods through `Provider`. Rejected: implementing unused discovery logic or scanning every provider and guessing which session belongs to a push. | Chainloop hook architecture; #3536 | diff --git a/docs/specs/004-spec-source-role.md b/docs/specs/issue-3531-spec-source-role.md similarity index 89% rename from docs/specs/004-spec-source-role.md rename to docs/specs/issue-3531-spec-source-role.md index c37e01cea..38e5648ac 100644 --- a/docs/specs/004-spec-source-role.md +++ b/docs/specs/issue-3531-spec-source-role.md @@ -4,10 +4,10 @@ ticket: https://github.com/chainloop-dev/chainloop/issues/3531 prd: --- -# Spec 004: Role, title, and description of each spec source +# Spec issue-3531: Role, title, and description of each spec source ## Summary -This spec changes the spec capture of [Spec 002](002-session-spec-capture.md) and [Spec 003](003-spec-capture-during-session.md). It does not replace them. Today each spec source has a kind: ticket, document, image, or text. The kind tells the format of a source, but not its purpose. A source also has no name that a person can read. With this change, the agent can also record a role, a title, and a description for each source. The role is `task`, `spec`, `plan`, or `reference`. The title is a short name, for example the title of a ticket. The description says in one or two sentences what the source holds. The CLI stores these values in the session material and in the annotations of the spec material. A tool that shows the sources can then group them by purpose, label them by title, and explain each one. +This spec changes the spec capture of [Spec issue-3495](issue-3495-session-spec-capture.md) and [Spec issue-3515](issue-3515-spec-capture-during-session.md). It does not replace them. Today each spec source has a kind: ticket, document, image, or text. The kind tells the format of a source, but not its purpose. A source also has no name that a person can read. With this change, the agent can also record a role, a title, and a description for each source. The role is `task`, `spec`, `plan`, or `reference`. The title is a short name, for example the title of a ticket. The description says in one or two sentences what the source holds. The CLI stores these values in the session material and in the annotations of the spec material. A tool that shows the sources can then group them by purpose, label them by title, and explain each one. ## Problem - A reader of the evidence cannot tell a spec from a background document. Both have the kind `document`. @@ -23,9 +23,9 @@ This spec changes the spec capture of [Spec 002](002-session-spec-capture.md) an - Goal: the agent can give these values to a binary file too. - Goal: sessions without these values stay valid, and earlier consumers keep working. - Non-goal: a change to the kinds, or to how the CLI finds the kind. -- Non-goal: rules in the CLI that guess a role, a title, or a description. The agent decides them, as it decides what a spec is (D-001 of Spec 002). +- Non-goal: rules in the CLI that guess a role, a title, or a description. The agent decides them, as it decides what a spec is (D-001 of Spec issue-3495). - Non-goal: a source address or other metadata for binary files. Only the role, the title, and the description are new. -- Non-goal: a change to the reminder at each user turn of Spec 003. +- Non-goal: a change to the reminder at each user turn of Spec issue-3515. ## Requirements @@ -58,7 +58,7 @@ The header of a text spec file, and the companion file of a binary file, MAY hol - Done when: a ticket file with `title: "ENG-1234: Add an export button"` pushes a spec entry and a material annotation with that title. ### R-008: Title limits -The system MUST cut a title that is longer than 120 characters, and keep the first 120. Each title MUST pass the secret redaction of Spec 002 before it goes into any evidence field. For a text file, the system MUST read the title from the redacted file, as it reads the source address. For a binary file, the system MUST redact the title of the companion file. A bad title MUST NOT stop the push. +The system MUST cut a title that is longer than 120 characters, and keep the first 120. Each title MUST pass the secret redaction of Spec issue-3495 before it goes into any evidence field. For a text file, the system MUST read the title from the redacted file, as it reads the source address. For a binary file, the system MUST redact the title of the companion file. A bad title MUST NOT stop the push. ### R-009: Description The header of a text spec file, and the companion file of a binary file, MAY hold a `description` field. It says in one or two sentences what the source holds, or why it is in the session. When a source has a description, the system MUST record it in the spec entry of the session material. It MUST also record it in a `chainloop.spec.description` annotation on the spec material. When the description is missing or empty, the system MUST leave out both. The system MUST NOT make a description from the content. The rules of R-008 apply, with a limit of 300 characters. @@ -138,7 +138,7 @@ A tool that shows the sources groups them by role when a source has one, and lab | D-002 | Role values | `task`, `spec`, `plan`, `reference` | Four values cover the purposes that a reviewer looks for: what to do, what to build, how, and supporting material. Rejected: only `spec`, with no role for all other sources (a reader cannot tell a task from a reference). | drafting | | D-003 | Role of a binary file | A companion header file that the agent writes | The agent decides the role for every source, also for an image. Rejected: the CLI sets `reference` for each image (a guess, and a mockup can be the spec). Rejected: no role for binary files. | drafting | | D-004 | Missing or unknown role | No role in the evidence | The evidence holds only what the agent stated. Consumers can apply their own rule. Rejected: a default role from the kind (a guess looks like a fact in the evidence). | drafting | -| D-005 | Instruction strength | SHOULD, in the session-start instruction only | A role is useful but not necessary, and the reminder at each turn must stay short (Spec 003). Rejected: MUST, and the roles in the reminder at each turn (more tokens on each turn). | drafting | +| D-005 | Instruction strength | SHOULD, in the session-start instruction only | A role is useful but not necessary, and the reminder at each turn must stay short (Spec issue-3515). Rejected: MUST, and the roles in the reminder at each turn (more tokens on each turn). | drafting | | D-006 | Name of the companion file | The binary file name plus `.meta.yaml`, for example `export-mockup.png.meta.yaml` | The suffix tells that the file holds metadata, not a spec. Rejected: the binary file name plus `.md`, with a header and an empty body (a reader can take it for an empty spec). | drafting | | D-007 | Companion file with no binary file | The CLI ignores it, with no warning | The file holds no spec content, so the push loses nothing. Rejected: a warning in the session material (noise for a case with no loss). | drafting | | D-008 | Name of a source | An optional title that the agent writes, next to the role | The agent knows the title of the source when it writes the file. The format already changes for the role, so a second field costs little. A tool can label a source from the session material alone. Rejected: the material name only (a short lower-case file stem). Rejected: a title that the CLI takes from the first heading (a guess that looks like a fact in the evidence). This changes the outcome of [#3528](https://github.com/chainloop-dev/chainloop/issues/3528), which closed a title field before the format had other changes. | drafting |