Design-to-Spec Intake — Distiller Assessment and Recommended Design¶
| Status | Proposed |
|---|
Status: Recommendation for decision · Reviewed: 2026-08-25
Executive decision¶
Do not finish or deploy the current autonomous distiller as designed. Preserve it as a useful spike, keep its deterministic/model boundary and human merge gate, and reframe the product as a human-invoked intake compiler.
The compiler should start from an explicit Linear intake issue and an exact Claude Design reference, use an optional prototype revision as supporting evidence, draft an applicable change against known feature files, and propose how to reconcile existing Linear work. A person must review the result. Only a merged spec change can authorize downstream implementation work.
The recommended operating loop is:
flowchart LR
A[Claude Design reference] --> C[Linear intake issue]
B[Optional prototype revision] --> C
C --> D[Human-invoked intake compiler]
D --> E[Draft intake packet]
E --> F{Human review}
F -->|needs intent| G[Conor decision]
G --> D
F -->|approved| H[Spec pull request]
H --> I{Merge gate}
I -->|merged| J[Update or create Linear build work]
J --> K[Build and QA]
K --> L[Deployed evidence]
L -. optional later .-> D
This is intentionally smaller than the two-agent system. It solves the known handoff problem first and postpones scheduling, automatic writes, and behavioral divergence testing until real usage proves which of those are necessary.
The decision in plain language¶
The current spike is not overengineered in code volume. It is approximately 250 lines and its internal separation is sensible. It is over-specified as a future service and under-specified at the domain boundaries that determine whether it can produce useful work.
The implemented slice concentrates on model isolation, JSON validation, and a future scheduled pipeline. The missing slices are the ones that carry the product value:
- the active Claude Design artifact and its revision;
- the existing Linear intake issue and related tickets;
- a stable mapping to the current per-feature spec structure;
- an applicable patch rather than unconstrained prose;
- duplicate-safe Linear reconciliation;
- evidence about what is actually deployed;
- explicit sign-off, ownership, and scope-lock state;
- repeatable evaluation on real Pinley changes.
The result can currently demonstrate that a model returns schema-valid JSON. It cannot yet demonstrate that a Claude Design change becomes the correct spec diff and the correct Linear action.
Scope of this recommendation¶
This document covers the handoff from product exploration through accepted requirements and ready engineering work:
- capture a change from Claude Design or the prototype;
- connect it to the Linear intake conversation;
- map it to existing feature definitions;
- draft the proposed spec change;
- identify existing Linear work before proposing anything new;
- collect the necessary human decisions;
- merge the accepted requirement;
- update or create downstream Linear implementation work.
It does not design the delivery-side implementation, perform QA, compare GitLab source, or permit an agent to approve its own work.
Material reviewed¶
The assessment covered:
- the four intake design artifacts in
design-process/; - the complete
distiller/TypeScript spike, README, handoff, package configuration, and Git history; - the spec's feature catalog, roadmap, launch-readiness process, master feature inventory, walkthrough conventions, and current per-feature frontmatter;
- the locally available
Pinley-Mechanical/AI-prototypecheckout, including its application, detailed MkDocs corpus, Linear-ready backlog, and Claude documentation-maintenance hook; - executable checks of the distiller and documentation repositories.
The review did not query live Linear, drive the deployed application, inspect GitLab source, or access the live Claude Design canvas. Those are not available through the current distiller and must not be silently inferred from local documentation.
What is healthy in the current spike¶
The following choices should survive the redesign:
- Deterministic mechanics around bounded model judgment. Git collection, patch validation, branch handling, and API writes belong in code. Semantic mapping and prose drafting are appropriate model tasks.
- A read-only model step. Restricting the model to read/search tools is a useful containment layer.
- Schema validation. Treating model output as untrusted data and validating it before use is the correct pattern.
- No automatic merge. A person decides whether proposed requirements become product truth.
- A reviewable pull request. The PR is a good audit artifact and a natural place to discuss a proposed change.
- Revision-bounded evidence. Explicit source revisions are better than asking a model to interpret an unbounded repository snapshot.
These are good implementation properties. They do not, by themselves, establish a viable intake process.
Evidence and findings¶
Summary¶
| Severity | Finding | Practical consequence |
|---|---|---|
| Blocker | The current program does not create a spec PR or touch Linear. | It is a judgment demo, not an intake pipeline. |
| Blocker | A clean first run executes git diff HEAD. |
It reports no changes instead of establishing an initial baseline. |
| Blocker | Claude Design and Linear intake are not inputs. | The model lacks the intent and conversation it is supposed to preserve. |
| High | Deployment state is not provided, although the schema asks for already_shipped. |
The model must guess or over-trust stale docs. |
| High | The target contract assumes a capability index and per-capability edit string that do not match the current spec. | The proposed edit cannot be safely located or applied. |
| High | Requirement relationship and implementation state are collapsed into one classification. | Valid states cannot be represented without lying. |
| High | There is no Linear lookup or reconciliation step. | Automatic creation would produce duplicates and lose existing context. |
| High | The written process disagrees about where intake starts and which artifact is authoritative. | Automation would encode an unresolved policy decision. |
| Medium | The schema validates shape but few semantic invariants. | Invalid mappings can be structurally valid. |
| Medium | Scheduled runs are not idempotent while a PR is open. | The same source range could generate repeated drafts. |
| Medium | The only live smoke test is synthetic and non-repeatable. | There is no evidence of useful performance on Pinley intake. |
| Medium | Raw repository diffs are treated as trusted model instructions. | Prompt injection, generated noise, and excessive context can influence proposed writes. |
1. The current implementation is a scaffold, not an end-to-end path¶
The working code can:
- read a local Git revision;
- read a checkpoint file if one exists;
- produce a Git diff when given a valid earlier revision;
- invoke one read-only Claude Agent SDK session;
- parse and structurally validate returned JSON;
- print the proposed judgment.
It cannot:
- read the active Claude Design source;
- read an intake issue or search existing Linear work;
- build the expected feature catalog from the current spec;
- apply a spec edit;
- create, update, or push a branch;
- open a pull request;
- create or update Linear issues;
- run on a schedule;
- advance a checkpoint after merge;
- supply a divergence report;
- update an existing open intake draft.
The README and handoff acknowledge most of these items as stubs, but the system diagrams and language describe them as a pipeline. Planning should use the implemented boundary, not the future diagram.
2. The first-run Git range is incorrect¶
When no checkpoint exists, the spike uses HEAD as the argument to git diff. In a clean checkout,
git diff HEAD compares the worktree to HEAD; it does not emit the repository's committed history.
This was reproduced against the locally available prototype. With no checkpoint file, the command reported:
No changes since the checkpoint. Nothing to distill.
The correct behavior is not to guess an implicit beginning. An intake should require an explicit baseline revision. If a future watcher is introduced, its first-run baseline must be deliberately seeded or use an explicitly approved import range.
3. The source is not Claude Design¶
The current program accepts only DISTILLER_PROTOTYPE_REPO and diffs that repository's code. The
canonical feature inventory refers extensively to Cara-AI-design/*.dc.html surfaces, but those
artifacts are not present in the local prototype checkout and no design connector exists in the
spike.
The intake designs themselves state that /design-sync carries design-system components but does not
carry behavior, screen states, or reasons. Therefore a prototype code diff cannot be treated as a
lossless proxy for Claude Design intent.
The locally available prototype also contains its own detailed workflows, epics, architecture pages, and a Claude stop hook that reminds authors to update those documents. Those structured docs may be useful evidence, but the current spike sends an unfiltered repository diff and does not distinguish behavioral documentation from JSX churn, generated data, style changes, or assets.
The proper intake event must name the exact design artifact and revision. Prototype code should be supporting evidence, not the sole trigger and not the sole representation of intent.
4. The target model has already evolved past the spike¶
At the beginning of the intake work, the spec used a broad 34-row capability registry while the master inventory contained 111 feature rows. The current repository has since been expanded into roughly 150 per-feature Markdown files carrying fields such as:
statusandstage;confidenceandestimate;scope_lockedanddesign_lockedwhere known;due;- one or more Linear IDs;
- a Linear epic;
- module and reference information;
- Conor's comments and open questions.
This is a substantially better target for distillation. It also invalidates the spike's assumption
that a generated capabilities.index.txt and a free-form cap_id are the main mapping contract.
The intake compiler should map directly to stable feature identities and exact file paths. The
repository should add an immutable feature_id frontmatter field, or explicitly declare that the
relative feature path is immutable. Titles, module grouping, and Linear tickets are not safe primary
keys: titles change, features move, and Linear relationships can be one-to-many or many-to-one.
5. spec_edit cannot be applied safely¶
The model currently returns one unconstrained string named spec_edit. It does not identify:
- the target file;
- the target heading or frontmatter field;
- the spec base SHA;
- whether the file already exists;
- whether the operation adds, modifies, removes, or splits a feature;
- whether multiple feature files must change;
- the actual patch preconditions.
The planned PR writer cannot deterministically translate that string into a correct repository
change. The replacement contract should return a unified diff plus explicit target paths and a base
revision. Code must run git apply --check, restrict writes to allowed documentation paths, and build
the rendered site before a branch can be pushed.
6. The classification mixes independent questions¶
promote, regress, and already_shipped are not mutually exclusive answers to one question.
A design change might modify an existing requirement while some of it is already shipped. A deployed build might regress an unchanged requirement. A prototype might demonstrate behavior that is already covered by the spec but absent from production. A visual-only change may require no behavior edit at all.
The replacement must separate three axes:
| Axis | Allowed values |
|---|---|
| Design versus accepted spec | new, modifies, removes, conflicts, already_covered, visual_only, unclear |
| Observed implementation state | unknown, shipped, partial, absent, regressed |
| Linear action | update_existing, create_child, create_new, close_or_supersede, none, needs_reconciliation |
Implementation state must default to unknown. It may change only when the packet includes current,
traceable deployment evidence.
7. The promised divergence input does not exist¶
The design says a second agent compares prototype, deployed behavior, and spec, then feeds the result
to the distiller. The current judge() function receives only a prototype diff and a capability-index
string. No deployed evidence or divergence report is available.
As a result, the model is asked to label changes already_shipped without a factual basis. This field
should be removed from the first release. A later behavioral evidence provider may populate the
implementation-state axis, but only after the team has a repeatable way to exercise the relevant
prototype and deployed flow.
The earlier design correctly identified behavioral comparison as the hardest and most judgment-heavy node. That is a reason to defer it behind evidence, not to let the first agent silently approximate it.
8. Linear is represented as prose, not reconciled work¶
The spike emits arrays of draft titles and bodies. It does not read Linear, so it cannot know whether:
- a relevant issue already exists;
- an issue is done, canceled, superseded, duplicated, or part of a larger epic;
- the proposed change belongs in the intake issue, an existing implementation issue, or a new child;
- the team's current label, state, cycle, owner, dependency, and project conventions are satisfied;
- a referenced historical issue should be reopened or left as evidence;
- several feature changes should remain one slice or be split.
This is especially risky because the spec explicitly tells reviewers to reconcile against existing PINs instead of recreating work. Linear search is therefore an input requirement, not a future output enhancement.
The first release should be read-only against Linear and produce a reconciliation plan. Write access should be added only after merge, and only through deterministic API operations tied to an approved packet.
9. The repositories disagree about “single source of truth”¶
The launch-readiness intake page says:
- the Feature Matrix is the source of truth;
- intake begins as a Linear issue;
- Cloud Design is a visual reference;
- the prototype is historical;
- only locked work enters a cycle.
The later intake diagrams say:
- the Markdown spec is the source of truth;
- prototype changes first become a spec pull request;
- Linear issues are generated after the spec merge.
The current feature index says per-feature pages are the source for scope and status. The design artifacts also disagree about whether Vania or Ivan is the final merge approver.
This should not be solved by choosing one system as the truth for every kind of information. Declare authority by field:
| Information | Authority |
|---|---|
| Raw request, discussion, and intake state | Linear intake issue |
| Visual direction and screen reference | Versioned Claude Design artifact |
| Accepted product behavior and scope | Merged per-feature spec page |
| Scope/design sign-off | Explicit fields on the spec page, backed by the intake decision |
| Implementation workflow, assignee, cycle, and delivery state | Linear implementation issue |
| Current behavior | Deployed application evidence |
| Roadmap summaries and module totals | Derived views, not independently edited truth |
With this split, Linear can be both an input and an output without forming a circular authority: capture enters through an intake issue; accepted requirements live in the spec; implementation work returns to Linear after approval.
10. Shape validation is not semantic validation¶
Zod currently confirms that fields are strings, arrays, or known enum members. It does not ensure that:
- the feature identifier exists;
- the target file matches the feature identifier;
- a new feature uses a new valid path;
- low confidence or a regression always requires human review;
needs_humanis consistent with questions and classifications;- acceptance criteria are non-empty and observable;
- a claimed spec quotation exists;
- a proposed Linear issue is not a duplicate;
- a claimed shipped state has deployed evidence;
- a patch applies to the recorded spec SHA;
- a design or scope lock was actually approved by a person.
The redesigned schema should use cross-field validation and deterministic repository/API checks. Schema validation remains necessary, but it is only the first layer.
11. The checkpoint design is not ready for concurrency¶
The proposed global distill-state.json advances only when a PR merges. That sounds safe, but a
scheduled run before the existing PR merges sees the same baseline again and can create a duplicate
draft. Two unrelated intakes also should not compete for one repository-wide prototype checkpoint.
The initial product should avoid a global watcher entirely. Each explicit intake packet should be keyed by its intake issue and exact revisions. If scheduling is added later, it should query for unprocessed Linear intake issues and upsert their existing branch/PR, not treat every prototype commit as committed product intent.
12. Read-only tools do not eliminate write risk¶
The model cannot directly edit files, which is good. Its output is nevertheless intended to be applied by a privileged deterministic process. Text in a prototype diff, design note, or Linear issue can therefore influence a proposed write through prompt injection or accidental instruction-like content.
Controls should include:
- treat all source material as quoted evidence, never as agent instructions;
- separate system instructions from collected content;
- cap diff size and exclude lockfiles, generated files, binary metadata, vendored code, and assets;
- allowlist writable spec paths;
- validate feature IDs and target paths deterministically;
- run patch and documentation-build checks in an isolated worktree;
- never expose GitHub or Linear write tokens to the model;
- require human review before push at first, and always before merge;
- record source revisions and evidence in the PR.
13. There is no useful evaluation suite yet¶
TypeScript typechecking passes. The spec builds. The live smoke test reportedly produced valid JSON for a synthetic batch-approval example. There are no test files in the distiller, no recorded model fixtures, no Pinley golden cases, and no measurement of reviewer effort or duplicate prevention.
The relevant success condition is not “the model returned JSON.” It is “a reviewer received the right mapping, an applicable spec patch, and a duplicate-safe Linear plan faster than doing the work manually.”
Recommended product definition¶
Name¶
Use intake compiler for the first release. “Watcher” or “autonomous distiller” implies that every source change should become product work. The compiler starts only from a deliberate intake event.
Purpose¶
Given one explicit Linear intake issue, its versioned design references, optional prototype evidence, and the current spec, draft a complete and reviewable proposal for:
- the accepted-spec change;
- the decisions still required;
- the relationship to existing features;
- the action to take on existing or new Linear implementation work.
Non-goals for the first release¶
- continuously watching every prototype commit;
- interpreting unversioned design state;
- determining deployed behavior without evidence;
- driving the prototype or deployed app;
- visual screenshot diffing;
- automatic scope or design sign-off;
- automatically merging a spec PR;
- automatically assigning, prioritizing, estimating, or scheduling engineering work;
- creating Linear issues before duplicate reconciliation and spec approval;
- providing a general-purpose RFC or project-management platform.
Canonical lifecycle¶
1. Capture¶
Create one Linear issue with the intake label. It is the durable conversation and must include:
- a one-sentence request;
- requester;
- exact Claude Design page/reference and revision if applicable;
- screenshots or exported evidence needed to understand the state;
- optional prototype repository and revision range;
- known existing Linear issue links;
- known feature/module;
- the reason the change matters now.
No estimate or cycle is required at capture.
2. Scope¶
The intake steward invokes the compiler for that issue. The compiler collects read-only evidence, searches the current feature catalog and Linear, and drafts an intake packet. It may map one request to multiple features or multiple requested changes to one implementation slice.
The compiler must not infer approval from a design's existence.
3. Decide and lock¶
A person reviews the packet. Conor answers the smallest necessary intent question. The named product approver confirms:
- accepted behavior;
- priority and roadmap placement;
- scope boundary;
- design revision;
- whether the work should be split;
- whether existing Linear work is reused.
scope_locked and design_locked are human-controlled fields. An agent may propose them but may not
set them to true.
4. Merge the spec¶
The approved patch lands in a spec PR. The merge is the event that makes the requirement accepted. The PR records:
- the Linear intake ID;
- design references and revisions;
- prototype revision range if used;
- mapped feature IDs and paths;
- unresolved questions, which must be empty or explicitly deferred;
- the planned Linear reconciliation;
- validation results.
5. Reconcile Linear¶
After merge, deterministic code updates the intake issue with the spec PR and merge SHA, then performs the approved actions:
- update an existing implementation issue;
- create children under the existing intake/epic;
- create a new issue only when reconciliation found no suitable existing work;
- close or mark superseded work only when explicitly approved;
- perform no action when the spec change is informational or visual-only.
Every created or updated issue links to the exact merged spec page and design revision.
6. Build and verify¶
Engineering builds from the merged requirement and linked design revision. QA verifies against the spec's observable acceptance criteria. Delivery state lives in Linear; actual behavior is established by deployed evidence, not inferred from ticket status.
Roles and permissions¶
| Role | Responsibility | Required access |
|---|---|---|
| Requester / designer | Supplies the intent and versioned design reference. | Linear intake; design source |
| Intake steward | Invokes the compiler, checks evidence, and edits the draft. | Read design/prototype/spec/Linear; open spec PR |
| Client decision-maker | Answers intent questions and signs off where required. | Intake queue and review artifact |
| Product approver | Confirms scope/priority and approves the spec merge. | Spec PR approval; Linear intake |
| Engineering owner | Confirms feasibility, dependencies, and slicing. | Spec and relevant Linear work |
| QA owner | Confirms acceptance criteria are observable and complete. | Spec, test environment, Linear |
| Automation | Collects, drafts, validates, and later applies approved deterministic actions. | Read by default; narrowly scoped write tokens only after approval |
The existing design artifacts assign final approval to different people. That role must be settled by policy before automation routes reviews or treats a merge as authorized.
Input contract¶
The first CLI should be explicit:
/distill PIN-812 --design "Cara Estimating Sheet.dc.html@revision-42" \
--prototype-from <sha> --prototype-to <sha>
Required inputs:
- Linear intake ID;
- exact design artifact and revision, or an explicit
no-designreason; - current spec base SHA;
- operator identity.
Optional inputs:
- prototype repository and explicit
from..torevisions; - screenshots or exports;
- suspected feature IDs/paths;
- deployed evidence references;
- a requested batch identifier when several intake issues are intentionally grouped.
The command should fail closed when a required source is missing. It should never turn “latest” into an unrecorded moving input.
Draft packet contract¶
The exact JSON schema may evolve, but it must express at least the following information:
version: 1
packet_id: PIN-812@design-revision-42
spec_base_sha: <sha>
intake:
issue_id: PIN-812
title: <captured request>
requester: <person>
sources:
design:
artifact: Cara Estimating Sheet.dc.html
revision: revision-42
evidence: [<stable link or content hash>]
prototype:
repository: Pinley-Mechanical/AI-prototype
from_sha: <sha>
to_sha: <sha>
deployed:
state: unknown
evidence: []
feature_mappings:
- feature_id: feat-bid-estimating-sheet
spec_path: features/bids/bid-detail-estimate-estimating-sheet.md
confidence: medium
evidence: [<source locations>]
changes:
- relationship: modifies
current_requirement: <what the merged spec says>
proposed_requirement: <what the intake proposes>
reason: <why the change is requested>
acceptance:
- precondition: <starting state>
action: <user action>
observable_result: <one visible result>
patch: |
diff --git a/content/features/... b/content/features/...
...
linear_reconciliation:
searched: true
candidates: [PIN-47, PIN-197]
actions:
- action: update_existing
issue_id: PIN-47
reason: <why this is the same implementation slice>
decisions:
questions: [<only unresolved decisions>]
scope_locked: false
design_locked: false
requires_client: true
requires_engineering: true
risk:
needs_human: true
reasons: [medium mapping confidence, scope not locked]
Contract invariants¶
Validation must enforce:
- each existing
feature_idresolves to exactly one current spec path; - each patch target matches a mapped feature or an allowed derived index;
- each patch applies to
spec_base_shawithgit apply --check; - new feature paths are unique and remain within
content/features/; shipped,partial,absent, orregressedrequires current deployed evidence;- low confidence, a conflict, a removal, an open question, or an unlocked scope requires human review;
needs_humancannot be false when any triggering condition exists;- Linear create actions require a completed search and an explicit no-match result;
- acceptance criteria have a precondition, action, and one observable result;
- no agent-generated packet can set either lock to true;
- every source uses a stable revision, URL, or content hash;
- the same packet key is idempotent.
Deterministic versus model responsibilities¶
Deterministic code owns¶
- validating CLI inputs;
- retrieving the named Linear intake issue;
- searching existing Linear issues and relationships;
- resolving design and prototype revisions;
- filtering diffs and enforcing size limits;
- parsing the feature catalog and frontmatter;
- validating stable feature IDs and paths;
- checking schema invariants;
- checking and applying patches in an isolated worktree;
- building the documentation;
- naming/upserting the branch and PR;
- recording source revisions and validation results;
- applying only the approved post-merge Linear action plan;
- maintaining idempotency and audit logs.
The model owns¶
- separating behavioral change from visual or mechanical noise;
- mapping evidence to likely existing features;
- explaining conflicts and ambiguity;
- drafting requirement prose and observable acceptance criteria;
- proposing a patch;
- proposing issue slicing and Linear reconciliation candidates;
- asking concise intent questions.
People own¶
- deciding whether a design represents requested product intent;
- confirming the mapping when confidence is not high;
- approving scope, priority, estimate, and roadmap placement;
- confirming implementation slicing and dependencies;
- locking scope and design;
- approving and merging the spec;
- approving any Linear creation, closure, or supersession.
Spec patch rules¶
- Patch exact per-feature pages, not a generic capability prose field.
- Preserve current frontmatter and page structure.
- Update derived module indexes through deterministic generation where possible.
- Do not edit roadmap summaries independently when they can be derived from feature metadata.
- Include current behavior, proposed behavior, acceptance criteria, source references, and open decisions in the appropriate feature page.
- Keep historical Linear references when they remain useful evidence; distinguish them from active implementation work.
- Do not mark a feature built merely because an issue is Done.
- Do not mark scope or design locked without a recorded human decision.
- New features require a stable feature ID, module, owner or ownership gap, and explicit roadmap state.
- Visual-only changes may update a design reference without generating implementation acceptance criteria when no behavior changes.
Linear reconciliation rules¶
Before proposing a new issue, search by:
- current feature-page Linear IDs;
- intake issue relationships;
- feature ID and title aliases;
- route and module;
- relevant epic/project;
- close semantic title matches;
- canceled, duplicate, and completed historical work.
Prefer actions in this order:
- update the existing intake issue;
- update an existing active implementation issue;
- add a child to the existing intake or epic;
- create a new issue only with an explicit no-match result;
- perform no Linear action when the accepted change creates no build work.
New implementation work must include:
- the stable feature ID and exact spec link;
- the design artifact and revision;
- acceptance criteria copied or linked from the merged spec;
- dependencies and parent/epic relationship;
- the originating intake issue;
- the spec PR and merge SHA;
- no cycle or owner unless approved by the responsible person.
The adapter must use deterministic API calls. The model proposes actions but never receives a Linear write token.
Idempotency and state¶
The initial compiler does not need a global checkpoint. Its natural key is:
intake issue + design revision + prototype to-SHA + spec base SHA
Recommended behavior:
- branch:
intake/PIN-812; - PR title:
Intake PIN-812: <short title>; - repeat invocation with the same packet updates the existing branch/PR;
- a changed design revision creates a new packet revision and visibly supersedes the earlier draft;
- a merged packet cannot be silently regenerated against a new source revision;
- concurrent intakes may proceed independently unless they touch the same feature, in which case the second run must report the conflict;
- post-merge Linear writes store an operation key so retries cannot create duplicates.
If a watcher is eventually justified, maintain checkpoints per source stream and per open intake, not as one mutable file in the spec repository.
Failure behavior¶
Fail without writing when:
- the intake issue cannot be read;
- the design revision cannot be resolved;
- the prototype revision is missing or not an ancestor when one is supplied;
- the diff exceeds configured limits after filtering;
- the feature mapping is ambiguous and no reviewer has chosen a target;
- the patch does not apply to the recorded base SHA;
- documentation validation fails;
- Linear reconciliation was not performed for a proposed create action;
- an existing branch contains human edits that cannot be cleanly preserved;
- required approval or lock state is absent for a post-merge write.
A failure report should state what evidence was collected, the precise failed check, and the smallest human action needed to continue. It must not substitute a plausible model guess.
Security and trust boundaries¶
- Treat design content, prototype code, commit messages, spec prose, and Linear text as untrusted data.
- Keep model tools read-only and load no personal settings, skills, hooks, or MCP servers.
- Keep GitHub and Linear credentials outside the model process.
- Use narrow tokens: spec PR permission and approved Linear issue mutation only.
- Permit no GitLab source access from this intake tool.
- Use an isolated worktree for patch validation and documentation builds.
- Prevent path traversal and writes outside approved spec directories.
- Store hashes/revisions for source evidence; do not rely on mutable “latest” URLs alone.
- Do not log API keys, private attachments, or full sensitive issue bodies unnecessarily.
- Never auto-merge.
- Keep all proposed changes reviewable as ordinary text diffs.
Human review is the primary decision control, not a reason to omit deterministic safeguards.
Diff collection and context limits¶
Raw repository diffs should not be sent wholesale. The collector should:
- require explicit
from..torevisions; - emit file status and rename information first;
- exclude dependencies, lockfiles, generated bundles, build output, binaries, and large seed data by default;
- distinguish docs, behavior, styling, tests, and data changes;
- keep an audit list of excluded files;
- cap total bytes and per-file bytes;
- include relevant prototype workflow-doc changes ahead of raw component churn;
- make visual-only changes visible without pretending they prove behavior;
- allow the operator to add a deliberately excluded file when it matters.
The model should see the smallest sufficient evidence packet, not an arbitrary scheduled batch.
Evaluation plan¶
Golden cases¶
Build a reviewed fixture set from real Pinley history:
- pure design-system or formatting churn that should produce no behavioral spec change;
- a prototype change that modifies one existing feature and updates an existing Linear issue;
- a genuinely new feature requiring a new feature page and new Linear child after merge;
- a change spanning multiple feature pages;
- a design that conflicts with the accepted spec;
- a behavior already covered by the spec but not known to be deployed;
- a real deployed regression with current evidence;
- a removed or archived design surface;
- a renamed file and generated-data-heavy commit range;
- an intake with several plausible existing Linear duplicates.
Each fixture should contain the source packet, expected feature mapping, expected classification on each axis, expected patch properties, expected Linear action, and reviewer rationale. Model output can vary in wording; the material decisions must not.
Metrics¶
Track:
- correct feature mapping rate;
- patch applicability rate;
- materially correct requirement-change classification;
- unsupported deployment claims;
- duplicate Linear create proposals;
- reviewer edit distance and review time;
- questions accepted as necessary versus avoidable;
- model time and cost per intake;
- failed/abandoned packets;
- post-merge correction rate.
Promotion gates¶
Before automatic PR creation:
- at least five real historical packets have been run manually;
- every patch applies cleanly;
- no packet creates duplicate Linear work;
- no deployment state is asserted without evidence;
- reviewers judge the draft faster to correct than to recreate;
- the stable feature identity and authority policy are settled.
Before automatic post-merge Linear writes:
- at least ten accepted packets have been processed;
- reconciliation actions are correct and idempotent;
- retry tests create no duplicates;
- ownership and approval routing are explicit;
- audit links from Linear to spec and source evidence are complete.
No quality gate should be based only on valid JSON or a single successful model run.
Test strategy¶
Unit tests¶
- explicit Git range handling, including missing and non-ancestor revisions;
- diff filtering and size enforcement;
- feature-catalog parsing and stable-ID uniqueness;
- cross-field schema invariants;
- patch path allowlisting and
git apply --check; - documentation-build failure propagation;
- Linear candidate normalization and duplicate detection;
- idempotency key generation;
needs_humanderivation;- evidence requirements for implementation-state claims.
Integration tests¶
- read a recorded Linear intake fixture and feature catalog;
- generate a patch in a temporary worktree;
- build MkDocs successfully;
- render a deterministic PR body;
- update an existing mock PR on rerun;
- apply mocked post-merge Linear actions exactly once;
- preserve human edits or fail explicitly when they conflict.
Model evaluations¶
- run the golden cases against the candidate model and prompt;
- version the prompt and schema alongside results;
- compare models on decision accuracy, cost, latency, and reviewer effort;
- do not default to the most expensive model without measured benefit;
- retain representative failure outputs for regression testing.
Rollout¶
R0 — Policy and manual baseline¶
Do now:
- settle authority by field;
- name the intake steward and final product approver;
- add or select a stable feature identity;
- choose how a Claude Design artifact is versioned and exported;
- manually process five real intakes using the proposed packet;
- record time, edits, questions, and Linear reconciliation decisions.
No service or watcher is needed.
R1 — Draft-only command¶
Build /distill PIN-### as a local or CI-invoked command that:
- reads sources and existing Linear work;
- writes a packet and patch to a temporary/output location;
- performs validation;
- does not push, open a PR, or write to Linear.
The intake steward edits and applies the output manually.
R2 — PR automation¶
After the promotion gate, allow deterministic code to create or update one draft PR. Continue to prohibit automatic merge and Linear writes. Record review metrics.
R3 — Post-merge Linear reconciliation¶
After ten accepted packets and idempotency testing, allow the merge event to apply the already approved Linear action plan. Create nothing that was not present in the reviewed packet.
R4 — Optional behavioral evidence¶
Only if deployment drift is a demonstrated recurring cost, add a separate evidence job that exercises the relevant prototype and deployed flow. Start with deterministic Playwright journeys and screenshots for a small set of high-value capabilities. Its output remains evidence; it does not approve a requirement or merge a change.
R5 — Optional scheduling¶
Only if manual invocation is a measured bottleneck, schedule discovery of ready Linear intake issues. Do not schedule raw prototype-repository watching. A source commit is exploration until a person places it into intake.
What to keep, change, and park¶
Keep¶
- the read-only model boundary;
- deterministic Git and API mechanics;
- Zod or equivalent structured validation;
- human PR review and merge;
- explicit source revisions;
- failure rather than silent malformed output.
Change before further investment¶
- make a Linear intake ID the entry point;
- add the exact Claude Design artifact and revision;
- parse the current per-feature catalog instead of
capabilities.index.txt; - adopt stable feature identities and exact spec paths;
- replace the single classification with three independent axes;
- replace free-form
spec_editwith a validated patch; - search Linear before proposing any create action;
- remove implicit initial Git behavior and require an explicit range;
- derive
needs_humanfrom validated conditions; - implement idempotent upsert semantics;
- add real Pinley fixtures before connecting writes.
Park¶
- the scheduled repository watcher;
- the global checkpoint file;
- automatic Linear creation;
- the second divergence agent;
- screenshot comparison across the whole product;
- automatic priority, estimate, cycle, or assignment decisions;
- automatic merge;
- a model default chosen without evaluation.
Migration from the existing spike¶
The current repository can be evolved rather than discarded:
- Mark the existing service as a proof of concept in its README.
- Add deterministic tests around current Git behavior, including the reproduced first-run bug.
- Replace environment-only invocation with an explicit intake CLI.
- Replace
capabilityIndex()with a parser for per-feature frontmatter. - Introduce a stable feature ID and validate its uniqueness.
- Replace
Change/Judgmentwith the versioned packet schema and cross-field invariants. - Add recorded Linear read/search fixtures before a live connector.
- Generate and validate a real patch in an isolated worktree.
- Run the five manual golden intakes.
- Implement PR upsert only after the draft-only output proves useful.
- Implement post-merge Linear writes last.
The current openPullRequest stub should not be the next task. The next task is the real input/output
contract plus evidence fixtures.
Acceptance criteria for the intake compiler¶
- Given a valid intake ID, the command records the exact issue, design revision, spec base SHA, and optional prototype range.
- A clean first run cannot silently report no changes because of an implicit
git diff HEAD. - Every mapped existing feature resolves to exactly one stable feature page.
- Every proposed patch applies cleanly to the recorded base and passes the MkDocs build.
- Visual-only or mechanical changes can produce an explicit no-spec-change result.
- Deployment state remains unknown unless current evidence is attached.
- Every proposed Linear create action includes proof that existing work was searched.
- Re-running the same packet cannot create a second PR or Linear issue.
- Low confidence, conflicts, removals, open questions, and unlocked scope always require review.
- Agents cannot set
scope_lockedordesign_lockedto true. - A PR shows all source links, feature mappings, questions, Linear actions, and validation results.
- No Linear mutation occurs before the corresponding spec change is merged and the action was reviewed.
- No model process receives GitHub merge permission, Linear write credentials, or GitLab source access.
- Reviewers can correct an accepted draft faster than recreating the intake manually in the measured pilot.
Open decisions¶
These decisions must be made before implementation can be considered production work:
- Are per-feature pages the authority for accepted scope, with roadmap pages generated as views?
- What is the immutable feature identifier: a new
feature_idor a guaranteed-stable relative path? - Where does the active Claude Design live, and how are exact revisions exported or addressed?
- Is the prototype still an active exploration surface, historical evidence, or both?
- Who is the intake steward, and whose approval makes a spec merge authoritative?
- Does the original Linear intake issue become the implementation parent, or remain a separate product-decision record?
- Which Linear states, labels, project, and parent/child conventions define intake and ready work?
- When may completed or canceled issues be reused, reopened, or only referenced?
- Which information requires Conor's decision versus engineering or QA confirmation?
- What source data may be sent to the judgment model, and what must remain local?
- What reviewer-time improvement justifies maintaining the automation?
- Has behavioral drift caused enough recurring cost to justify a future divergence check?
Final recommendation¶
The problem is real: behavioral intent is being lost between Claude Design, the prototype, the spec, and Linear. A distillation aid can help. The present implementation does not yet solve that problem because it begins from the wrong event and lacks the artifacts that carry intent and existing work.
Use the Linear intake issue as the spine, the versioned design as the visual source, the merged per-feature spec as accepted product truth, and Linear implementation issues as delivery truth. Build one explicit, draft-only compiler around those boundaries. Prove it on real intakes. Automate PR and Linear writes only after accuracy, usefulness, and idempotency are demonstrated.
The best next engineering work is not another agent, a scheduler, or openPullRequest. It is a stable
feature identity, a versioned intake packet, five real fixtures, and a manual baseline against which
automation can earn its complexity.
Verification record from this assessment¶
- Distiller TypeScript typecheck: passed.
- Spec MkDocs build: passed; only the repository's existing non-nav notices and Material-for-MkDocs upstream warning were emitted.
- Distiller test inventory: no unit or integration test files found.
- Distiller live run with no checkpoint against a clean local prototype: reproduced the false “No changes since the checkpoint” result.
- Current distiller PR, Linear, scheduler, checkpoint-update, and divergence integrations: not implemented.
- Current spec target: per-feature Markdown pages with structured planning and Linear metadata are now present, improving the target structure but superseding the spike's capability-index assumption.