Hyphegesis Protocol

SkillDev tools

Conduct method before object-level work. Fires when the work needs several moves in non-trivial order. Type: (MethodUnderdetermined, Hybrid, CONDUCT, WorkProspect × MoveGround) → ConductedMethod

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Hyphegesis Protocol skill

What this skill tells your AI

The instructions your AI receives, as published by jongwony/epistemic-protocols in hyphegesis/skills/conduct/SKILL.md and read by ahel’s review.

Conduct how a session's epistemic work will be carried out — the order, independence, reconciliation, termination, and routing of its cognitive moves — when that method is underdetermined before object-level cognition begins. The morphism is design THEN hand off: Hyphegesis designs a conduct topology over the moves it identifies and emits a method plan with in-session checkpoints, then stops; the substrate executes the moves. Type: (MethodUnderdetermined, Hybrid, CONDUCT, WorkProspect × MoveGround) → ConductedMethod.

Definition

Hyphegesis (ὑφήγησις: a leading-the-way, guiding from just ahead): A dialogical act of conducting a session's epistemic work — deciding how its multiple cognitive moves relate in order, independence, reconciliation, termination, and routing — when the method is underdetermined while the goal is clear. The protocol's lexical verb is /conduct. It activates only when the work needs two or more moves whose conduct is non-trivial (single-move work relays to that one protocol), designs the conduct topology draft-first — filling every axis·region with a reasoned value shown beside the alternatives it displaces, and proposing the region cut itself with what it read to cut that way and the standing affordance to replace it, then opening a value gate only where the user points — and registers an in-session checkpoint when a constitutive decision's evidence does not yet exist (synthesis output shape generally; cell membership in the decompose-recovery instance), surfaces substrate feasibility as a handoff annotation, compiles a decision-typed Recognition brief into every checkpoint, assembles a cross-cutting trace contract (its disclosure overlay over the five axes — residuals, degradations, coverage caps, never silent), and hands off a method plan that the substrate — not Hyphegesis — executes.

── FLOW ──
Hyphegesis(WP) → (Λ.work_pointer := the navigation block the accumulated context supplies, None otherwise) → GroundPointer[unreachable ∨ support-integrity failure: relay(handoff unreadable)(extension) → deactivate] → MethodBrief(WP) → guard[relay-test, anti-self-application] →
  [single-move ∨ trivial-conduct: relay-route(extension) → deactivate] |
  [multi-move ∧ non-trivial:
    Qc(brief, warrant) → A_w → [Accept: continue | Amend(WP'): Λ.work_prospect := WP' → re-enter Phase 0 over WP', rebinding work_pointer against the corrected prospect] →
    MoveId(WP × MG) → Sc(MoveSet) → A_s → [Confirm(MS'): |MS| ≥ 2 → MS | |MS| < 2 → the relay terminals PHASE TRANSITIONS enumerates, deactivate] →
    DraftTopology(MS, WP) → CT_draft →
    loop( DraftSurface(CT, constituted_axes, CT_draft) → DraftGate → Stop → DM →
          [Sufficient: exit
           | Open(sites): [CutSite(p) ∈ sites: ReviseCut(p) → CarryConstituted → ReDraft → re-present (the round ends here — no value gate opens over region names about to be replaced)
                           | otherwise: for each site in impact/leverage-first order: AxisGate(site) → Stop → VM → update(CT, constituted_axes) → (VM = Sufficient: exit, or re-present first when this round re-filled a slot the surface has not shown | VM carrying a partition ends the round: ReviseCut → CarryConstituted → ReDraft → re-present | else: next site) — and only when the sites run out with no such exit: ReDraft(every unconstituted slot, against the values just constituted) → re-present]   -- no arm runs ReDraft twice; an arm that exits runs none, since the exit is defined as preceding it
          ] ) until Sufficient →
    FinalizeTopology(CT, constituted_axes, CT_draft) → (CT, residuals, topology_degradations) → AssignMoves(MS, CT) → move_assignment → RegisterCheckpoints(WP, CT) → checkpoints →
    SubstrateFeasibility(CT) → SH → AnnotateHandoff(CT) → CarryPointer → CompileCheckpointBrief(checkpoints, WP, CT, MS) → RecordDegradation(SH, CT) → degradations → AssembleTraceContract(residuals, degradations, derived_coverage_limits(CT), derived_termination_grounds(CT, move_assignment)) → TC → converge(conduct trace: move assignment + handoff annotations + checkpoint briefs + trace contract, one surfacing op per element in TOOL GROUNDING) → handoff(ConductedMethod) → ConductedMethod ]

── MORPHISM ──
WorkProspect × MoveGround
  → brief(method, conduction_warrant)         -- infer the work prospect's method-brief; judge whether conduction is warranted
  → guard(relay_test, anti_self_application)  -- single-move work relays to that one protocol; Hyphegesis does not conduct Hyphegesis
  → identify(moves)                           -- candidate cognitive moves read off the move ground, presented for Recognition (`Recognition over Recall`)
  → select(moves)                             -- user confirms the move set via Cognitive Partnership Move (Constitution)
  → draft(conduct_topology)                   -- fill every axis·region with a reasoned value shown beside the alternatives it displaces, and propose the region cut carrying what was read to cut that way and the affordance to replace it — the cut's half differs because partitions are not enumerable, not because it is exempt; so the whole method is legible before any of it is answered
  → design(conduct_topology)                  -- the user points at the slots the draft got wrong; each pointed-at slot opens its own gate, highest-leverage first among them, and a pointed-at cut is settled alone because it re-keys the rest. Every value the user constitutes is pinned; the draft re-fills around it. Edge-local over move-regions; FinalizeTopology replaces the current pass's residual/degradation products, and once the moves are placed by the arrow below, checkpoint registration replaces the checkpoint set from the current CT + WP. Deferred decisions whose evidence does not exist yet register there
  → assign(moves, topology) → move_assignment  -- place every selected move into a region of the resolved topology and into its slot under that topology's order; it is a field the emitted plan carries in its own right
  → annotate(substrate_feasibility)           -- per resolved topology, surface substrate realizability as a handoff annotation
  → carry(work_pointer)                      -- carry the navigation block the work arrived under onto the emitted artifact, whole and unchanged. The pointer travels; the record's contents do not, so the executing substrate and any later session reach the canonical record itself rather than a copy that could silently disagree with it
  → compile(checkpoint_briefs)                -- for every registered deferred decision, compile the decision-typed Recognition presentation contract the substrate executes there (structure, not content)
  → contract(trace_disclosure)                -- assemble the cross-cutting disclosure overlay: residuals + degradations + coverage caps + termination grounds (one per region whose resolved termination needs a stop parameter — until_goal_met(g), bounded_rounds(n), until_dry_ceiling(k), or an emergent value declaring needs_stop_ground — each read off the value that carries it); surfaced, never silent
  → handoff(conducted_method)                 -- emit the method plan + in-session checkpoints, then stop (substrate executes)
  → ConductedMethod
requires: method_underdetermined(WP)           -- runtime checkpoint (Phase 0)
deficit:  MethodUnderdetermined                -- activation precondition (Layer 1/2)
preserves: WP                                  -- work prospect read-only
invariant: Conduction over Substrate

── TYPES ──
WP     = WorkProspect: the work or goal facing object-level cognition, with its method (conduct plan) not yet determined
MG     = MoveGround: what this session affords as candidate moves — the accumulated session context, the documented deficit/resolution declaration of each protocol available to it, and the analysis passes and delegations the session itself affords
Move   = CognitiveMove { step: protocol invocation | analysis pass | delegation }
MS     = MoveSet: (WP × MG) → {Move₁ … Moveₙ}  -- MoveId yields n ≥ 2 under the warrant; a Phase 1 selection may reduce it, and |MS| < 2 is what the Phase 1 relay terminals handle
A_s    = SelectionJudgment ∈ {Confirm(MS')}
A_w    = BriefJudgment ∈ {Accept, Amend(WP')}   -- Amend carries the corrected prospect: this protocol is Hybrid, so the Phase 0 gate is where the AI-inferred WP is constituted
MethodBrief = AI-inferred summary of WP: { work_intent, expected_handoff, span }  -- span = invocation → the next planned /compact or /clear
Warrant = ConductionWarrant ∈ {warranted, relay}  -- warranted = moves ≥ 2 ∧ conduct non-trivial; relay = single-move ∨ trivial
MoveRegion = a contiguous sub-graph of moves sharing one conduct treatment; the partition over MS is PROPOSED with the draft (DraftTopology reads MS's non-uniformity and cuts accordingly, citing what it read) and REVISED by the user, who reaches that revision from either gate. Proposer and reviser are both surfaced: a proposed cut is a draft slot the user can open like any other, so proposing it constitutes nothing
axis   ∈ {order, independence, reconciliation, termination, routing}
Emergent(a) = a conduct value for axis a that the presented Gen set did not name, constituted at that axis·region's gate — the user's affordance, since a value the presented set did not name cannot be named by whoever is doing the presenting. It carries the obligation classes it falls under — relaxes_isolation, needs_stop_ground, crosses_span — declared with the value, because every downstream obligation below dispatches on the CLASS, not on a named value's identity; an emergent value declaring none carries none
  Gen(order)          ∈ {sequential_chain, parallel_fan, dependency_dag} ∪ Emergent(order)
  Gen(independence)   ∈ {isolated, shared} ∪ Emergent(independence)
  Gen(reconciliation) ∈ {aggregate, dialectic, adversarial_refute, synthesis} ∪ Emergent(reconciliation)
  Gen(termination)    ∈ {single_pass, bounded_rounds(n), until_dry_ceiling(k), until_goal_met(g)} ∪ Emergent(termination)   -- g ∈ {protocol_contract(ref), stated_condition(ref), resolution_required(resolver)}. The stop parameter travels INSIDE the value for every member that takes one, so whoever fills the slot carries it and no separate producer is needed. What a gate adds is the user's constitution, not the parameter. until_goal_met is no exception, and that is what makes the set uniform: a ground settled at fill time but left outside the value would have to be re-found at Phase 3 from a CT that does not hold it
  Gen(routing)        ∈ {return_to_user, chain_to_next, handoff_to_protocol(target), deepen_on_finding, handoff_to_span} ∪ Emergent(routing)  -- handoff_to_protocol carries the protocol it routes to INSIDE the value, so the handoff is dispatchable without a second lookup whoever filled the slot; handoff_to_span: the move/region output crosses the span wall to a future span that does not share this session's context
ResolvedValue⟨a⟩ = per-axis resolved value, axis-typed:
   ResolvedValue⟨reconciliation⟩ = RVᵣ = Gen(reconciliation) ⊕ Compose(RVᵣ, RVᵣ, op)   -- RVᵣ abbreviates this same type: a composite's operands are themselves resolved reconciliation values, so composites nest
   ResolvedValue⟨order⟩ = Gen(order);  ResolvedValue⟨independence⟩ = Gen(independence);  ResolvedValue⟨termination⟩ = Gen(termination);  ResolvedValue⟨routing⟩ = Gen(routing)
op     ∈ {⨾ sequential, ∥ parallel}             -- extensible at operator level
CT     = ConductTopology = Map(axis → Map(MoveRegion → ResolvedValue⟨axis⟩))
default(a) = ⟨order: sequential_chain, independence: isolated, reconciliation: synthesis, termination: single_pass, routing: return_to_user⟩[a]  -- the per-axis fallback, used for a slot the draft could not ground and by FinalizeTopology for any slot still unfilled. termination falls back to the one value needing no stop parameter, so Sufficient always yields an executable method; every other member arrives WITH its parameter, from the draft or from a gate alike, and the fallback never binds one with the parameter unset — which is the whole reason the fallback is single_pass
CT_draft = Map(axis → Map(MoveRegion → DraftSlot)) over the proposed cut  -- the whole topology filled before anything is asked. TOTAL over the cut's slots: every axis·region carries a DraftSlot, so accepting the draft always yields an executable method and no slot reaches the user blank. And CURRENT: whatever changes a slot's disposition leaves it holding a WHOLE candidate, and nothing takes a candidate the user has not been shown. A constituted slot's entry is the exception that proves it — that entry may sit stale precisely because nothing reads it while the pair is constituted, so the step that un-constitutes it is the step that owes it a fill
DraftSlot = { value: ResolvedValue⟨axis⟩, ground: Option(String), differential: Set(alternative × implication) }
   -- ground = Some(g): the reasoning that picked this value over the others, cited to what it read (the work prospect's own method brief, the move set, a value already constituted, a cut just revised). ground = None: nothing preferred any value, so the slot carries default(a) and says so — a materially different fact from a grounded fill, and the residual record keeps the two apart
alternatives(a) = the NAMED members of Gen(a) ∪ Emergent-affordance ∪ [a = reconciliation] Compose-affordance   -- fixed by the axis alone, so it is read off a rather than kept beside each slot's value
   -- one rule, applied twice: alternatives(a) ENUMERATES what is closed and carries an AFFORDANCE for each part that is open. Closed here is the named members of this axis's Gen set — every one of them, so the draft conceals no candidate it already analysed. Open on every axis is Emergent(axis), which Gen(axis) also contains and which the presenter by definition cannot name, so quantifying over Gen(axis) itself would demand the unnameable; the affordance to constitute an Emergent value travels instead. Open on reconciliation additionally is the composites, which nest, so naming them is as unmeetable as enumerating the partitions of MS — the affordance to COMPOSE travels there. Without that second one, the axis whose values reach furthest past its named set would be the axis whose draft can hide a whole kind of value, since a slot taken as drafted never opens the gate where the composites are surfaced
   -- differential states, for the alternative(s) that would most change the downstream plan, what changes if the slot goes that way. Bounded on purpose: naming all values is what keeps the taxonomy whole, and spending the differential where the plan actually turns is what keeps the draft readable. The full per-value trade-off unfolds at the gate the user opens
Site   = (axis × MoveRegion) ⊎ CutSite(partition: Option(Set(MoveRegion)))   -- a slot of the draft the user can point at. CutSite is the proposed region cut itself, and it CARRIES its revision the way every other answer here carries its payload: Some(p) supplies the cut to use, None says only that the proposed one is wrong and hands the next proposal back to the draft, citing what was rejected. Both settle alone — the round ends either way, because the region names are being replaced either way. Without the payload the cut branch would have no producer for the partition ReviseCut needs, and the branch forecloses the gate that would otherwise elicit it
DM     = DraftJudgment ∈ {Sufficient, Open(Set(Site))}   -- the draft gate's answer. Sufficient = take the topology as drafted; Open(sites) = these slots are wrong, open them. Silence is none of the two: it carries Stop and accepts nothing
AxisGate = { axis, region, options, drafted_value, basis, differential: Set(option × implication) }   -- opens only for a pointed-at site; options is the full Gen set (plus composites on reconciliation), drafted_value is what the draft had put there, and differential carries the per-value implications `Round composition` requires the gate to present. This is where the draft's bounded differential is repaid in full: the draft spends it on the alternative that most moves the plan, the opened gate carries every option's. The gate OPENS ON WHAT THE SURFACE SHOWED — so at a slot the user already constituted and has now re-opened, that is their own value and never the draft's pre-gate entry, which is the value they replaced; and where the surface's basis predates something they constituted earlier in the same round, the gate says so rather than passing it off as current
DraftTopology(MS, WP) = (proposed cut, CT_draft) -- read MS's non-uniformity for the cut and fill every slot over it. An AI reading presented for Recognition, never a selection: nothing here enters constituted_axes
ReDraft(CT_draft, constituted_axes) = CT_draft with every UNCONSTITUTED slot re-filled against what is now constituted, except that a value CarryConstituted just carried is the user's own and stays — what it displaces is a fact about the region now in force and is redrawn there — and every constituted slot's own entry left untouched -- untouched is not the same as holding what the user set: what the user set lives in CT under constituted_axes, and this entry stays at the pre-gate value the draft had put there, read by nothing while that pair is constituted. Re-grounding is why a decision made in one ROUND cannot leave a stale reason standing in the next. The round is the unit, not the gate — re-grounding between the gates of one round would move the ground out from under a round the user composed in one act, so a later gate carries that surface's basis and says so instead
ReviseCut(partition: Option(Set(MoveRegion))) = Some(p): replace the region keys of the four edge-local axes of the DRAFT with p — the draft's keys only, so CarryConstituted still reaches the constituted values under their old keys. None: hand the cut back to DraftTopology, which proposes a different one citing the rejected proposal as what it read. The None arm is reached from CutSite(None) ONLY, because pointing at the cut is what says the cut is wrong. Reorient(a, None) does not call this function at all — supplying no partition there asserts nothing about the cut, so that slot alone returns to the draft over the current keys and the round continues. Either way order's single {whole} key is untouched, so the constituted global sequence survives every re-cut. The Option is what lets a user reject a cut without having to author its replacement — the AI proposes, the user disposes, exactly as at every other slot
CarryConstituted(constituted_axes, partition) = for each (a, r) ∈ constituted_axes with a ≠ order whose region r the new cut replaces: DROP the pair from constituted_axes, and seed each replacement region overlapping r with the value Λ.topology holds at that pair as its DRAFT, ground = "carried from the value you set on r"
   -- the value is read from Λ.topology, since constituted_axes holds pairs and no values. ReviseCut re-keys the DRAFT, so that value is still under its old key when this step runs
   -- a replacement region may overlap SEVERAL old regions, and the values they carry may differ; a slot holds one. Which carried value it takes is NOT settled by a precedence rule here, for the reason TerminationGround gives for its own: the reading that picks it is over this session's context, and a rule written now would have to rank grounds this protocol cannot read into. What IS fixed is the disclosure — the ground names every carried value with the region it came from. The ground and not alternatives(a), which is typed over the Gen set alone and could not hold a carried Compose. So a merge can leave a choice of the user's un-taken, but never un-shown
   -- the value survives as a candidate the user can see and change, never as a constitution. That distinction is the whole guard: a silent survival would let a name the new cut happens to reuse read as already-constituted and let FinalizeTopology take a value belonging to the previous cut. Carrying it in the draft layer instead is what stops the user being asked the same axis once per re-cut
Checkpoint = { region: MoveRegion, decision: DeferredDecision, brief: Option(CheckpointBrief) }
DeferredDecision ∈ {SynthesisOutputShape} ∪ Emergent(DeferredDecision)  -- a non-axis decision whose deciding evidence exists only at the checkpoint
CheckpointSet = ordered Set(Checkpoint)  -- ordered by topology order between regions, with registration order breaking ties
CheckpointBrief ∈ {SynthesisBrief} ∪ Emergent(CheckpointBrief)  -- one realization named today; every realization presents pre-gate evidence refs, private-gap slots, and candidates with differential implications, each as Slot(T)
SynthesisBrief = { findings_ref: Map(Move → Slot(output_ref)), convergences: Slot(Set(finding)), divergences: Slot(Set(finding)), decision_axes: Slot(Set(decision_axis)), private_gap_slots: Set(GapSlot), fusion_candidates: Slot(Set(fusion_candidate)), output_shape_candidates: Slot(Set(OutputShape)) }  -- the Recognition presentation contract for SynthesisOutputShape
   Slot(T) = a typed placeholder compiled at design time and filled with T by the substrate at execution
   GapSlot = { category: a limit category the assigned move's protocol contracts to report, content: Slot(filled ∨ declined) }
OutputShape = the first-class unit the synthesis output is organized around  -- an open organizing unit, not an enum: the candidate space is never fixed in advance
checkpoint_set(WP, CT) = { Checkpoint(r, d, None) | r ∈ dom(CT[reconciliation]), d ∈ deferred_decisions(WP, CT, r) }
deferred_decisions(WP, CT, r) = the non-axis decisions this pass identifies for region r whose deciding evidence does not exist at design time and does exist at the checkpoint; SynthesisOutputShape ∈ it when CT[reconciliation][r] contains synthesis ∧ (CT[routing][r] ∈ {return_to_user, handoff_to_span} ∨ CT[routing][r] declares crosses_span)   -- keyed on the crosses_span obligation class as well as the named value, so an emergent routing that crosses the span wall registers the same checkpoint the named one does
compile_checkpoint_brief(c, WP, CT, MS) = the CheckpointBrief realization c.decision calls for, compiled from current CT + MS; SynthesisOutputShape → SynthesisBrief
SH     = SubstrateHandoff = { feasibility: Map(MoveRegion → FeasibilityAnnotation), annotations: Set(HandoffAnnotation) }
FeasibilityAnnotation = { realizable: Bool, basis: String }  -- the per-region substrate-realizability verdict; basis cites the inventory evidence it rests on
HandoffAnnotation = SpanExternalization(region: MoveRegion, record_surface: Option(String))   -- carries the externalization obligation a handoff_to_span region's seam declares; record_surface names the durable surface SubstrateFeasibility proposed, and is None exactly when that region was found unrealizable — the obligation still travels, beside the substrate_infeasible degradation the same pass records
span_externalization(r, CT, SH) = SpanExternalization(r, SH.feasibility[r].realizable ? Some(SH.feasibility[r].basis) : None)
VM     = ConductMove ∈ {Select(value), Compose(left: RVᵣ, right: RVᵣ, op), Reorient(axis, partition: Option(Set(MoveRegion))), Sufficient}   -- the answer at an OPENED axis gate. Compose carries BOTH operands the composite type needs, together with the operator; this MOVE is what writes Compose(left, right, op) into CT when the user makes it. A composite is a ResolvedValue like any other, so it can equally stand as a draft value and reach CT through Sufficient; the slot's ground says which happened   -- partition is the revised region cut the user's reframing supplies. The cut has one PROPOSER and one REVISER, both visible: DraftTopology proposes it (surfaced as CutSite, constituting nothing), and the user revises it. The user reaches that revision from either gate — pointing at the cut at the draft gate, or supplying a partition in this move at an opened one —

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
161
Forks
15
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
conduct-jongwony
Source
github.com/jongwony/epistemic-protocols