Agent skill

Induce

by jongwony in jongwony/epistemic-protocols

Several concrete cases at hand seem to share something no one has named yet: pin down what they have in common, checked against the goal the name serves.

MITAuto-check passed

Install Induce

skills CLI
$ npx skills add jongwony/epistemic-protocols --skill induce -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install jongwony/epistemic-protocols induce --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/jongwony/epistemic-protocols.git skills-src && mkdir -p .claude/skills && cp -r skills-src/periagoge/skills/induce .claude/skills/induce && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
induce
GitHub stars
173
Token cost
~7.9k tokens
SKILL.md length
1,193 words
Files
2 (incl. references)
Skills in repo
29
Repo updated
First seen
Licence
MIT

At a glance

Several concrete cases at hand seem to share something no one has named yet: pin down what they have in common, checked against the goal the name serves.

  • SKILL.md covers Definition, Mode Activation, Protocol and Rules
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Induce is an agent skill from jongwony/epistemic-protocols. Several concrete cases at hand seem to share something no one has named yet: pin down what they have in common, checked against the goal the name serves.

Its SKILL.md is about 7.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/round-composition.md`).

The repository describes itself as: Epistemic protocols for Claude Code — structure human-AI interaction quality at every decision point - https://epistemic-protocols.com. The licence is MIT.

Example prompts

  • “/induce”

What it can do on your machine

Read from SKILL.md and the folder at commit 69bb95b. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are lean).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Induce loads about 7.9k tokens when it runs, and up to ~8.6k if it reads all its reference files. Until then it costs about 40 tokens; SKILL.md has 1,193 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~40
When it runs · the whole SKILL.md, loaded when a task matches
~7.9k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~8.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from jongwony/epistemic-protocols at commit 69bb95b, republished under its MIT licence (© jongwony). 1,193 words, ~7,907 tokens.

Download SKILL.mdSave it as .claude/skills/induce/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
induce
description
Several concrete cases at hand seem to share something no one has named yet: pin down what they have in common, checked against the goal the name serves.

Periagoge Protocol

Crystallize in-process abstraction by reading the goal it serves across the live readings of the cases, through examples, with a working candidate moved until it fits the user's intent. Type: (AbstractionInProcess, AI, INDUCE, A) → CrystallizedAbstraction.

Definition

Periagoge (περιαγωγή): A dialogical act of turning an in-process abstraction toward its crystallized form: AI states the goal the abstraction serves and a working candidate, crosses every live reading of what the cases share with that goal through examples, and moves goal and candidate with the user until the abstraction matches the user's intent. The user reaches the abstraction by reading goal and readings against each other, with every alternative in view (the Greek dialectical vocabulary supplies the source terms).

lean
/-!
How to read this block. It is core Lean 4 and elaborates as written, and you are the model it is
written for: you read it, and by inference over the context you settle each element it leaves
open. Every `axiom` is one of those judgments — a black box to the contract, yours to make from
the material in front of you; its doc comment says what you judge there, and nothing in this
block decides it for you. Every `def`, `inductive`, and `structure` is fixed by the contract.
-/

/-! ── FLOW ──
Periagoge(A) → start(c) → induce(c, utterances), where c is the fused session context:
  start: scan where fewer than two cases or no essence → [not in process: not activated] → pass → sheet → Stop
  each utterance: [bears on nothing in the run: the sheet holds] pass → [stop: withdrawn | route: routed |
    confirm ∧ candidate live ∧ covered: crystallized | otherwise: the sheet again → Stop]
  no utterance: the sheet holds
-/

/-! ── MORPHISM ──
A
  → CrystallizedAbstraction
requires: in_process(A)                     -- judged at activation
deficit:  AbstractionInProcess              -- activation precondition
preserves: instance_set(A)                  -- the cases are read, never rewritten; a case you found is shown as yours
invariant: Goal Crossed with Readings through Examples, with Alternatives Maintained, over Single-Candidate Steering
invariant: setting a reading aside, an open item's disposition, and every closing are the person's; your readings settle none of them
-/

namespace Periagoge

/-! ── GROUND ──
The session primitive this contract reads.
-/

inductive Origin | person | assistant | external | peer | injected | unknown
  deriving DecidableEq

/-- A turn is who sent it and what it says. What the turn does — a statement, a request, an
    instruction, a report of what was observed — is read from its content, never stored here. -/
structure Turn (P : Type) where
  origin  : Origin
  content : P

abbrev Context (P : Type) := List (Turn P)

/-- An origin that may ground: the harness says who sent a turn, and that is all this admits on.
    The assistant's own turns, injected text, and turns of unknown origin ground nothing. -/
def Grounding := {o : Origin // o ≠ .assistant ∧ o ≠ .injected ∧ o ≠ .unknown}

/-- Any turn a person sent, whatever it does. -/
def Utterance (P : Type) := {e : Turn P // e.origin = .person}
def Response (P : Type) := {e : Turn P // e.origin = .assistant}
/-- A turn from outside the conversation: what a tool or the environment returned, or a peer's
    report. A person's account of what they observed is an utterance, read as such. -/
def Evidence (P : Type) := {e : Turn P // e.origin = .external ∨ e.origin = .peer}

def fuse {P : Type} (c : Context P) (u : Utterance P) : Context P := c ++ [u.val]

/-- One turn of the context, with the origin it grounds on. -/
structure Cite {P : Type} (c : Context P) where
  idx : Nat
  lt  : idx < c.length
  src : Grounding
  ok  : (c[idx]'lt).origin = src.val

/-- `admits` reads only who sent the cited turn; `supports` is the model's reading of what that
    turn says, including what it does — a statement, a request, a report of an observation. -/
structure Coord (P A : Type) where
  admits   : Grounding → Prop
  supports : Context P → Turn P → A → Prop

/-- `open_` may carry a candidate citation whose support is still short. -/
inductive Occ {P A : Type} (q : Coord P A) (c : Context P)
  | open_  (candidate : Option (Cite c))
  | filled (a : A) (src : Cite c) (allowed : q.admits src.src)
      (supported : q.supports c (c[src.idx]'src.lt) a)

/-- The same turn, cited from a longer context; what it supports is judged again against the
    context that now stands. -/
def Cite.lift {P : Type} {c : Context P} (s : Cite c) (t : Context P) : Cite (c ++ t) :=
  { idx := s.idx
    lt := by have := s.lt; simp; omega
    src := s.src
    ok := by rw [List.getElem_append_left s.lt]; exact s.ok }

/-! ── TYPES ── -/

noncomputable section

variable {P : Type}

/-- `A`, `AbstractionSeed`: the in-process state, read from the context — the cases, read and never
    rewritten; the essence intuition, which a routed colimit-shaped signal seeds only as that
    detection's reading; and any provisional name the person gave, which grounds the candidate's
    name without fixing it. -/
abbrev AbstractionSeed (P : Type) := Context P

/-- A concrete case: what it is, and where it sits. -/
structure Instance where
  content : String
  context : String
  deriving DecidableEq  -- elab: lets the sheet gather each case once

/-- **Your judgment**: an essence is sensed whose name, scope, or position is still unsettled, and
    at least two concrete cases can be read together. An abstraction already located — one awaiting
    comparison or validation — is not in process, and a set of cases and essence this session
    already crystallized or withdrew stays inactive. -/
axiom inProcess : Context P → Prop

/-- **Your record**: the cases you found that the person's words have not yet taken up. The next
    sheet opens with them, marked as found by you, so the person sees them before their next turn;
    they never join the cases silently. -/
axiom found : Context P → List Instance

/-- **Your judgment**, made afresh on every pass: the goal — what the abstraction is for — as it now
    stands. Where the person's words state it, it is their words, quoted; otherwise it is your
    reading, marked as yours. It moves: a turn that narrows or widens it moves it, on the scope its
    words reach. -/
axiom goal : Context P → String

/-- One reading of what the cases share. -/
abbrev Reading := String

/-- `(N, Rule)`: the working candidate — a name and a rule, the reading the rule is read off, and
    the label it was grounded on. The name is delivered with the goal, the rule, and the examples
    the rows drew: it locates the abstraction and returns the person to those cases. -/
structure Candidate where
  name       : String
  rule       : String
  reading    : Reading
  labelBasis : Option String

/-- **Your proposal**, from the first sheet on: the working candidate, with every move the person
    made since — a rename, a rule correction, a move to another reading, a merge. -/
axiom candidate : Context P → Candidate

/-- **Your judgment**, made afresh on every pass: every reading of what the cases share drawn in this
    activation, the readings the person added included. A reading you would no longer hold stays
    here: dropping it is your proposal, shown in the ledger and among your contrary grounds, until
    the person sets it aside. A merge the person makes is a reading; a reading you judge the same
    across passes keeps its name. A reading the person set aside comes back within the activation
    only through their own words (`Reopened`), never as your proposal. -/
axiom readings : Context P → List Reading

/-- **Your judgment**: the cited turn sets reading `r` aside, on this ground — their reason, carried
    verbatim — whatever form the turn takes. -/
axiom SetAsideSupported : Reading → Context P → Turn P → String → Prop

/-- A reading is set aside only by the person's turn. -/
def setAsideCoord (r : Reading) : Coord P String :=
  { admits := (·.val = .person), supports := SetAsideSupported r }

/-- **Your reading**: the person's setting-aside of `r`; `open_` until one reaches it. -/
axiom setAside : (c : Context P) → (r : Reading) → Occ (setAsideCoord (P := P) r) c

def filledValue {A : Type} {q : Coord P A} {c : Context P} : Occ q c → Option A
  | .open_ _     => none
  | .filled a .. => some a

/-- **Your judgment**: the person's later words name reading `r` again after setting it aside; it
    returns with their ground shown beside it. -/
axiom Reopened : Context P → Reading → Bool

/-- The readings still in play: a reading leaves only by the person's setting-aside, and returns
    only by their words. -/
def live (c : Context P) : List Reading :=
  (readings c).filter (fun r => (filledValue (setAside c r)).isNone || Reopened c r)

/-- Every reading the person set aside, with their ground. -/
def setAsideReadings (c : Context P) : List (Reading × String) :=
  (readings c).filterMap (fun r => (filledValue (setAside c r)).map (r, ·))

/-- An example named by a phrase that carries the feature being judged, never by a bare number. -/
structure Example where
  phrase : String
  source : Instance

/-- One row of the cross view: what the reading becomes against the goal — the check it yields —
    an example it catches and one it misses, and where the working candidate sits on it. -/
structure Row where
  againstGoal   : String
  catches       : Example
  misses        : Example
  candidateHere : String

/-- **Your judgment**: the row for reading `r`. Choose examples that separate the goal and the
    readings rather than ones every reading treats alike, drawn from the person's own domain: pair
    the cases that align most readily, not the most distant, since distance is what a separating
    example is for; align what they carry slot by slot from the cases themselves; and draw a case
    that tells readings apart. A row's examples stay as the last sheet showed them until a move of
    the person's reaches them — a swap, a move of the goal, the candidate, or the reading they cross,
    a correction, a case they brought; an example you would change otherwise is your proposal in the
    ledger, not a swap. -/
axiom row : Context P → Reading → Row

/-- The cross view: every live reading with its row. -/
def crossView (c : Context P) : List (Reading × Row) := (live c).map (fun r => (r, row c r))

/-- A case unfolded on the sheet, a few lines: what happened, what was seen and what was not, how
    it surfaced, and who brought it. -/
structure CaseUnfolding where
  happened  : String
  seen      : String
  unseen    : String
  surfaced  : String
  broughtBy : String

/-- **Your reading** of case `i`, unfolded. -/
axiom unfoldCase : Context P → Instance → CaseUnfolding

/-- Every case the cross view uses, once each. -/
def rowCases (c : Context P) : List Instance :=
  ((crossView c).flatMap (fun x => [x.2.catches.source, x.2.misses.source])).eraseDups

/-- The cases section of the sheet: every case the cross view uses, unfolded, so the person never
    leaves the sheet to see one. -/
def casesSection (c : Context P) : List (Instance × CaseUnfolding) :=
  (rowCases c).map (fun i => (i, unfoldCase c i))

/-- The candidate is read off a reading still in play. -/
def CandidateLive (c : Context P) : Prop := (candidate c).reading ∈ live c

open Classical in
/-- The candidate the sheet shows: only while its reading is in play. Where the person set that
    reading aside, you propose a candidate on a live reading; where none is live, the sheet shows
    none. -/
def shownCandidate (c : Context P) : Option Candidate :=
  if CandidateLive c then some (candidate c) else none

/-- **Your reading**: what the person said is still missing, each point in their words. -/
axiom missing : Context P → List String

/-- What a run can still owe at its end, tagged by what it is. -/
inductive OpenItem
  | reading (r : Reading)
  | question (q : String)

/-- The live readings the candidate does not take, and what the person said is still missing. -/
def openItems (c : Context P) (taken : Option Reading) : List OpenItem :=
  ((live c).filter (fun r => decide (some r ≠ taken))).map .reading ++ (missing c).map .question

inductive OpenDisposition
  | nonblocking
  | deferred

/-- **Your judgment**: the cited turn disposes of item `i` this way — not blocking where the closing
    turn takes the run with the item shown open, deferred where it routes the item to later work
    by name or unambiguous reference beside deferral words. Ambiguous deferral words defer
    nothing. -/
axiom DispositionSupported : OpenItem → Context P → Turn P → OpenDisposition → Prop

/-- An open item is disposed of only by the person's turn. -/
def dispositionCoord (i : OpenItem) : Coord P OpenDisposition :=
  { admits := (·.val = .person), supports := DispositionSupported i }

/-- **Your reading**: how item `i` stands; `open_` where no turn of the person's covers it. -/
axiom disposition : (c : Context P) → (i : OpenItem) → Occ (dispositionCoord (P := P) i) c

/-- A line of the sheet, named as the sheet shows it. -/
abbrev Entry := String

/-- **Your reading**: the lines the sheet shows as the context now stands. -/
axiom entries : Context P → List Entry

/-- Who first put a value forward, kept apart from how it came to stand. -/
inductive Proposer | ai | person

/-- **Your reading**: the position of the turn that first put forward what `e` holds now. -/
axiom introducedAt : Context P → Entry → Nat

def proposer (c : Context P) (e : Entry) : Proposer :=
  match c[introducedAt c e]? with
  | some ⟨.person, _⟩ => .person
  | _                 => .ai

/-- How a value came to stand: the person's turn set it; it is yours and still proposed; or a
    confirm adopted yours. -/
inductive Standing | set | proposed | adopted

/-- **Your reading**: the person's turn set what `e` holds now, on the scope their words reach. -/
axiom setByPerson : Context P → Entry → Bool

def standing (c : Context P) (e : Entry) : Standing := if setByPerson c e then .set else .proposed

structure Provenance where
  entry    : Entry
  proposer : Proposer
  standing : Standing

def provenance (c : Context P) : List Provenance :=
  (entries c).map (fun e => ⟨e, proposer c e, standing c e⟩)

/-- A confirm adopts what was still proposed. -/
def adopt (p : Provenance) : Provenance :=
  match p.standing with
  | .proposed => { p with standing := .adopted }
  | _         => p

/-- What a ledger line records. -/
inductive LedgerKind
  /-- the person's own move -/
  | personEdit
  /-- a value you re-drew because a move forces it -/
  | necessary
  /-- a value you re-drew, a case you found, or a reading you dropped, because you propose it -/
  | proposal

/-- One change since the last sheet. -/
structure LedgerLine where
  change : String
  cause  : Option Entry
  kind   : LedgerKind

/-- **Your record**: what the latest turn changed, the person's moves first. -/
axiom ledger : Context P → List LedgerLine

/-- The one move a sheet asks about; stopping and going elsewhere stay open on every sheet. -/
inductive Move
  | narrowGoal
  | widenGoal
  /-- move the candidate onto another reading -/
  | moveCandidate (to : Reading)
  /-- merge two readings into one -/
  | merge (a b : Reading)
  /-- swap an example on a reading's row for one that separates better -/
  | swapExample (r : Reading)
  | confirm
  /-- every reading drawn so far was set aside: name a distinction the readings missed, read
      another set of cases, or move the goal -/
  | exhausted

/-- **Your selection** of the move to ask about: the one whose answer would most change how goal and
    readings cross. Ask for a confirm only where the candidate fits the goal on every example shown;
    where an example could still separate it, that example comes first. -/
axiom selectMove : Context P → Move

open Classical in
/-- The move the sheet asks about. -/
def focus (c : Context P) : Move := if live c = [] then .exhausted else selectMove c

/-- **Your record**: the contrary grounds you showed before the person's answers — a reading the
    examples back better than the candidate's, a goal the candidate misses on an example shown, a
    case you would weigh otherwise — attached to the closing when the person closes over them;
    empty when there were none. Your reading never refuses a confirm: a confirm over it carries it
    as dissent. -/
axiom dissent : Context P → List String

/-- How the person ends the run. -/
inductive Closing
  /-- confirm the goal and the candidate as the sheet shows them -/
  | confirm
  /-- stop here -/
  | stop
  /-- go on to the protocol the person names -/
  | route (target : String)

/-- **Your judgment**: the cited turn closes the run this way, read against the context as it now
    stands, the order of its turns included: a closing said before a later sheet was presented was
    answered by that sheet, so a confirm reaches only the sheet it followed. Whatever form the turn
    takes, a move, a correction, or a rename closes nothing; "not yet" keeps the run open. -/
axiom ClosingSupported : Context P → Turn P → Closing → Prop

/-- Only the person closes. -/
def closeCoord : Coord P Closing :=
  { admits := (·.val = .person), supports := ClosingSupported }

/-- **Your reading**: the person's closing; `open_` until one reaches it. -/
axiom closing : (c : Context P) → Occ (closeCoord (P := P)) c

/-- **Your judgment**, the adoption condition: everything a confirm would take was shown on the sheet
    the confirm answered — the goal with who set it, the candidate, every live reading's row, every
    case the rows use unfolded, the readings set aside with their grounds, every case with who
    brought it — together with your
    contrary grounds. A confirm adopts the goal as shown. Where anything would be taken unseen, the
    sheet is drawn again with the whole basis. -/
axiom Covered : Context P → Prop

/-- **Your judgment**: the latest utterance bears on this run — a move, a correction, a case, a
    rename, a closing, a question about the sheet. An utterance about other work leaves the run as
    it stands. -/
axiom Reaches : Context P → Prop

/-- `CrystallizedAbstraction`: the person's confirm over a covered sheet whose candidate is read off
    a live reading. -/
structure CrystallizedAbstraction (P : Type) where
  context    : Context P
  goal       : String
  candidate  : Candidate
  crossView  : List (Reading × Row)
  cases      : List (Instance × CaseUnfolding)
  setAside   : List (Reading × String)
  openTrace  : List OpenItem
  dissent    : List String
  provenance : List Provenance

/-- What a run established when the person stops it or goes elsewhere, so a later run resumes from
    it; the goal, the candidate, and the readings stand as your reading. -/
structure Withdrawn (P : Type) where
  context   : Context P
  goal      : String
  candidate : Candidate
  setAside  : List (Reading × String)
  openTrace : List OpenItem
  dissent   : List String

inductive Outcome (P : Type)
  | notActivated (c : Context P)
  | crystallized (r : CrystallizedAbstraction P)
  /-- the person stopped -/
  | withdrawn    (r : Withdrawn P)
  /-- the person named another protocol: proceed to it, citing their words -/
  | routed       (target : String) (r : Withdrawn P)
  | holding      (c : Context P)

/-! ── MODE STATE ──
Λ is the fused context and nothing else; every reading above is taken from it. No gate, stage, or
count is stored: each sheet is judged afresh from the whole context.
-/

abbrev Mode (P : Type) := Context P

/-! ── PHASE TRANSITIONS ──
A step is one arm of a structural recursion over the person's utterances. A pass is the silent
work: the reads the run needs enter the context, then the pass's record — the run judged afresh.
`respond` presents the sheet; `declare` is the closing declaration of the trace.
-/

/-- **Your reads** at activation: where fewer than two cases are in hand or no essence is sensed,
    the session context and the person's artifacts scanned for cases that could be read
    together. -/
axiom scan : Context P → List (Evidence P)

/-- **Your reads** for a pass: the cases' own context by artifact read and search, examples from the
    person's domain, and an external fetch where that domain lies outside their artifacts. -/
axiom collect : Context P → List (Evidence P)

/-- **Your record** of a pass, once its reads have entered the context: the run as judged — the goal,
    the candidate, the readings and their rows, the readings set aside, provenance, the ledger, your
    contrary grounds, and the move. A record grounds nothing. -/
axiom passRecord : Context P → List (Response P)

def pass (c : Context P) : Context P :=
  let c₁ := c ++ (collect c).map (·.val)
  c₁ ++ (passRecord c₁).map (·.val)

/-- The crystallized abstraction; the context ends in the declaration. -/
def crystallize (declare : Context P → Response P) (c : Context P) : CrystallizedAbstraction P :=
  { context := c ++ [(declare c).val], goal := goal c, candidate := candidate c,
    crossView := crossView c, cases := casesSection c, setAside := setAsideReadings c,
    openTrace := openItems c (some (candidate c).reading), dissent := dissent c,
    provenance := (provenance c).map adopt }

/-- What the run established; no candidate was taken, so every live reading stays open. -/
def withdraw (declare : Context P → Response P) (c : Context P) : Withdrawn P :=
  { context := c ++ [(declare c).val], goal := goal c, candidate := candidate c,
    setAside := setAsideReadings c, openTrace := openItems c none, dissent := dissent c }

open Classical in
/-- `respond` presents the sheet the Protocol section describes under "The sheet": the
    candidate as `shownCandidate` gives it, the cross view (`crossView`), the cases as `casesSection`
    unfolds them, ending at the one move (`focus`). -/
def induce (respond declare : Context P → Response P) :
    Context P → List (Utterance P) → Outcome P
  | c, []      => .holding c
  | c, u :: us =>
    let c' := fuse c u
    if ¬ Reaches c' then induce respond declare c' us
    else
      let c₁ := pass c'
      match filledValue (closing c₁) with
      | some .stop      => .withdrawn (withdraw declare c₁)
      | some (.route t) => .routed t (withdraw declare c₁)
      | some .confirm   =>
        if CandidateLive c₁ ∧ Covered c₁ then .crystallized (crystallize declare c₁)
        else induce respond declare (c₁ ++ [(respond c₁).val]) us
      | none => induce respond declare (c₁ ++ [(respond c₁).val]) us

open Classical in
def start (respond declare : Context P → Response P) (c : Context P)
    (us : List (Utterance P)) : Outcome P :=
  let c₁ := c ++ (scan c).map (·.val)
  if ¬ inProcess c₁ then .notActivated c₁
  else
    let c₂ := pass c₁
    induce respond declare (c₂ ++ [(respond c₂).val]) us

/-! ── CONVERGENCE ──
crystallized, withdrawn, routed — the three closings of `Outcome`, each the person's; the trace each
carries is its structure's fields, and at a withdrawal they stand as your reading.
-/

/-! ── TOOL GROUNDING ──
What each operation of this contract does. An interaction with the person is one of two kinds,
and its kind fixes how it continues once its text is presented.
-/

inductive Interaction | constitution | extension

inductive Continuation | stop | proceed

inductive Annot | sense | observe | track | transform | dispatch | interaction (kind : Interaction)

/-- Every interaction presents its text; a Constitution then stops for the person's turn, and an
    Extension proceeds. -/
def Interaction.realization : Interaction → Continuation
  | .constitution => .stop
  | .extension    => .proceed

inductive Op | detect | scan | absorb | collect | judge | record | sheet | readTurn | declare
             | converge | seam

def grounding : Op → Annot × String
  | .detect   => (.sense, "Internal analysis: the deficit over the utterance and the context")
  | .scan     => (.observe, "artifact read, artifact search (conditional: fewer than two cases, or no essence)")
  | .absorb   => (.interaction .extension, "a routed colimit-shaped signal as activation ground, its cited essence and locator shown as the detection's reading")
  | .collect  => (.observe, "artifact read, artifact search; external fetch (conditional: the domain lies outside the person's artifacts), its URL cited where used")
  | .judge    => (.sense, "Internal analysis: the whole run afresh against the whole context")
  | .record   => (.track, "record: the pass's record")
  | .sheet    => (.interaction .constitution, "the sheet, then one move (mandatory)")
  | .readTurn => (.sense, "Internal analysis: the new turn read against the fused context as it now stands")
  | .declare  => (.interaction .extension, "at a withdrawal or a route, the trace as your reading")
  | .converge => (.interaction .extension, "at a crystallization, the trace and the dissent")
  | .seam     => (.interaction .extension, "at a chain the person declared, proceed to the named protocol citing that turn")

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

end

end Periagoge

Mode Activation

/induce remains directly invocable; AI-guided activation stays silent and follows inProcess. An abstraction already located — one awaiting comparison or validation — belongs to other work.

Bind the seed from an explicit argument first, then the most recent cluster of cases, then a surfaced essence. Where no essence is sensed, show the scan result and invite the user to name what feels in process; where the scan finds no second case, say what was searched and invite one. Prior-session recall may seed examples or neighbouring abstractions but never settles crystallization.

Protocol

The sheet

Every turn shows one sheet, in everyday language. It opens with any case you found since the last sheet, marked as found by you, so the user meets it before their next turn; a found case stays yours until the user's words take it up, and a confirm that covers it adopts it as yours.

Then the goal: what the abstraction is for. Where the user has said it, quote their words; otherwise give your reading and mark it as yours. Under it, the working candidate — a name and a rule — from the first sheet on, always on a reading still in play: where the user sets that reading aside, propose a candidate on a live one. Both move: the run's work is moving the goal and the candidate until the abstraction matches what the user means.

Then the cross view, one row per live reading. Each row says what the reading becomes against the goal — the check it would give you — an example it catches and an example it misses, and where the candidate sits on that reading. Name every case by a short phrase that carries the feature being judged. Then a cases section: every case the rows use, unfolded in a few lines — what happened, what was seen and what was not, how it surfaced, who brought it — so every case is read on the sheet itself. Unfold a new or changed case again; an unchanged one may be folded as the same as the last sheet; unfold them all on the sheet a confirm would answer. The full list of cases with who brought each, and the readings the user set aside beside the user's own words, appear when they change, when reconsidering needs them, and on the sheet a confirm would answer. Mark every value as the user's or yours. Label each field with the question it answers, in the user's words, and say each term this file uses as the concrete question it stands for in the user's material. Draw the fields with the structure the host renders — headings, tables, lists.

Under the sheet, the ledger of what the last turn changed: the user's moves first, then what you re-drew because of them, each marked as forced by that move or as your proposal. A reading you would no longer hold stays in the cross view until the user sets it aside; dropping it is your proposal, shown in the ledger. A row's examples stay as the last sheet showed them until a move of the user's reaches them; an example you would change otherwise is likewise a proposal in the ledger. Then your contrary grounds, each beside the value it bears on.

Then one move to ask about: narrow or widen the goal, move the candidate onto another reading or merge two readings, swap an example for one that separates better, or confirm. Say what each way of answering does to the goal and the candidate. Where every reading was set aside, say that every reading drawn so far was set aside on the grounds shown, and ask whether to name a distinction the readings missed, read another set of cases, or move the goal. Stopping, and going on to a protocol the user names, stay open on every sheet.

Show full SKILL.md (435 more words)Show less

The user may answer in their own words, and one answer may reach several parts of the sheet. A move reaches what its words reach. An utterance about other work leaves the sheet as it stands; the sheet returns when the user comes back to the run. A reading leaves the cross view only by the user's words setting it aside, and returns when the user names it again, with their earlier ground shown beside it. Only the user closes the run: confirming, stopping, or going on to a protocol they name. A confirm takes the goal and the candidate as the sheet it followed showed them, with the whole basis in view, and only while the candidate's reading is still in play; where something it would take was never shown, draw the sheet again with the whole basis, and a confirm said before that later sheet does not reach it.

At the close, declare the trace before proceeding: the goal and who set it, the candidate, the cross view with its cases unfolded, the readings set aside with their grounds, every case with who brought it, and the open trace. The open items are the live readings the candidate does not take and what the user said is still missing. Each open item takes its disposition from the user's closing turn: not blocking where the turn takes the run with the item shown open, deferred where it names the item for later work beside deferral words. An item no turn covered is shown as undisposed. At a withdrawal, show the goal, the candidate, and the readings as your reading, not as established.

Read references/round-composition.md before composing when terminology must remain stable, wording must be carried unchanged, material belongs to another round or trace, or the order of the sheet bears on where a sentence sits.

Rules

  • Recognition over Recall: Present the sheet and one move with anticipatable consequences, and yield for the user's judgment.
  • Goal and candidate first, tested against each other: Open every sheet with the goal and a working candidate, and test the candidate against the goal through examples on every row. The goal and the alternatives beside the candidate are what keep the user's judgment their own.
  • Round composition: Compose each round in everyday language, keep each judgment beside its evidence and next-move implication, and place analysis before the move.
  • Form feedback: Derive each round's density from the current request; carry an explicit form instruction until countermanded. Change the form directly. Elements fixed elsewhere remain fixed; state what changed and, where the instruction overlaps a fixed element, what stays and why.

© jongwony, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file (references) in periagoge/skills/induce of jongwony/epistemic-protocols.

  • SKILL.md
  • references/round-composition.md

Open the folder on GitHubat commit 69bb95b

Compare with similar skills

Induce next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Induce compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Induce this skilljongwony/epistemic-protocols173—~7.9kAutomated safety check: PassMIT
Share CaseNeuroAIHub/BrainPilot1k—~1.9kAutomated safety check: PassAGPL-3.0
Case Reviewsickn33/agentic-awesome-skills47k1 repos~1.6kAutomated safety check: PassMIT
Deslop Shared Libsgarrytan/gstack136k—~3.3kAutomated safety check: NotesMIT
Case Reviewzhaoxuya520/reverse-skill40k1 repos~1.6kAutomated safety check: WarnMIT
Relsa Severity AssessmentK-Dense-AI/scientific-agent-skills48k1 repos~5.2kAutomated safety check: NotesMIT

Similar skills

  • Share Case

    NeuroAIHub/BrainPilot

    One-command community case sharing — capture research context from your session and submit to GitHub Discussions

    1k GitHub stars~1.9k tokensUpdated 5 days ago
    Auto-check passed
  • Case Review

    sickn33/agentic-awesome-skills

    Quality-gate review of a reverse-engineering or assessment case package: scope readiness, Evidence-to-Finding-to-Path traceability, work-item coverage, timeline consistency, and artifact hashes.

    47k GitHub starsUsed in 1 repo~1.6k tokens
    SecurityAuto-check passed
  • Deslop Shared Libs

    garrytan/gstack

    Find worthwhile shared-code extractions in recent work. An agent skill from garrytan/gstack.

    136k GitHub stars~3.3k tokensUpdated today
    Writing & ContentAuto-check: notes
  • Case Review

    zhaoxuya520/reverse-skill

    Reviews a reverse-skill case package for scope readiness, Evidence to Finding to Path traceability, work item coverage, timeline references, and optional artifact hash integrity before report handoff.

    40k GitHub starsUsed in 1 repo~1.6k tokens
    SecurityAuto-check: warnings
  • Relsa Severity Assessment

    K-Dense-AI/scientific-agent-skills

    Supports multivariate severity assessment and exploratory endpoint-time score forecasting for laboratory animal studies using the RELSA (RELative Severity Assessment) score and ARIMA-based foRcast…

    48k GitHub starsUsed in 1 repo~5.2k tokens
    Data & AnalyticsAuto-check: notes
  • Clinical Case Report

    nexu-io/open-design

    Structured medical case presentation for clinical rounds, conferences, and documentation.

    100k GitHub stars~2.2k tokensUpdated today
    Auto-check passed

More from jongwony/epistemic-protocols

All 29 skills in this repo
  • Outcome

    jongwony/epistemic-protocols

    This skill should be used when the user asks to "run the outcome eval", "paired bare vs protocol", "which decisions did the protocol surface", "count what the AI asked or presented", "does /inquire…

    173 GitHub stars~1.3k tokensUpdated yesterday
    Auto-check: notes
  • Realize

    jongwony/epistemic-protocols

    This skill should be used when the user asks to "run the eval", "test whether the protocol actually works at runtime", "check type realization", "measure protocol fulfillment", "run the…

    173 GitHub stars~3.3k tokensUpdated yesterday
    Auto-check: notes
  • Verify

    jongwony/epistemic-protocols

    This skill should be used when the user asks to "verify protocols", "check consistency before commit", "validate definitions", "run pre-commit checks", "verify soundness", or wants to ensure…

    173 GitHub stars~1.4k tokensUpdated yesterday
    Auto-check passed
  • Encapsulation

    jongwony/epistemic-protocols

    This skill should be used when the user asks to "audit plugin encapsulation", "check self-containment semantics", "find contributor-knowledge assumptions", or invokes /encapsulation.

    173 GitHub stars~2k tokensUpdated yesterday
    Auto-check passed
  • Formal Review

    jongwony/epistemic-protocols

    This skill should be used when the user asks to "formal review", "formal lens review", or invokes /formal-review.

    173 GitHub stars~3.5k tokensUpdated yesterday
    Auto-check: notes
  • Recollect

    jongwony/epistemic-protocols

    The user vaguely recalls something discussed before but cannot name it — one session, or a line of work, topic, or settled concept across several: find it in past records to recognize.

    173 GitHub stars~8.7k tokensUpdated yesterday
    Auto-check passed

Questions about Induce

What does Induce do?

Several concrete cases at hand seem to share something no one has named yet: pin down what they have in common, checked against the goal the name serves. Induce is an agent skill from jongwony/epistemic-protocols. Several concrete cases at hand seem to share something no one has named yet: pin down what they have in common, checked against the goal the name serves.

How do I install Induce in Claude Code?

Run `npx skills add jongwony/epistemic-protocols --skill induce -a claude-code`. Or copy the skill folder (periagoge/skills/induce in jongwony/epistemic-protocols) into .claude/skills/induce in your project. Claude Code loads it when a task matches its description.

How do I install Induce in Codex?

Run `npx skills add jongwony/epistemic-protocols --skill induce -a codex`. Or copy the skill folder (periagoge/skills/induce in jongwony/epistemic-protocols) into .agents/skills/induce in your project. Codex loads it when a task matches its description.

Can I use Induce in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add jongwony/epistemic-protocols --skill induce -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/induce, .gemini/skills/induce, .github/skills/induce and .opencode/skills/induce in your project.

What does Induce need to run?

SKILL.md names no scripts, command-line tools or credentials: Induce is instructions for the agent only.

Does Induce access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Induce safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Induce use?

Induce is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Induce use?

About 7.9k tokens (SKILL.md is roughly 32k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 684 tokens, read only when the agent opens those files.

What are the alternatives to Induce?

Skills that share tags, products or a category with Induce: Share Case (NeuroAIHub/BrainPilot, 1k stars), Case Review (sickn33/agentic-awesome-skills, 47k stars), Deslop Shared Libs (garrytan/gstack, 136k stars) and Case Review (zhaoxuya520/reverse-skill, 40k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Induce?

jongwony (a GitHub user) maintains it in jongwony/epistemic-protocols, which has 173 GitHub stars. The repository holds 29 skills in this directory. The repository was last updated on October 6, 2026.

Source: jongwony/epistemic-protocols on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.