Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
caa084a
WIP: proud-gull-252
briansrls Apr 26, 2026
6f494af
WIP: proud-gull-252
briansrls Apr 26, 2026
a02c9a5
WIP: proud-gull-252
briansrls Apr 26, 2026
0a98c73
WIP: proud-gull-252
briansrls Apr 26, 2026
f9015dd
fix(extdeps): document wire serde gaps; add Developer to OpenAI chat …
briansrls Apr 26, 2026
75f2db1
WIP: proud-gull-252
briansrls Apr 26, 2026
dc113a1
docs(extdeps): name request-wire serde gaps for Anthropic/OpenAI mess…
briansrls Apr 26, 2026
b60bd69
docs(extdeps): classify LLM role coproducts
briansrls Apr 26, 2026
2dc0fae
WIP: sleek-fox-264
briansrls Apr 26, 2026
04a91ec
WIP: sleek-fox-264
briansrls Apr 26, 2026
0d9e1d7
fix(extdeps): make Anthropic message content role-specific
briansrls Apr 26, 2026
3046ade
WIP: sleek-fox-264
briansrls Apr 26, 2026
44f682b
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
8a1d969
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
69993a5
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
d2d1753
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
6bdd4b9
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
1786c87
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
14d285a
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
63cf157
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
b112953
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
79df4f8
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
55da674
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 2026
9e362d8
docs: mark R2 PB tier3 mirror pack authored
briansrls Apr 26, 2026
6484954
Merge remote-tracking branch 'origin/main' into session/proud-gull-252
briansrls Apr 26, 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
2 changes: 1 addition & 1 deletion docs/briefs/r2-manager-brief-authority-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Each deliverable owned by an R2 manager belongs to exactly one of categories 1-5
| Deliverable | Category | Notes |
|---|---|---|
| The manager brief itself | 5 (placeholder) | Graduates on R2 spawn |
| Tier 3 mirror dissolutions (termination/computation/induction/effect-carrier) | 1 (worker brief; 4+ sub-briefs) | Pending; mirror-by-mirror |
| Tier 3 mirror dissolutions (termination/computation/induction/effect-carrier) | 1 (worker brief; 4+ sub-briefs) | Authored in `docs/briefs/r2-pb-tier3-mirror-dissolution-workers.md`; mirror-by-mirror dispatch |
| Tier 2 patch_lower_helpers_* retirement | 1 (worker brief) | Pending; if survives R1; B7 priority hint received |
| `kernel_algebra_profile` mirror dissolution | 1 (worker brief) | Pending; gated on `ValueBody::Map` substrate |
| Post-R1 emergent dissolutions | 1 (worker brief; ad-hoc) | Pending; emerge during R2 |
Expand Down
11 changes: 6 additions & 5 deletions docs/briefs/r2-pure-bootstrap-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@

| Lane | Size | Status (at brief authoring) | Description |
|---|---|---|---|
| Tier 3 mirror dissolutions: termination | M | NOT YET AUTHORED | `DescentEvidence`, `PositiveDescentAmount`, `ProportionalDivisor`, `ShrinkFactor`, `evidence_rank`, `merge_evidence` Rust mirror at `dag.rs:628-790` dissolves as v3 lowers + evaluates `.dag` runtime values. Tier 3 #10 from #810. |
| Tier 3 mirror dissolutions: computation | M | NOT YET AUTHORED | `SizeBound`, `RecursionShape`-related Rust mirror at `dag.rs:839-915` dissolves with same substrate dependency. |
| Tier 3 mirror dissolutions: induction | M | NOT YET AUTHORED | `RecursionShape`, `InductiveField`, `SubValueRelation` Rust mirror at `dag.rs:916-980` dissolves with same substrate dependency. |
| Tier 3 mirror dissolutions: effect-carrier | S | NOT YET AUTHORED | `src/v3/compiler/src/dag/effects.rs` (216 LOC) + `compose_operation_effects` in `workflow_idempotency.rs` (105 LOC). Mechanical PB dissolution once self-hosting reaches it. Tier 3 #12 from #810. |
| Tier 3 mirror dissolutions: termination | M | AUTHORED in [`r2-pb-tier3-mirror-dissolution-workers.md`](r2-pb-tier3-mirror-dissolution-workers.md) | `DescentEvidence`, `PositiveDescentAmount`, `ProportionalDivisor`, `ShrinkFactor`, `evidence_rank`, `merge_evidence` Rust mirror at `dag.rs:628-790` dissolves as v3 lowers + evaluates `.dag` runtime values. Tier 3 #10 from #810. |
| Tier 3 mirror dissolutions: computation | M | AUTHORED in [`r2-pb-tier3-mirror-dissolution-workers.md`](r2-pb-tier3-mirror-dissolution-workers.md) | `SizeBound`, `RecursionShape`-related Rust mirror at `dag.rs:839-915` dissolves with same substrate dependency. |
| Tier 3 mirror dissolutions: induction | M | AUTHORED in [`r2-pb-tier3-mirror-dissolution-workers.md`](r2-pb-tier3-mirror-dissolution-workers.md) | `RecursionShape`, `InductiveField`, `SubValueRelation` Rust mirror at `dag.rs:916-980` dissolves with same substrate dependency. |
| Tier 3 mirror dissolutions: effect-carrier | S | AUTHORED in [`r2-pb-tier3-mirror-dissolution-workers.md`](r2-pb-tier3-mirror-dissolution-workers.md) | `src/v3/compiler/src/dag/effects.rs` (216 LOC) + `compose_operation_effects` in `workflow_idempotency.rs` (105 LOC). Mechanical PB dissolution once self-hosting reaches it. Tier 3 #12 from #810. |
| `kernel_algebra_profile` mirror dissolution | M | GATED (waiting on Substrate Manager `ValueBody::Map` carrier; future T-Substrate sub-lane) | Map-shaped (not list/sum); requires `ValueBody::Map` substrate work. Substrate Manager future sub-lane. |
| Tier 2 `patch_lower_helpers_*` retirement | S | NOT YET AUTHORED (queued for PB-Tier1 priority hint per #810 §5) | If survives R1, PB Manager retires `patch_lower_helpers_generated_type_alias_refinement` once generated `lower_helpers` can emit refinement field natively. |
| Post-R1 emergent dissolutions | varies | NOT YET MATERIALIZED | Catch-all for new PB work that surfaces post-R1 (new mirror dissolutions discovered during R2; new Rust scaffolds inadvertently introduced and needing dissolution). |
Expand Down Expand Up @@ -58,9 +58,9 @@

Authored:
- Pre-R1 PB program briefs (in `pure-bootstrap-zero-manager.md`, archives on R2 promotion); content migration here covers post-R1 deliverables only.
- [`r2-pb-tier3-mirror-dissolution-workers.md`](r2-pb-tier3-mirror-dissolution-workers.md) — termination, computation, induction, and effect-carrier mirror dissolution worker pack.

Pending — pre-spawn Director-authored per inbox #828 coordination split; post-spawn manager-authored autonomously per "Pre-spawn vs post-spawn authority" subsection above:
- Tier 3 mirror dissolution worker briefs (4: termination, computation, induction, effect-carrier)
- `kernel_algebra_profile` worker brief (gated on Substrate Manager `ValueBody::Map`)
- Tier 2 `patch_lower_helpers_*` retirement worker brief (if survives R1)

Expand All @@ -73,5 +73,6 @@ Lane status table refreshes here as work lands. Pre-spawn placeholder.
- Parent: `docs/r2-structure.md` §"Pure Bootstrap Manager"
- Migrating from: `docs/briefs/pure-bootstrap-zero-manager.md` (archives on R2 promotion)
- Self-hosting design: `docs/design-pure-bootstrap-zero.md` LIVE 2026-04-25
- Tier 3 worker pack: [`docs/briefs/r2-pb-tier3-mirror-dissolution-workers.md`](r2-pb-tier3-mirror-dissolution-workers.md)
- Tier 3 source: `docs/briefs/debt-paydown-synthesis-2026-04-25.md` items #10 + #12
- ROADMAP single authority on gate semantics: `ROADMAP.md §"Lane acceptance — .dag gates"`
12 changes: 10 additions & 2 deletions dsl/extdeps/github/auth.dag
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,20 @@ module extdeps.github.auth

import gunbc.auth.credentials { gcp_secret_credential }
import std.resources { Network }
import std.types { NonEmptyStr }
import std.types { NonEmptyStr, Secret }

// Secret Manager materializes secret bytes only — no GitHub-issued scope or
// expiry metadata on the wire (P3: do not fabricate empty scopes / absent
// expiry as if observed). Acquisition-path carrier lives in auth, not the
// GitHub core provider model.
type GitHubSecretManagerPat {
token: Secret
}

func github_token(
project_id: NonEmptyStr = "gunbai-secrets",
secret_name: NonEmptyStr = "github-token"
) -> { token: Secret }
) -> GitHubSecretManagerPat
uses net: Network
{
cred = gcp_secret_credential(
Expand Down
52 changes: 46 additions & 6 deletions dsl/extdeps/llm/anthropic.dag
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//
module extdeps.llm.anthropic

import extdeps.llm.llm { Role, StopReason, TokenUsage, llm_snake_wire_contract }
import extdeps.llm.llm { StopReason, TokenUsage, llm_snake_wire_contract }
import std.errors { AnthropicErrorShape }
import std.credentials { CredentialSource, EnvVar }
import std.serialization { VariantEncoding }
Expand Down Expand Up @@ -40,10 +40,20 @@ data models: List<AnthropicModelSpec> = [
// -- Anthropic content blocks (provider-specific) ---------------------
// Extends the shared ContentBlock (llm.dag) with tool-use blocks.

type AnthropicContentBlock
= TextBlock { text: String }
| ToolUseBlock { id: String, name: String, input: Json }
| ToolResultBlock { tool_use_id: String, content: String, is_error: Bool? }
// 🟢 TERMINAL provider-domain coproduct for user-message content. `UserTextBlock`
// and `UserToolResultBlock` are role-legal Anthropic Messages content rows; the
// wire `type` keys are emitter/transport obligations, not caller-authored model
// state. `UserToolResultBlock.content: String` is the narrow text-result slice;
// non-string/nested result content is gap-carried below.
type AnthropicUserContentBlock
= UserTextBlock { text: String }
Comment thread
briansrls marked this conversation as resolved.
| UserToolResultBlock { tool_use_id: String, content: String, is_error: Bool? }

// 🟢 TERMINAL provider-domain coproduct for assistant-message content.
// Assistants can emit text or tool-use requests; tool results are user rows.
type AnthropicAssistantContentBlock
= AssistantTextBlock { text: String }
| AssistantToolUseBlock { id: String, name: String, input: Json }

// -- System prompt -------------------------------------------------

Expand Down Expand Up @@ -87,6 +97,36 @@ data current_api_version: AnthropicApiVersion = {
header: "anthropic-version"
}

// Messages API conversation row: the outer variant is the role discriminator,
// so role-specific content legality is structural. User rows can carry text or
// tool results; assistant rows can carry text or tool-use requests.
// 🟢 TERMINAL provider-domain coproduct for the modeled Messages row roles.
// Q4.5 P1 closure (#808 / #856 Substrate escalation).
type AnthropicChatMessage
= UserMessage { content: List<AnthropicUserContentBlock> }
| AssistantMessage { content: List<AnthropicAssistantContentBlock> }

Comment thread
briansrls marked this conversation as resolved.
// Outputs still JSON-path-project; same downstream closure as OpenAI slice.
data structural_coverage_gap_anthropic_messages_outputs: List<String> = [
"closure:rest_typed_response_body|llm.Anthropic.Messages|residue:output_fields_use_json_path_projection"
]

// Request wire: Messages API expects string `role` + flat `content[]` objects
// keyed by `type` (https://docs.anthropic.com/en/api/messages). `type` is not
// caller-authored model state on `TextBlock`; the future
// `rest_request_wire_serde_alignment` closure must emit it from the variant.
data structural_coverage_gap_anthropic_messages_request_wire: List<String> = [
"closure:rest_request_wire_serde_alignment|llm.Anthropic.Messages|AnthropicChatMessage|residue:message_variant_must_emit_role_string_user_assistant",
"closure:rest_request_wire_serde_alignment|llm.Anthropic.Messages|AnthropicUserContentBlock.UserTextBlock|residue:variant_must_emit_flat_type_text_wire_key",
"closure:rest_request_wire_serde_alignment|llm.Anthropic.Messages|AnthropicAssistantContentBlock.AssistantTextBlock|residue:variant_must_emit_flat_type_text_wire_key",
"closure:rest_request_wire_serde_alignment|llm.Anthropic.Messages|AnthropicAssistantContentBlock.AssistantToolUseBlock|residue:variant_must_emit_flat_type_tool_use_wire_key",
"closure:rest_request_wire_serde_alignment|llm.Anthropic.Messages|AnthropicUserContentBlock.UserToolResultBlock|residue:variant_must_emit_flat_type_tool_result_wire_key"
]

data structural_coverage_gap_anthropic_tool_result_full_content_surface: List<String> = [
"closure:anthropic_tool_result_full_content_surface|AnthropicUserContentBlock.UserToolResultBlock|residue:content_modeled_as_string_only|missing:nested_content_blocks|missing:image_content"
]

// -- Service: REST transport wiring ------------------------------

service llm.Anthropic {
Expand All @@ -105,7 +145,7 @@ service llm.Anthropic {
input {
api_key: Secret
model: String
messages: Json
messages: List<AnthropicChatMessage>
Comment thread
briansrls marked this conversation as resolved.
max_tokens: Int = 4096
temperature: Float?
system: String?
Expand Down
41 changes: 39 additions & 2 deletions dsl/extdeps/llm/openai.dag
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//
module extdeps.llm.openai

import extdeps.llm.llm { Role, StopReason, TokenUsage, llm_snake_wire_contract }
import extdeps.llm.llm { StopReason, TokenUsage, llm_snake_wire_contract }
import std.errors { OpenAiErrorShape }
import std.serialization { VariantEncoding }
import std.types { HttpMethod, AuthScheme }
Expand Down Expand Up @@ -76,6 +76,43 @@ type ToolCall {
function: FunctionCall
}

// Roles on Chat Completions `messages[]` for this **narrow string-content**
// carrier: system / developer / user / assistant per OpenAI Chat Completions
// (https://platform.openai.com/docs/api-reference/chat/create). Tool rows and
// multimodal `content` arrays are not modeled here — gap-carried below.
// 🟢 TERMINAL provider-domain coproduct for the modeled narrow text-message
// row. Full Chat Completions message variants remain gap-carried by
// `structural_coverage_gap_openai_chat_message_full_api_surface`; request wire
// role-string serialization remains gap-carried separately.
type OpenAiChatMessageRole = System | Developer | User | Assistant
Comment thread
briansrls marked this conversation as resolved.

// Chat Completions API message row: wire accepts plain-string `content` for
// text-only payloads (OpenAI docs). Typed here so callers cannot pass opaque
// Json; multimodal rows extend this product when needed (Q4.5 P1 / #808).
type OpenAiChatMessage {
role: OpenAiChatMessageRole
content: String
}

// Typed inputs close the Json bypass; outputs still JSON-path-project until
// `response { 200 => Typed... }` lands. Queryable receipt for lenses/audits.
data structural_coverage_gap_openai_chat_completion_outputs: List<String> = [
"closure:rest_typed_response_body|llm.OpenAI.ChatCompletion|residue:output_fields_use_json_path_projection"
]

// Full Chat Completions message coproduct (tool_call_id, tool role, function,
// multimodal content parts) is not this row — downstream closure trigger.
data structural_coverage_gap_openai_chat_message_full_api_surface: List<String> = [
"closure:openai_chat_message_full_coproduct|OpenAiChatMessage|missing:tool_role_with_tool_call_id|missing:function_role|missing:multimodal_content_array"
]

// Chat Completions `messages[].role` must be wire strings (system/developer/
// user/assistant). Emitter serde for unit enums may not match; same closure
// as Anthropic request wire — verify before relying on typed bodies for 200s.
data structural_coverage_gap_openai_chat_request_messages_wire: List<String> = [
"closure:rest_request_wire_serde_alignment|llm.OpenAI.ChatCompletion|OpenAiChatMessageRole|residue:unit_enum_role_must_serialize_as_openai_role_strings"
]

// -- Service: REST transport wiring ------------------------------

service llm.OpenAI {
Expand All @@ -93,7 +130,7 @@ service llm.OpenAI {
input {
api_key: Secret
model: String
messages: Json
messages: List<OpenAiChatMessage>
Comment thread
briansrls marked this conversation as resolved.
temperature: Float?
max_tokens: Int?
}
Expand Down
10 changes: 5 additions & 5 deletions dsl/gunbc/tools/review.dag
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ import extdeps.shell

data default_model: String = "claude-sonnet-4-6-20250929"
data cron_schedule: String = "*/10 * * * *"
// BRIDGE: messages should be [{ role: "user", content: "..." }] (Json array),
// but emit_simple_expr cannot render list/record literals in transport bodies.
// Passed as a JSON-encoded string; the emitter coerces via serde_json::from_str.
// Dissolves when emit_simple_expr handles ExprListLit/ExprRecordLit.
data review_messages: String = "[{\"role\": \"user\", \"content\": \"Review the PR described in the system prompt.\"}]"
data review_messages: List<AnthropicChatMessage> = [
UserMessage {
content: [UserTextBlock { text: "Review the PR described in the system prompt." }]
}
]

// -- Pure functions ---------------------------------------------------

Expand Down
6 changes: 5 additions & 1 deletion src/v2/tests/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6254,7 +6254,11 @@ fn anthropic_live_e2e() {

import extdeps.llm.anthropic

data test_messages: String = "[{\"role\": \"user\", \"content\": \"Say hello in exactly 3 words.\"}]"
data test_messages: List<AnthropicChatMessage> = [
UserMessage {
content: [UserTextBlock { text: "Say hello in exactly 3 words." }]
}
]

func ask_claude(
model: String = "claude-haiku-4-5-20251001",
Expand Down
Loading