sketch

sketch is a skill for Claude Code, Codex from jongwony/epistemic-protocols. It costs 46 tokens per session (9,420 once invoked), scanned A, original, MIT.

A method for discovering a design by reviewing concrete sketches and marking what does not fit. It repeats that review and revision until a suitable form is recognized.

In plain words
What is it for?
Exploring visual or other forms when the intended result is unclear, then refining a chosen sketch through feedback.
Why use it?
It helps when people can identify wrong examples more easily than they can describe the right design in advance.

Skill for Claude CodeCodex

Written for no agent in particular: nothing here depends on one.

Part of the hypotyposis plugin — 1 skill shipped together

Good fit Exploring visual or other forms when the intended result is unclear, then refining a chosen sketch through feedback.

Compare 6 skills from other repositories ↓
Install with agentmods
npx agentmods add skills/jongwony/epistemic-protocols/sketch
Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

Any agent
npx skills add jongwony/epistemic-protocols --skill sketch
Clone the repo
git clone --depth 1 https://github.com/jongwony/epistemic-protocols

Made for: Claude Code, Codex.

Or install hypotyposis, the plugin that ships this one along with the rest of its 1 skill.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for sketch

README.md
[![agentmods](https://agentmods.dev/badge/skills/jongwony/epistemic-protocols/sketch/github.svg)](https://agentmods.dev/skills/jongwony/epistemic-protocols/sketch)
Your own site
<a href="https://agentmods.dev/skills/jongwony/epistemic-protocols/sketch"><img src="https://agentmods.dev/badge/skills/jongwony/epistemic-protocols/sketch/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for sketch

Your own site · 80×15
<a href="https://agentmods.dev/skills/jongwony/epistemic-protocols/sketch"><img src="https://agentmods.dev/badge/skills/jongwony/epistemic-protocols/sketch.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 46 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 9,420 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00046 $0.09420
Opus 5 $0.00023 $0.04710
Sonnet 5 $0.00009 $0.01884
Haiku 4.5 $0.00005 $0.00942

Measured 3d ago against content hash f5e8c413ea8f, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-11, from the pricing page.

Security

Grade A, and why

sketch scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 3d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

hypotyposis/skills/sketch/SKILL.md · 335 lines

How it starts

The opening of the file, as written. The whole thing — 335 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Hypotyposis Protocol

Discover what a form should be by encountering concrete sketches and marking what does not fit, until the user recognizes a specific version as the form for a stated purpose. Type: (FitUnrecognized, Hybrid, SKETCH-RECOGNIZE-CYCLE, FormIntentSeed) → RecognizedForm.

Definition

Hypotyposis (ὑποτύπωσις): an outline or sketch — a first drawing of a position rather than its finished statement. A dialogical act for the moment when a form has to be made and the intent behind it cannot yet be settled from descriptions: the user can say what is wrong with a thing in front of them long before they can say what the thing should be, because good fit has no positive description of its own while each misfit is immediate and can be pointed at (Alexander, 1964). So the protocol runs the other way round from a specification: the AI drafts each round's focus, the perception it needs, and its variants, relays the draft with the basis that chose each, and produces the sketches; the user marks a specific version — what does not fit and what to keep — as first-class utterances, settling or sending back the round's readings in the same answer; the AI revises the retained version under those marks; and the loop ends when the user recognizes one version as the form for a stated purpose and names where it lives.

── FLOW ──
Hypotyposis(I) → detect(I, ctx) →
  [¬fit_unrecognized(I, ctx)] no_activation_relay → exit (NoActivationRelay)
  bind(I) → Λ.history (each prior item as Settled | Candidate, provenance kept) → Λ.round := 1 →
  spec_relay(draft(RoundSpec, provisional(Λ))) → Λ.spec := draft → produce(spec, Λ) → Sk →
  present(Sk) → Qfit(Sk, spec.focus) → Stop → M →
    [M = Marks(ms, acts)]   act(acts) → record(ms) → interpret(ms) → record(Proposed) → Λ.round += 1 → spec_relay
    [M = Fit(w, acts)]      act(acts) → w.context_revision := Λ.context_revision → Λ.fit_witnesses ∪= {w} → Λ.round += 1 → spec_relay   -- one focus adequate; the loop continues
    [free response: spec revision] revise(draft, rev) → spec_relay (scoped to the revision; no new round counted)
    [M = Finish(rec, acts)] act(acts) → rec.context_revision := Λ.context_revision → Λ.recognition := Some(rec) → Qplace → Stop → P → harvest → account →
                        [retention verified] RecognizedForm
                        [retention failed]   declare → Qplace (re-presented with the failure; the same location is admissible)
    [M = Withdraw]    account → EarlyExit
  [either party, at the spec relay or at any gate: recognition needs no further encounter ∨ activation premise collapsed]
    dissolution_relay → account → DissolutionExit
  [either party, at the spec relay or at any gate: a sibling deficit is demonstrated ∨ a realization the round requires is unavailable]
    boundary_relay → account → BoundaryExit

── MORPHISM ──
FormIntentSeed
  → detect          -- deficit predicate over the utterance and accumulated context (silent analysis)
  → bind            -- prior material enters the history as Settled or Candidate, provenance kept
  → relay_round     -- Extension: focus, realization, and targets drafted with the basis that chose each, relayed beside the provisional coordinates; nothing is settled here
  → produce         -- transform: one sketch per brief — a brief naming a parent revises that retained version, a parentless brief generates from the material it names or from prior material — and declares what producing it determined that no coordinate covered
  → present         -- relay: each sketch from its typed concretum, what this round can and cannot expose, and whether an artifact was observed
  → recognize       -- Constitution: marks on a specific version — Marks | Fit | Finish | Withdraw; the same answer promotes, supersedes, or holds the coordinates in view
  → record          -- track: every mark, and every interpretation read from it, enters the append-only history; interpretations stay provisional
  → place           -- Constitution: where the recognized concretum lives beyond the session, and which versions the run passed over are kept as revert points; no default for either
  → harvest         -- active commitments, recognition witness, trace, and residual recorded before release
  → account         -- per-sketch retain-or-release disposition, verified
  → RecognizedForm
requires: form_purpose_in_scope(I)             -- runtime checkpoint (Phase 0): the work is about to make a form
deficit:  FitUnrecognized                       -- activation precondition (Layer 1/2)
preserves: utterance(I)                          -- I.utterance is read-only; the history accumulates beside it
invariant: Concretum Retention                   -- a brief that revises does so on a retained parent; a sketch under judgment is never regenerated from coordinates alone
invariant: Commitment Provenance Preservation    -- a prior constitutive act stays recorded; a later user act may supersede its operative determination; AI inference alone never supersedes a user commitment
invariant: Recognition over Description          -- fit is the user's recognition of a specific version for a stated purpose

── TYPES ──
I  = FormIntentSeed { utterance: String, prior: List(ReferencedMaterial) }
       -- Input type: morphism processes I uniformly; prior is source-neutral — a settled direction, a resolved intent,
       --   a candidate field, an existing artifact, a prior session's record — each named by the user or already in context
ReferencedMaterial = { source: String, content: String }          -- what it is and where it came from; no sibling type is a runtime dependency
Binding = Settled(Coordinate) | Candidate(ReferencedMaterial)      -- how a prior item enters the history at bind: a commitment the user already made, or material to draw on
fit_unrecognized(I, ctx) = a form-making purpose is in scope
                         ∧ decision-relevant intent remains underdetermined
                         ∧ encountering and revising a concrete proposal is what would constitute that intent
                         ∧ the resolution sought is a recognized form with its commitments and residuals
Axis      = String                                                 -- emergent label: "information unit", "reading order", "density", "tone"
Focus     = Axis | Question(String)                                -- what this round filters attention toward; an unexpected misfit on any other axis stays admissible
Value     = String                                                 -- a determination on an axis, in the user's words or read off the sketch
Realization = capability description                               -- what this round's judgment needs in order to be possible: the perception it rests on
       --   (narration, spatial layout, interaction, sound, …) and, where the focus opens an axis carrying a standard
       --   outside both parties' preference, the referent it is checked against. Open, named per round — and a referent
       --   the round requires that this session cannot supply is the boundary arm's condition rather than something to
       --   proceed without
VariantBrief = { parent: Optional(SketchRef), source: Optional(ReferencedMaterial), commits: Map(Axis, Value) }
       -- one sketch to produce. Some(parent): revise that retained version. None: generate from active_coords and
       --   from the material `source` names, or from the bound prior material where it names none — every brief of round 1's
       --   first pass, and a fresh start the user names at Qfit for a later round; a SpecRevision re-entry that keeps a version
       --   names it as parent, so the re-drafted round revises the retained version rather than regenerating it
       -- a round that changes where the material comes from is a parentless brief naming the new source, not a
       --   different kind of round: what the loop does is unchanged, and what moved is only what "generate" draws on
RoundSpec = { focus: Focus, realization: Realization, targets: NonEmptyList(VariantBrief) }
       -- k = |targets| is drafted here; a count the user settled at a recognition gate holds until they revise it
Supersession = { of: Coordinate, by: Optional(Coordinate) }        -- the user's act on a coordinate in view: by = Some(c') replaces it with a determination the user states (c' enters Settled, basis Utterance), by = None retires it with nothing in its place
CoordinateActs = { settlements: Set(Coordinate), supersessions: Set(Supersession) }
       -- the user's acts on the coordinates in view, riding the recognition answer: which provisional coordinates become
       --   Settled and which coordinates — Provisional or Settled — they supersede; either set possibly empty
SpecRevision = a change to this round's focus, realization, or targets, named by the user as a free response at the recognition
       gate; the spec relay re-presents scoped to it and no new round is counted
SketchRef = { id: ℕ, round: ℕ }                                    -- identity of one version; the harvest and every mark point at one of these
Concretum = Text(value) | Artifact(versioned_ref)                  -- Text: narration carried in session text; Artifact: a file under temp isolation, versioned at creation
Sketch = { ref: SketchRef, parents: List(SketchRef), concretum: Concretum, rendered_from: snapshot(active_coords), focus: Focus }
       -- what it was rendered under that no Settled or Provisional coordinate covered — its brief's commits and what producing it determined — reaches the history as Proposed coordinates basis Production(ref),
       --   so a sketch's own determinations are read back by its reference rather than stored a second time
Anchor = Element(locator) | Region(bounds) | Whole | Span(text)    -- where on a sketch a mark points; Whole admits "something is missing here" with nothing to point at
       -- premise: a mark points at a place. A property recurring across the sketch sits at none, and arrives as Whole
       --   with the property itself in the mark's utterance and, where it names one, its axis — carried whole, not classified
Mark = Misfit { sketch: SketchRef, anchor: Anchor, utterance: String, axis: Optional(Axis) }
     | Keep   { sketch: SketchRef, anchor: Anchor, utterance: String }
       -- a user utterance anchored on a version; Keep is the positive half of mixed feedback and is retained, never dropped
Status = Provisional | Settled
Coordinate = { axis: Axis, value: Value, basis: Mark | Binding | Utterance | Production(SketchRef), status: Status, round: ℕ }
       -- interpret() yields Provisional only; Settled requires the user's act at Qfit or a convention already on record
       -- Production(ref): a determination rendered into that sketch that no Settled or Provisional coordinate covered — drafted in its brief or made while producing.
       --   Provisional like any reading, and settled or superseded only by the user's act at the next recognition gate —
       --   production introduces determinations, it never settles them
Event = Bound(Binding) | Marked(Mark) | Proposed(Coordinate) | Promoted(Coordinate) | Superseded(Coordinate, by: Optional(Coordinate)) | Witnessed(FitWitness)
       -- Superseded is appended by supersede at Qfit and nowhere else: the user's act is its only producer, so an AI interpretation the user rejects leaves provisional(Λ) and a determination the user replaces leaves active_coords
       -- Proposed is appended by interpret and by produce: a coordinate the AI puts forward, whichever step reached it.
       --   Its basis says which, and its lifecycle is one — presented at the spec relay and again beside the sketch at Qfit, promoted or superseded there, residual otherwise
active_coords(Λ) = fold(Λ.history)                                  -- the operative determinations now: per axis, the latest Settled coordinate with no Superseded(it, _) after it — Superseded(c, Some(c')) makes c' operative in c's place, Superseded(c, None) retires c with nothing in its place; Provisional ones shown beside
provisional(Λ)   = { c : Proposed(c) ∈ Λ.history ∧ ¬∃ Promoted(c) ∈ Λ.history ∧ ¬∃ Superseded(c, _) ∈ Λ.history }
                                                                    -- what the AI read from a mark or decided while producing, awaiting the user's act at Qfit; derived from the history, never stored apart
FitWitness  = { sketch: SketchRef, context_revision: ℕ, scope: Focus, utterance: String }
       -- adequacy on one focus for one version; bound to the context revision the answer carrying it left, acts included; stale once its sketch is superseded or the context revision moves — shown as stale, never reused silently
Recognition = { target: SketchRef, context_revision: ℕ, purpose_scope: String, residual: Set(Axis) }
       -- target must be a presented, retained version; Finish is recognition of the assembled form, not of one focus
M  = Recognition gate answer ∈ {Marks(Set(Mark), CoordinateActs), Fit(FitWitness, CoordinateActs), Finish(Recognition, CoordinateActs), Withdraw}
       -- the acts ride Marks, Fit, and Finish: the answer that judges the version also settles or sends back the readings shown
       --   beside it, and an answer naming none carries empty sets; a settlement stated in the Finish answer reaches commitments
       --   through the same act, and what is still Provisional after it is declared in the result's provisional set; Withdraw
       --   carries none — nothing it settled would be read
       -- Marks(∅, ∅) is read as Stop, never as Fit; Marks(∅, acts) with acts non-empty moves the coordinates and re-enters the
       --   next round as any Marks does; silence yields the turn again; a response carrying both marks and a finish is parsed
       --   as Marks — recognition names an unmarked version
       -- premise: one answer settles this version. An answer also naming what a later round should take up departs from
       --   that premise rather than breaking it — it is parsed by its constructor, and the rest is recorded as itself
Location = a reference the user judges to outlive the session      -- the capability the placement gate asks the user to bind; the protocol supplies no default
       -- the durability is their judgment, not a checked fact: account verifies that the reference resolves to that
       --   version's concretum AT THE MOMENT IT IS CHECKED, which is the narrower of the two claims
P  = Placement gate answer ∈ {Place(Location, kept: Map(SketchRef, Location))}
       -- where the recognized version lives, and which versions that were not recognized are kept as revert points and
       --   where; kept may be empty. On a re-presentation after RetainFailed, either may be the same or another; a
       --   free-response withdrawal here is EarlyExit with the recognition in the partial trace
Fixture = { ref: Location, target: SketchRef, scope: String, residual: Set(Axis), kept: Map(SketchRef, Location) }
       -- status: recognition witness. It carries no implementation commitment and is not an executable specification
       -- kept: what a later reversal would otherwise have to rebuild. A version the loop passed over is what the
       --   decision could return to, and returning to it costs rebuilding unless it survives as itself
Disposition ∈ {Retained(Location), Released, ReleaseFailed(reason), RetainFailed(reason)}
       -- Retained is written only once verification holds: the reference resolves to the recognized version's exact concretum. RetainFailed sends control back to Qplace; ReleaseFailed is declared with a handoff
TraceEntry = (Mark → Optional(Coordinate) → Optional(SketchRef) → Recognized | Superseded | Residual)
       -- what each mark became: its interpretation, the revision it drove, and how it ended
ExitCause ∈ {NotActivated, Recognized, Withdrawn, BoundaryReached, Dissolved}
RecognizedForm = single record { commitments: Set(Coordinate) (Settled only), witness: Fixture, recognition: Recognition,
                                 trace: List(TraceEntry), residual: Set(Axis ⊎ ReferencedMaterial), provisional: Set(Coordinate) }
       -- assembled after account: the retained concretum is reachable through witness.ref, and what the user named for a
       --   round that never came is declared rather than dropped
NoActivationRelay = the non-activation basis stated: the failed predicate with its evidence; a sibling deficit visible in the same scan is named as a finding and left to the session
EarlyExit = withdrawal at any gate: partial trace over completed rounds + account enforced + residual declared (no RecognizedForm returned; any prior recognition remains in the partial trace)
BoundaryExit = the unresolved obligation named — a sibling deficit demonstrated, or a realization the round requires that this session cannot supply — with account enforced; which protocol takes it is the session's, never this record's
DissolutionExit = the deficit dissolved during a circulation: the sharpened description made the form recognizable without a further encounter, or the activation premise collapsed; declared by either party with its basis, the surviving determinations relayed, account enforced
Phase     ∈ {0, 1, 2, 3, 4, 5, 6}

── A-BINDING ──
bind(I) = explicit_arg ∪ recent_form_intent ∪ surfaced_fit_gap
Priority: explicit_arg > recent_form_intent > surfaced_fit_gap

/sketch "what to make"          → I = FormIntentSeed with utterance; prior = material the utterance names or that is already in context
/sketch (alone)                 → I = the most recent form-making intent in session
"I'd know it when I see it"     → I = the utterance under discussion (AI-detected path: the spec relay cites the evidence of FitUnrecognized as the run's basis; a decline of the run is a withdrawal at the first Qfit)

── PHASE TRANSITIONS ──
Phase 0: I → detect(I, ctx) → fit_unrecognized?                                     -- silent analysis
       [false] Λ.exit := NotActivated → no_activation_relay → exit (NoActivationRelay)
       [true]  → Phase 1
Phase 1: bind(I) → Λ.history := Bound(each prior item) → Λ.round := 1 → Phase 2       -- track; Settled where the user already committed, Candidate otherwise
Phase 2: draft(RoundSpec, provisional(Λ)) → spec_relay(draft, provisional(Λ)) → commit(Λ.spec := draft) → Phase 3   -- round-spec relay [Tool]
       -- the relay yields no turn: it lays out this round's focus, what the judgment needs, the variant briefs, each with the basis that chose it, and each provisional coordinate with where it came from; nothing is settled here — a coordinate is promoted or superseded only by the user's act at Qfit
       -- RE-ENTERED from Qfit on a SpecRevision: revise(draft, rev) first, then the relay goes out scoped to the revision and no new round is counted
       -- on the AI-detected path the relay cites the evidence of FitUnrecognized as the run's basis; a decline of the run is the withdrawal arm at the first Qfit (Phase 6, EarlyExit arm — account enforced, since a sketch exists by then)
Phase 3: produce(Λ.spec, Λ) → Sk : NonEmptyList(Sketch) → Λ.sketches ++= Sk
         → Λ.history ++= Proposed(each determination rendered into Sk that no Settled or Provisional coordinate covered — its brief's own commits included, since the relayed draft settled nothing — basis Production(its ref))   -- transform [Tool]
       [|Λ.spec.targets| > 1, conditional] produce_delegate(∥ one sketch per executor, temp-isolated) [Tool]
       -- dispatch on brief.parent: Some(ref) → revise(ref retained, active_coords, marks since ref, brief.source where it names one); None → generate(brief.source where it names one else prior material, active_coords, brief.commits) — a brief may name both, and changing the material does not itself abandon the parent
       -- every sketch records its concretum and a versioned reference at creation; existing project files stay unchanged
Phase 4: present(Sk) → acquire(marks) → Qfit(Sk, Λ.spec.focus) → Stop → M             -- recognition gate [Tool]
       [M = Marks(ms, acts)] act(acts) → Λ.history ++= Marked(each) → interpret(ms) → Δ → Λ.history ++= Proposed(each c ∈ Δ) → stale(Λ.fit_witnesses over superseded sketches) → Λ.round += 1 → Phase 2
       [M = Fit(w, acts)]    act(acts) → w.context_revision := Λ.context_revision → Λ.fit_witnesses ∪= {w} → Λ.history ++= Witnessed(w) → Λ.round += 1 → Phase 2   -- the witness is bound to the revision the same answer left, so the acts riding it do not stale it on arrival
       [M = Finish(rec, acts)] act(acts) → rec.context_revision := Λ.context_revision → Λ.recognition := Some(rec) → Phase 5   -- the recognition is bound to the revision its own acts left, as a Fit witness is
       [M = Withdraw]        → Phase 6 (EarlyExit arm)
       -- act(acts): promote(acts.settlements) → Λ.history ++= Promoted(each) → supersede(acts.supersessions) → Λ.history ++= Superseded(each of, by) → Λ.context_revision += 1 where either set is non-empty; it runs before interpret, so a reading is drawn against what the user just settled
       -- free responses declared pre-gate: interrogate a sketch (answered within its placeholder status, gate re-presented); send back this round's focus, realization, or variants (a SpecRevision — Phase 2 with the revision named, no new round counted); contest the premise (dissolution arm); name a boundary (boundary arm)
       -- Marks(∅, ∅) is Stop; a mixed response keeps its Keep marks; a response naming a version that was not presented is answered, never parsed as Finish
Phase 5: Qplace(Λ.recognition.target) → Stop → P                                        -- placement gate [Tool]
       [P = Place(location, kept)] Λ.fixture := Some({ref: location, target, scope, residual, kept}) → harvest → Phase 6 (RecognizedForm arm)
       -- the protocol names the capability (a reference the user judges to outlive the session) and supplies no default, for the recognized version or for any kept one; a withdrawal here is the EarlyExit arm with the recognition recorded in the partial trace
       -- RE-ENTERED from Phase 6 on RetainFailed: the failure is declared before the gate; the user names a location again — the same one is admissible — or withdraws
Phase 6: account → [a terminal arm] Λ.exit := cause → terminal                          -- all arms [Tool]; the RetainFailed arm returns to Phase 5 with Λ.exit still None
       [from Phase 5 — recognized and placed] retain(recognition.target at Λ.fixture.ref) ∧ ∀ (s, loc) ∈ Λ.fixture.kept: retain(s at loc)
         → verify(resolves(Λ.fixture.ref, concretum(recognition.target)) ∧ ∀ (s, loc) ∈ Λ.fixture.kept: resolves(loc, concretum(s)))
         [all verified] Λ.dispositions ++= (target, Retained(Λ.fixture.ref)) and (s, Retained(loc)) for each kept
           → release(every sketch neither recognized nor kept) → Λ.exit := Recognized → assemble → RecognizedForm
         [any failed after one retry] Λ.dispositions ++= (each that failed, RetainFailed(reason)) → Λ.fixture := None → Phase 5 (Qplace re-presented with every failure declared; harvest re-runs with the next fixture)
           -- ONE rule for the recognized version and for a kept one: a reference that does not resolve returns the placement to the user rather than being closed over, since accounted demands every reference the result needs
           -- nothing is released on this arm: every sketch stays retained until a terminal is reached, so a later Place still finds the target and each kept version
       [withdrawal at any gate] release(all) → EarlyExit
       [dissolution arm] release(all) → DissolutionExit
       [boundary arm] release(all) → BoundaryExit
       -- release: per sketch, the destruction read off its concretum (a no-op for Text) → verify absence → Disposition; a failure retries once, then is declared ReleaseFailed with a handoff, never silent
       -- Λ.dispositions is append-only; a sketch's disposition is its latest entry, so a RetainFailed is superseded by the Retained a later Place verifies

── LOOP ──
Each round re-enters Phase 2 with the history it accumulated; the round counter is visible at every spec relay and Qfit.
No fixed round cap: a round that re-enters a Constitution gate is dialogue, and the user can withdraw at any gate.
Variant count is drafted per round at the spec relay; a count the user settled at a recognition gate holds until they revise it.
Continue until: RecognizedForm (Finish + placement + account) OR EarlyExit OR DissolutionExit OR BoundaryExit.
Convergence evidence: at RecognizedForm, present the trace — each mark → its interpretation → the revision it drove → how it ended (recognized, superseded, or residual) — beside the recognized version, its placement, the versions kept as revert points, the Settled commitments, the coordinates still Provisional and the residual — axes left open and material the user entrusted to a round that never came. Each other terminal presents its own payload (TOOL GROUNDING). Demonstrated, not asserted.

── CONVERGENCE ──
disposition(s)  = the latest entry for s.ref in Λ.dispositions
accounted(Λ) = ∀ s ∈ Λ.sketches: disposition(s) is defined                  -- every sketch has a declared disposition
             ∧ (Λ.fixture = Some(f) ⇒ resolves(f.ref, concretum(f.target))
                                    ∧ ∀ (s, loc) ∈ f.kept: resolves(loc, concretum(s)))  -- each reference resolves to that version's exact concretum, verified at the moment it is checked, and to nothing else
             ∧ ∀ s: disposition(s) ∈ {ReleaseFailed(_), RetainFailed(_)} ⇒ handoff_declared(s)  -- failures are declared, never silent
recognition_ready(Λ) = Λ.recognition = Some(rec)
                     ∧ rec.target ∈ presented(Λ.sketches) ∧ disposition(rec.target) = Retained(Λ.fixture.ref)   -- retention verified, never assumed
                     ∧ rec.context_revision = Λ.context_revision
                     ∧ Λ.fixture ≠ None                                      -- Qplace settled
                     ∧ residual_declared(Λ) ∧ trace_declared(Λ)
converged(Λ) = accounted(Λ) ∧ ((Λ.exit = Recognized ∧ recognition_ready(Λ)) ∨ (Λ.exit = Dissolved ∧ basis_declared(Λ)))
result equations:
  NoActivationRelay ⇔ Λ.exit = NotActivated                                  -- nothing produced; nothing to account
  RecognizedForm    ⇔ Λ.exit = Recognized ∧ recognition_ready(Λ) ∧ accounted(Λ)
  EarlyExit         ⇔ Λ.exit = Withdrawn ∧ accounted(Λ)                      -- non-convergent
  BoundaryExit      ⇔ Λ.exit = BoundaryReached ∧ obligation_named(Λ) ∧ accounted(Λ)   -- non-convergent; the session routes it
  DissolutionExit   ⇔ Λ.exit = Dissolved ∧ basis_declared(Λ) ∧ accounted(Λ)  -- convergent stand-down: no form was owed

── TOOL GROUNDING ──
-- Realization: Constitution → TextPresent+Stop; Extension → TextPresent+Proceed
Phase 0 detect (sense)              → Internal analysis (deficit predicate over the utterance and accumulated context; no external tool)
Phase 0 no_activation_relay (extension) → TextPresent+Proceed (the non-activation basis — the failed predicate with its evidence; a sibling deficit seen in the scan is named as a finding and left to the session; not activated)
Phase 1 bind (track)                → Internal state update (prior material enters Λ.history as Settled or Candidate with provenance; the round counter starts)
Phase 2 draft (sense)               → Internal analysis (focus, realization, and target briefs proposed from the accumulated history — the operative commitments, the provisional readings, the bound prior material, and every mark so far — read together rather than from any one of them)
Phase 2 spec_relay (extension)      → TextPresent+Proceed (the round's draft whole: this round's focus, what the judgment needs, the variant briefs, each with the basis that chose it, and each provisional coordinate with where it came from — laid out so that any of it can be settled, sent back, or replaced at the recognition gate, as can any Settled coordinate in view; fires BEFORE anything is produced and settles nothing; on the AI-detected path it cites the evidence of FitUnrecognized as the run's basis; re-presented scoped to a SpecRevision the recognition gate named, without counting a round)
Phase 2 revise (track)              → Internal state update (a SpecRevision named at Qfit: the draft revised as named before the spec relay re-presents)
Phase 2 commit (track)              → Internal state update (Λ.spec := the relayed draft; no coordinate moves here — the user's acts on coordinates are written at Qfit's record step)
Phase 3 produce (transform)         → artifact write, environment run (temp-isolated sketches, each with its concretum and a versioned reference registered at creation; a brief naming a parent revises that retained version, a parentless brief generates from the material its source names or from prior material; existing project files are never modified; Text concreta are session text only. Each sketch proposes as coordinates what it was rendered under that no Settled or Provisional coordinate covered — its brief's own commits and what producing it determined beyond them, since the relayed draft settles nothing — so the user meets those determinations beside the sketch at Qfit rather than only their consequences on the screen)
Phase 3 produce_delegate (dispatch) → delegate (conditional: more than one target; parallel topology: one sketch per executor, each temp-isolated with its reference registered; subordinate to the active runtime policy)
Phase 4 present (extension)         → TextPresent+Proceed (each sketch from its typed concretum — Text re-presented as recorded, an Artifact walked through at its reference, reporting what was observed there or that it was not observed and what was tried — since Text is read as recorded while an Artifact is only ever presented as far as it was seen — then this round's focus, what this realization cannot expose, which content came from the user and which is the AI's proposal, what this sketch's own production determined, and every fit witness now stale)
Phase 4 acquire (observe)           → a channel returning utterances anchored on a sketch (read-only: the marks arrive as the user's utterances; the channel is a capability the host supplies, named here and bound nowhere in this contract. What a host must satisfy is that the user can point at what they saw and that the pointing arrives with the utterance; how it does so is read at the round against the host in front of it)
Phase 4 Qfit (constitution)         → present (mandatory recognition gate on a specific version: Marks, Fit on this focus, Finish for a stated purpose, Withdraw — and, riding Marks, Fit, or Finish, the user's acts on the coordinates in view: which provisional readings they settle, and which coordinates they supersede or retire; Marks(∅, ∅) is Stop; the pre-gate text declares the free-response paths — interrogate, send back this round's focus, realization, or variants, contest the premise, name a boundary)
Phase 4 record (track)              → Internal state update (the user's acts on coordinates written first — each settled coordinate takes a Promoted event, each superseded one a Superseded event with the replacement they stated or none, and the context revision advances where either set is non-empty; then every mark appended to Λ.history as itself, then each Provisional coordinate interpret read from it appended as Proposed; a fit witness appended, bound to the context revision those acts left; witnesses over superseded sketches marked stale)
Phase 4 interpret (sense)           → Internal analysis (marks, read against the accumulated history, → Provisional coordinates, each carrying the mark it came from; never Settled here; what it yields reaches Λ only through record)
Phase 5 Qplace (constitution)       → present (mandatory placement gate: the recognized version and the capability it needs — a reference the user judges to outlive the session — together with the versions this run passed over, since those are what a later reversal would otherwise rebuild; the user names the location and which of the others are kept and where; no default is offered for either)
Phase 6 harvest (track)             → Internal state update (Settled commitments, the fixture, the recognition, the trace, the residual axes, and the coordinates still Provisional, recorded before any release; the durable record is the RecognizedForm entire — sketch content beyond what placement retains stays session-local)
Phase 6 account (transform)         → artifact write, environment run (retain the recognized version at the settled location and verify the reference resolves to that exact concretum — one retry, then RetainFailed is declared and Qplace is re-presented with nothing released; once every placed version is retained, release the sketches placement did not keep and verify each — one retry, then ReleaseFailed declared with a handoff)
dissolution_relay (extension)       → TextPresent+Proceed (either party, at the spec relay or at any gate: the sharpened description made the form recognizable without a further encounter, or the activation premise collapsed; state the basis, relay the Settled commitments and every mark recorded, run account, stand down as DissolutionExit — a success, not an abandonment)
boundary_relay (extension)          → TextPresent+Proceed (either party, at the spec relay or at any gate: a sibling deficit is demonstrated, or a realization this round requires is one this session cannot supply; name the obligation and its basis, relay the harvest so far, run account, exit as BoundaryExit; the next protocol is the session's to choose)
withdraw (extension)                → TextPresent+Proceed (explicit free-response exit at any gate: partial trace + residual declared; account enforced; EarlyExit. A hard interrupt yields no turn, so account cannot run: temp isolation's bounded lifecycle is the backstop)
converge (extension)                → TextPresent+Proceed (transformation trace: marks → interpretations → revisions → recognition; the recognized version, its placement, Settled commitments, Provisional coordinates, residual axes, and every disposition)
seam (extension)                    → TextPresent+Proceed (fires at deactivation: a user-declared chain naming the next protocol settles the next move — proceed to it, citing that settling source; the RecognizedForm enters it as prior material, its fixture a recognition witness and nothing more. This protocol declares no wired outbound edge of its own. Every Constitution gate inside this protocol and inside the next fires unchanged)

── MODE STATE ──
Λ = { phase: Phase, I: FormIntentSeed, round: ℕ,
      context_revision: ℕ,                     -- advances when the accumulated context moves outside the marks: a new user utterance about the form, a spec revision, a promoted or superseded coordinate
      history: List(Event ⊎ ReferencedMaterial),   -- append-only; the typed events and, beside them, each gate answer as the
                                               --   user said it, so what a constructor does not reach still survives the round
                                               --   it was said in; active_coords and provisional are folded from it, never stored apart
      spec: Option(RoundSpec),                 -- this round's relayed draft; None until the spec relay goes out
      sketches: List(Sketch),                  -- every version produced, retained for revision until account
      fit_witnesses: Set(FitWitness),          -- with staleness derived from sketches and context_revision
      recognition: Option(Recognition),
      fixture: Option(Fixture),
      dispositions: List<(SketchRef, Disposition)>,   -- append-only; a sketch's disposition is its latest entry, one defined per sketch by terminal (invariant: accounted)
      exit: Option(ExitCause),
      active: Bool, cause_tag: String }
-- Guard: no sketch is produced before the spec relay presented its brief with its basis — on round 1's first pass, phase < 3 ⇒ sketches = ∅; a re-entry on a SpecRevision, and every later round, holds the sketches already produced and produces nothing until its spec relay has gone out again
-- Guard: a Coordinate enters Settled only through Promoted (a user act at Qfit), Bound(Settled) (a commitment already on record), or as the `by` of a Superseded the user stated at Qfit; a Proposed event is the only way a Provisional coordinate enters the history, and it stays Provisional until Promoted or Superseded

── COMPOSITION ──
*: product — (D₁ × D₂) → (R₁ × R₂). Form resolution emergent via session context.

Read the full file on GitHub · 335 lines

Files

What ships with it

1 file beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 3d ago Changed f5e8c413ea8f
  2. 4d ago First seen · 335 lines · 46 tokens per session scan A 2738fe01207d

Subscribe to this mod's changes

sketch is a skill published in the GitHub repository jongwony/epistemic-protocols (161 stars, last pushed today), licensed MIT. It adds 46 tokens to every session and 9,420 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-07.

Related

Other skills, from other repositories

logo-designer

Design and iterate on logos using SVG. Use this skill when the user asks to "create a logo", "design a logo", "make me a logo", "iterate on this logo", "logo for my project", or discusses logo design, branding icons, or wordmarks.

neonwatty/logo-designer-skill · 61 tokens

xiaohongshu-cover

An AI cover-planning tool for Xiaohongshu, a Chinese social platform for lifestyle and product content. It studies popular covers in a topic area and produces three cover concepts with examples and image-generation prompts.

redfox-data/redfox-community-dsh · 103 tokens

pn-image-creator

Questionnaire-driven image creation for high-quality PNG or SVG. Always grounds prompts in pn-cinematography-lighting and pn-image-prompt-engineering (camera, lighting, visual style). Gates on user confirmation before generation. Use with Cursor image generation or SVG per pn-svg-creator.

perniemann/pnCore · 63 tokens

html-ppt-zhangzara-retro-zine

A neighborhood zine on the disappearing corner shops — portraits, voices, and what a block loses when they close. Built as a decision-grade story deck for community, local readers.

nexu-io/open-design · 49 tokens

html-ppt-zhangzara-studio

A photography studio's portfolio-and-rate deck — the signature work, the process, and the packages that win the brief. Built as a decision-grade design craft deck for prospective clients.

nexu-io/open-design · 47 tokens

webgl-halftone-drift

A self-contained WebGL2 hero: a flowing field screened through a rotated halftone dot grid into a duotone print aesthetic; move the cursor to bend the drift.

nexu-io/open-design · 44 tokens