Skip to content

Design-to-Spec Intake — Distiller Assessment and Recommended Design

StatusProposed

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:

  1. capture a change from Claude Design or the prototype;
  2. connect it to the Linear intake conversation;
  3. map it to existing feature definitions;
  4. draft the proposed spec change;
  5. identify existing Linear work before proposing anything new;
  6. collect the necessary human decisions;
  7. merge the accepted requirement;
  8. 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-prototype checkout, 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:

  1. 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.
  2. A read-only model step. Restricting the model to read/search tools is a useful containment layer.
  3. Schema validation. Treating model output as untrusted data and validating it before use is the correct pattern.
  4. No automatic merge. A person decides whether proposed requirements become product truth.
  5. A reviewable pull request. The PR is a good audit artifact and a natural place to discuss a proposed change.
  6. 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:

  • status and stage;
  • confidence and estimate;
  • scope_locked and design_locked where 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_human is 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.”

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:

  1. the accepted-spec change;
  2. the decisions still required;
  3. the relationship to existing features;
  4. 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-design reason;
  • current spec base SHA;
  • operator identity.

Optional inputs:

  • prototype repository and explicit from..to revisions;
  • 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_id resolves to exactly one current spec path;
  • each patch target matches a mapped feature or an allowed derived index;
  • each patch applies to spec_base_sha with git apply --check;
  • new feature paths are unique and remain within content/features/;
  • shipped, partial, absent, or regressed requires current deployed evidence;
  • low confidence, a conflict, a removal, an open question, or an unlocked scope requires human review;
  • needs_human cannot 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

  1. Patch exact per-feature pages, not a generic capability prose field.
  2. Preserve current frontmatter and page structure.
  3. Update derived module indexes through deterministic generation where possible.
  4. Do not edit roadmap summaries independently when they can be derived from feature metadata.
  5. Include current behavior, proposed behavior, acceptance criteria, source references, and open decisions in the appropriate feature page.
  6. Keep historical Linear references when they remain useful evidence; distinguish them from active implementation work.
  7. Do not mark a feature built merely because an issue is Done.
  8. Do not mark scope or design locked without a recorded human decision.
  9. New features require a stable feature ID, module, owner or ownership gap, and explicit roadmap state.
  10. 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:

  1. update the existing intake issue;
  2. update an existing active implementation issue;
  3. add a child to the existing intake or epic;
  4. create a new issue only with an explicit no-match result;
  5. 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..to revisions;
  • 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:

  1. pure design-system or formatting churn that should produce no behavioral spec change;
  2. a prototype change that modifies one existing feature and updates an existing Linear issue;
  3. a genuinely new feature requiring a new feature page and new Linear child after merge;
  4. a change spanning multiple feature pages;
  5. a design that conflicts with the accepted spec;
  6. a behavior already covered by the spec but not known to be deployed;
  7. a real deployed regression with current evidence;
  8. a removed or archived design surface;
  9. a renamed file and generated-data-heavy commit range;
  10. 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_human derivation;
  • 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:

  1. settle authority by field;
  2. name the intake steward and final product approver;
  3. add or select a stable feature identity;
  4. choose how a Claude Design artifact is versioned and exported;
  5. manually process five real intakes using the proposed packet;
  6. 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_edit with a validated patch;
  • search Linear before proposing any create action;
  • remove implicit initial Git behavior and require an explicit range;
  • derive needs_human from 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:

  1. Mark the existing service as a proof of concept in its README.
  2. Add deterministic tests around current Git behavior, including the reproduced first-run bug.
  3. Replace environment-only invocation with an explicit intake CLI.
  4. Replace capabilityIndex() with a parser for per-feature frontmatter.
  5. Introduce a stable feature ID and validate its uniqueness.
  6. Replace Change/Judgment with the versioned packet schema and cross-field invariants.
  7. Add recorded Linear read/search fixtures before a live connector.
  8. Generate and validate a real patch in an isolated worktree.
  9. Run the five manual golden intakes.
  10. Implement PR upsert only after the draft-only output proves useful.
  11. 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_locked or design_locked to 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:

  1. Are per-feature pages the authority for accepted scope, with roadmap pages generated as views?
  2. What is the immutable feature identifier: a new feature_id or a guaranteed-stable relative path?
  3. Where does the active Claude Design live, and how are exact revisions exported or addressed?
  4. Is the prototype still an active exploration surface, historical evidence, or both?
  5. Who is the intake steward, and whose approval makes a spec merge authoritative?
  6. Does the original Linear intake issue become the implementation parent, or remain a separate product-decision record?
  7. Which Linear states, labels, project, and parent/child conventions define intake and ready work?
  8. When may completed or canceled issues be reused, reopened, or only referenced?
  9. Which information requires Conor's decision versus engineering or QA confirmation?
  10. What source data may be sent to the judgment model, and what must remain local?
  11. What reviewer-time improvement justifies maintaining the automation?
  12. 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.