Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
42a6136
harness: the round-count boundary becomes a durable alignment-checkpo…
briansrls Sep 29, 2026
e7d85d0
roadmap: the alignment chain must reach the admitted root, carries th…
briansrls Sep 29, 2026
f73cd93
roadmap: the issue page renders the derived project path, and each pr…
briansrls Sep 29, 2026
8121138
harness: the prompt context model's first cut -- typed inputs, snapsh…
briansrls Sep 29, 2026
859d1b4
harness: guidance emits modeled prompt segments; the prose is their r…
briansrls Sep 29, 2026
cbfe011
harness+roadmap: close review 5358022153's carrier invariants -- exac…
briansrls Sep 29, 2026
d9a4dfb
roadmap: author harness-checkpoint-subject-planner under harness-recu…
briansrls Sep 29, 2026
2c2da12
roadmap: the checkpoint-probe planner -- pure obligation derivation o…
Sep 30, 2026
2640e62
harness: the attempt lineage owns its wire log; typed fork points; fa…
Sep 30, 2026
f5783c3
roadmap: root the dispatchable population under admitted-root programs
Sep 30, 2026
381e7c6
roadmap: the issue title link navigates; focus and topological sort a…
briansrls Sep 30, 2026
c073449
lane C: the pure checkpoint-subject/probe-obligation planner (review …
briansrls Sep 30, 2026
559722e
lane D: conversation persistence, typed fork points, fabric KV observ…
briansrls Sep 30, 2026
811dc0b
lane B: root the dispatchable population under admitted-root programs
briansrls Sep 30, 2026
d88a9f9
roadmap: type the session roster standing members explicitly (JsonValue)
briansrls Sep 30, 2026
536171f
roadmap: avoid the reserved profile binder in the session overlay (re…
briansrls Sep 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 34 additions & 10 deletions dag/gunbc/auth/profile_projection.dag
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,16 @@ fn profile_store_upsert_write(path: String, session: AuthenticatedSession, prior
}
}

// A SKIPPED ENTRY, NAMED: the never-blocks law still holds (one malformed file must not blank the
// picker), but the skip is now carried as data with its reason instead of being erased -- a
// missing-looking avatar must be distinguishable from a profile nobody published (review Cut B).
type ProfileStoreSkipped {
entry: String
reason: String
}

type ProfileStoreReadAll
= ProfileStoreRead { profiles: List<PrincipalProfile> }
= ProfileStoreRead { profiles: List<PrincipalProfile>, skipped: List<ProfileStoreSkipped> }
| ProfileStoreUnread { step: String, reason: String }

// THE READ-ALL, the picker roster's source: every decodable profile file in the store. A file
Expand All @@ -340,29 +348,45 @@ fn profile_store_read_all(layout: ProfileStoreLayout) -> ProfileStoreReadAll {
if !listing_result.success {
ProfileStoreUnread { step: "list", reason: listing_result.error }
} else {
let decoded = profile_store_decode_entries(layout: layout, entries: listing_result.entries, acc: [], skipped_acc: [])
ProfileStoreRead {
profiles: profile_store_decode_entries(layout: layout, entries: listing_result.entries, acc: [])
profiles: decoded.profiles,
skipped: decoded.skipped,
}
}
}

fn profile_store_decode_entries(layout: ProfileStoreLayout, entries: List<String>, acc: List<PrincipalProfile>) -> List<PrincipalProfile> {
fn profile_store_decode_entries(
layout: ProfileStoreLayout,
entries: List<String>,
acc: List<PrincipalProfile>,
skipped_acc: List<ProfileStoreSkipped>,
) -> { profiles: List<PrincipalProfile>, skipped: List<ProfileStoreSkipped> } {
match entries.first() {
Absent => acc
Absent => {
let done = { profiles: acc, skipped: skipped_acc }
done
}
Present { value: entry } =>
let next = if !ends_with(s: entry, suffix: ".json") {
acc
let stepped = if !ends_with(s: entry, suffix: ".json") {
{ profiles: acc, skipped: skipped_acc }
} else {
let read_result = Filesystem.Read(path: join([layout.root as String, "/", entry], ""))
if !read_result.success {
acc
{ profiles: acc, skipped: concat(skipped_acc, [ProfileStoreSkipped { entry: entry, reason: join(["read failed: ", read_result.error], "") }]) }
} else {
match principal_profile_of_json(text: read_result.content) {
ProfileFileMalformed { detail: _ } => acc
ProfileFileDecoded { profile: p } => concat(acc, [p])
ProfileFileMalformed { detail } => {
let skipped_file = { profiles: acc, skipped: concat(skipped_acc, [ProfileStoreSkipped { entry: entry, reason: join(["malformed: ", detail], "") }]) }
skipped_file
}
ProfileFileDecoded { profile: p } => {
let decoded_file = { profiles: concat(acc, [p]), skipped: skipped_acc }
decoded_file
}
}
}
}
profile_store_decode_entries(layout: layout, entries: entries.skip(n: 1), acc: next)
profile_store_decode_entries(layout: layout, entries: entries.skip(n: 1), acc: stepped.profiles, skipped_acc: stepped.skipped)
}
}
15 changes: 14 additions & 1 deletion dag/gunbc/harness/harness_cli.dag
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import std.measure { TokenCount, token_count, token_count_value, Second, second,
import std.process { ProcessExit, ExitSuccess, ExitFailure }
import gunbc.harness.harness_tool { HarnessToolEnvironment }
import gunbc.harness.harness_turn {
HarnessTurnConfig, HarnessTurnOutcome, TurnProviderStopped, TurnCompletedByArtifact, harness_tool_contract_wire,
HarnessTurnConfig, HarnessTurnOutcome, TurnProviderStopped, TurnCompletedByArtifact, TurnAlignmentCheckpointDue, harness_tool_contract_wire,
CompletesOnProviderStop, CompletesWhenEntryPresent, harness_run_turn, harness_outcome_label,
harness_outcome_detail,
}
Expand Down Expand Up @@ -234,6 +234,7 @@ fn harness_macbook_config(backend_url: String, model: NonEmptyStr, unit: Harness
reasoning_mode: harness_reasoning_mode,
wire_shape: harness_default_wire_shape,
system_prompt: harness_default_system_prompt,
alignment_chain_fingerprint: "",
request_scratch_path: harness_request_scratch_path,
events_path: harness_probe_events_path,
context_budget: harness_context_budget_for(unit: unit),
Expand Down Expand Up @@ -262,11 +263,16 @@ fn harness_probe_outcome(backend_url: String, model: NonEmptyStr, unit: HarnessS
// happened rather than whether the task succeeded. Nothing here inspects the assistant's text for
// correctness: that is external verification's subject, and a harness that graded its own worker's
// answer would be the same conflation DCH-2 forbids between a stop reason and a completed task.
// CHECKPOINT-DUE IS A CONTROL TRANSFER, NOT A FAILURE (review 5358022153): it gets its own admitted
// exit standing (3) rather than the generic failure code, so a consumer matching on 1 never reads a
// planned adjudication handoff as a crash. The belt's authority remains the provider event stream.
fn harness_turn_exit(outcome: HarnessTurnOutcome) -> ProcessExit {
match outcome {
TurnProviderStopped { wire_stop_reason: _, assistant_text: _, steps_taken: _, input_tokens: _, output_tokens: _ } =>
ExitSuccess
TurnCompletedByArtifact { path: _, steps_taken: _ } => ExitSuccess
TurnAlignmentCheckpointDue { steps_taken: _ } =>
ExitFailure { code: 3, reason: harness_outcome_label(outcome: outcome) }
_ =>
ExitFailure {
code: 1,
Expand Down Expand Up @@ -508,6 +514,7 @@ fn harness_worker_config(
model: NonEmptyStr,
unit: HarnessServingUnit,
system_prompt: String,
alignment_chain_fingerprint: String,
) -> HarnessTurnConfig {
HarnessTurnConfig {
backend_url: backend_url,
Expand All @@ -517,6 +524,7 @@ fn harness_worker_config(
reasoning_mode: harness_reasoning_mode,
wire_shape: harness_default_wire_shape,
system_prompt: system_prompt,
alignment_chain_fingerprint: alignment_chain_fingerprint,
request_scratch_path: request_scratch_path,
events_path: events_path,
context_budget: harness_context_budget_for(unit: unit),
Expand Down Expand Up @@ -566,6 +574,7 @@ fn harness_worker_cli(
repo_root: String,
gunbc_program: String,
attempt_identity: String,
alignment_chain_fingerprint: String,
) -> ProcessExit {
let system_prompt = harness_worker_system_prompt_at(worktree: worktree, repo_root: repo_root, gunbc_program: gunbc_program)
let binding = harness_bind_seat(short_hostname: harness_executor_short_hostname(), class: BatchQualityTolerant, requirement: AnyAdmittedModel, shape: harness_default_wire_shape, inputs: harness_model_request_inputs(role: "worker", shape: harness_default_wire_shape, system_prompt: system_prompt, user_input: brief), actor: join(["worker:", worktree], "") as NonEmptyStr, attempt: attempt_identity as NonEmptyStr, policy: harness_seat_policy)
Expand All @@ -583,6 +592,7 @@ fn harness_worker_cli(
model: bound_model,
unit: bound_unit,
system_prompt: system_prompt,
alignment_chain_fingerprint: alignment_chain_fingerprint,
),
prompt: brief,
step_budget: harness_worker_step_budget,
Expand Down Expand Up @@ -631,6 +641,7 @@ fn harness_reviewer_config(
reasoning_mode: harness_reasoning_mode,
wire_shape: harness_default_wire_shape,
system_prompt: system_prompt,
alignment_chain_fingerprint: "",
request_scratch_path: request_scratch_path,
events_path: events_path,
context_budget: harness_context_budget_for(unit: unit),
Expand Down Expand Up @@ -712,6 +723,7 @@ fn harness_auditor_config(
reasoning_mode: harness_reasoning_mode,
wire_shape: harness_default_wire_shape,
system_prompt: system_prompt,
alignment_chain_fingerprint: "",
request_scratch_path: request_scratch_path,
events_path: events_path,
context_budget: harness_context_budget_for(unit: unit),
Expand Down Expand Up @@ -802,6 +814,7 @@ fn harness_supervisor_config(
reasoning_mode: harness_reasoning_mode,
wire_shape: harness_default_wire_shape,
system_prompt: system_prompt,
alignment_chain_fingerprint: "",
request_scratch_path: request_scratch_path,
events_path: events_path,
context_budget: harness_context_budget_for(unit: unit),
Expand Down
118 changes: 118 additions & 0 deletions dag/gunbc/harness/harness_conversation_fork.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
module gunbc.harness.harness_conversation_fork

import std.types { String, Int, Bool }

// THE FORK POINT: WHERE AN ATTEMPT LINEAGE COULD RESUME. A turn's conversation lives in memory
// while it runs and is gone when the process exits; the fork point is the durable address of a
// moment in that conversation -- which lineage, which epoch and round, and the digests of the
// exact request and response bytes that passed the wire (gunbc.harness.harness_turn's wire log
// persists those bytes under <events_path>.wire/<round>.{request,response}.json; the digests here
// bind them without carrying the bytes).
type ConversationForkPoint {
attempt_lineage: String
epoch: Int
round: Int
request_digest: String
response_digest: String
model_identity: String
wire_shape: String
}

// THE FORK RECEIPT'S LAW, stated where admittance is decided. The durable wire log is the
// CORRECTNESS AUTHORITY for what the conversation was: a resume replays context from those bytes
// or it does not happen. An engine's KV prefix residency is a PERFORMANCE DERIVATION from that
// log -- a cache of computed state that may be present, absent, or gone -- and is NEVER a
// correctness dependency: no admittance below consults it, and no resume may require it. A fork is
// admitted only while every identity that produced the context still holds; any change refuses
// with the cause named, because replaying context across a change silently substitutes work the
// engine never did.
type ConversationForkAdmittance
= ForkAdmitted { point: ConversationForkPoint }
| ForkInvalid { cause: String }

// THE THREE REFUSALS, one per identity that must hold. The causes are the law's sentences: a fork
// across a model change replays context the engine never computed; a fork across a wire-shape
// change replays a conversation the current envelope cannot carry back to the engine; and a moved
// chain fingerprint means the alignment chain the context was built against changed. Each cause
// carries both spellings -- the fork point's and the candidate resume's -- so the refusal names
// what moved instead of merely asserting that something did.
fn conversation_fork_admit(
point: ConversationForkPoint,
model_identity: String,
wire_shape: String,
chain_fingerprint_at_point: String,
chain_fingerprint_now: String,
) -> ConversationForkAdmittance {
if point.model_identity != model_identity {
ForkInvalid { cause: join([
"a fork across a model change replays context the engine never computed: the fork point was",
" built under model identity ", point.model_identity,
" and the candidate resume offers ", model_identity,
], "") }
} else if point.wire_shape != wire_shape {
ForkInvalid { cause: join([
"a fork across a wire-shape change replays a conversation the current envelope cannot carry:",
" the fork point was built under ", point.wire_shape,
" and the candidate resume offers ", wire_shape,
], "") }
} else if chain_fingerprint_at_point != chain_fingerprint_now {
ForkInvalid { cause: join([
"the alignment chain the context was built against changed: the fork point binds chain",
" fingerprint ", chain_fingerprint_at_point,
" and the candidate resume offers ", chain_fingerprint_now,
], "") }
} else {
ForkAdmitted { point: point }
}
}

// KV PREFIX RESIDENCY IS AN OBSERVATION, NEVER CORRECTNESS STATE. The fabric's cache standing --
// whether a serving unit still holds the prefix of a conversation in its KV cache -- informs
// PLACEMENT PREFERENCE ONLY: a warm compatible location is PREFERRED (cheaper, faster), and when
// none is available the lineage executes COLD FROM DURABLE STATE, replaying the wire log the slow
// way. Neither direction is a correctness input: a wrong preference costs time, and a wrong
// correctness dependency would cost truth.
//
// THE OBSERVATION'S IDENTITIES ARE THE REASON. A fork receipt binds model, checkpoint, tokenizer,
// chat-template, tool-schema, projection and prefix digests -- the full set a KV prefix silently
// encodes -- because two serving units only share a prefix when ALL of them match. A shared chain
// fingerprint alone NEVER establishes the same KV prefix: the fingerprint names the alignment
// chain the context was built against, not the token stream any particular engine resident holds.
// Standing is therefore carried beside those identities, and a consumer that wants to trust a warm
// location must check every one of them, not the chain name.
type KvPrefixResidency
= Resident
| NotResident
| Unobserved
| Evicted
| Incompatible

type KvPrefixResidencyObservation {
serving_unit: String
model_identity: String
tokenizer_identity: String
chat_template_identity: String
semantic_prompt_digest: String
wire_digest: String
standing: KvPrefixResidency
observed_at: String
}

// THE PLACEMENT RULE, pure so the preference is testable without the fabric: only an observed
// Resident prefix earns preference. Unobserved is the honest default -- an unasked question never
// answers warm, so it lands on cold exactly like NotResident, Evicted and Incompatible. Executing
// cold is always available because the durable wire log, not any cache, is the correctness
// authority; this fold decides speed, never possibility.
type KvPlacementPreference
= PreferWarmLocation
| ExecuteColdFromDurableState

fn kv_prefix_residency_placement(standing: KvPrefixResidency) -> KvPlacementPreference {
match standing {
Resident => PreferWarmLocation
NotResident => ExecuteColdFromDurableState
Unobserved => ExecuteColdFromDurableState
Evicted => ExecuteColdFromDurableState
Incompatible => ExecuteColdFromDurableState
}
}
Loading