Date: 2026-09-22
Status: implementation-grade execution plan
Parent: #570 — connector control plane and self-hosting
Primary implementation: #574 — connector kernel, profile validation, probes, and routing
Dispatch bridge: #578
Durable state: #597
Multi-user authority: #598
IDKMesh needs one auditable answer to this question:
Given a GitHub issue or canonical WorkUnit, which class of agent/model is allowed to attempt it, which configured connectors are eligible, and what evidence or human authority is required before the result can progress?
The answer must be:
This plan converges the issue/model-router idea into the connector kernel instead of creating a second scheduler.
There must be exactly one canonical routing service in the product layer.
Do not build these as separate decision engines:
All of them should call the same deterministic route resolver.
The intended flow is:
GitHub issue / product task
|
v
WorkUnit preview / canonical task facts
|
v
RoutingDecision
- required capability tier
- authority mode
- risk class
- task classes
- tool/runtime requirements
- external-processing policy
- spend ceiling
- independence requirement
- escalation policy
|
v
Connector admission
- enabled?
- healthy?
- secrets available?
- task class supported?
- risk allowed?
- capability sufficient?
- runtime/tool fit?
- external processing allowed?
- project spend allowed?
- capacity available?
|
v
EligibleConnector[]
|
v
deterministic selection or explicit human choice
|
v
Run / attempt
|
v
candidate -> normalization -> verification
|
v
escalate / stop / human decision
A model can be technically capable of a task without having authority to satisfy the task.
Examples:
The route resolver therefore returns both:
required_capability_tier
authority_mode
Neither field may be inferred from the other.
The architecture uses stable tier semantics, not permanent marketing model names.
| Tier | Name | Intended work | Default dispatch posture |
|---|---|---|---|
| T0 | deterministic | script/CI-maintained state, validation, mechanical generation | no LLM |
| T1 | small | narrow tests, tiny fixes, low-ambiguity docs, one-module changes | cheap/free agent eligible |
| T2 | standard | bounded multi-file tooling/features with explicit acceptance tests | standard coding agent |
| T3 | strong | architecture-aware work, cross-cutting implementation, migrations, broad synthesis | strong model/agent |
| T4 | peak | core orchestration, statistical/research methodology, security/release/governance-sensitive implementation | peak model plus independent review |
Provider/model names belong in dated connector configuration/evidence, not in tier semantics.
A connector declares what tiers it can serve. The router declares what tier a task requires.
The first version should support:
| Authority mode | Meaning |
|---|---|
deterministic |
no agent dispatch should occur |
agent_candidate |
an agent may produce a candidate; normal verification/integration still applies |
human_gate_then_agent |
a named human/governance gate must be satisfied before or alongside dispatch |
human_required |
the acceptance evidence itself must come from a human/external actor; an owner-controlled agent cannot satisfy the issue |
Hard rule:
required model capability never upgrades repository authority
A T4 route is still only a candidate-generation recommendation unless project policy says otherwise.
#574 should introduce one versioned internal/product object similar to:
{
"api_version": "idkmesh.io/v1alpha1",
"routing_id": "route-...",
"project_id": "MSKazemi/idkmesh",
"source": {
"type": "github_issue",
"number": 564,
"revision": "<issue-updated-at-or-event-id>"
},
"work_unit": {
"id": "wu-...",
"digest": "sha256:..."
},
"policy_version": "routing-policy-v0.1",
"required_capability_tier": "T2",
"authority_mode": "agent_candidate",
"risk_class": "low",
"task_classes": ["coder", "tooling"],
"requirements": {
"git_write_candidate": true,
"network": "optional",
"sandbox": "required",
"tools": ["git", "python", "pytest"],
"min_context_class": "repository-bounded"
},
"constraints": {
"external_processing": true,
"project_spend_usd_max": 0,
"human_dispatch_approval_required": false,
"independent_reviewer_required": false
},
"escalation": {
"max_tier": "T4",
"max_attempts_per_tier": 1,
"switch_family_after_correlated_failure": true
},
"explanation": [
"bounded multi-file generator change",
"explicit deterministic acceptance checks",
"no security/governance/release authority",
"standard tier sufficient"
]
}
The exact schema can evolve, but the semantic separation should remain.
Each configured agent/model path needs machine-readable capability evidence.
Example normalized capability view:
{
"connection_id": "jules-main",
"kind": "agent",
"driver": "jules",
"enabled": true,
"health": "healthy",
"capabilities": {
"tiers": ["T1", "T2"],
"task_classes": ["coder", "tests", "docs"],
"tools": ["git", "tests", "remote_sandbox"],
"candidate_types": ["github_pull_request"],
"max_risk": "low"
},
"policy": {
"external_processing": true,
"project_spend_usd_max": 0,
"max_concurrency": 1
},
"independence": {
"provider_family": "google",
"agent_family": "jules",
"execution_family": "jules-hosted"
}
}
For raw model providers, tier capability is only one part of eligibility. A raw model connection is not automatically a coding-agent connection.
The resolver must apply decisions in a fixed order.
Bind routing to:
Do not route against mutable text without recording what was seen.
Before cost or model capability:
if acceptance requires human/external evidence:
authority = human_required
automatic dispatch = denied
elif task is deterministic workflow-maintained state:
authority = deterministic
model tier = T0
elif named human/governance dependency exists:
authority = human_gate_then_agent
else:
authority = agent_candidate
Set a minimum capability/risk posture from semantic task facts.
Examples:
Negative-scope text such as “do not change schemas” must not trigger a schema floor.
For tasks without an explicit reviewed route, measure bounded observable signals such as:
The score only raises capability above the hard floor. It never lowers a hard floor.
Convert issue/work facts into normalized requirements:
A connector is ineligible if any of these fail:
enabled
AND healthy_or_allowed_degraded
AND connector_kind_compatible
AND required_tier_supported
AND task_class_supported
AND risk_allowed
AND tools/runtime_fit
AND candidate_type_supported
AND secret_refs_resolvable
AND external_processing_policy_satisfied
AND project_spend_policy_satisfied
AND concurrency_capacity_available
AND repository/source_binding_valid
AND human_gate_satisfied_if_required
Every rejection must have a stable machine-readable reason.
Among eligible connectors, prefer a lexicographic decision rather than an opaque learned score for v0.1.
Recommended ordering:
This keeps the decision explainable.
A future evidence-driven scheduler may replace some ordering with calibrated policy, but the hard gates remain non-compensating.
For T4 or other routes requiring independent review, the planner should produce a route set, not only one connector.
Example:
primary candidate:
strong/peak coding agent
independent critic/reviewer:
different provider family where practical
no shared candidate-generation prompt lineage when avoidable
deterministic verifier:
repository test/security/evidence gate
human decision:
when required by authority policy
Independence metadata should track at least:
Ten attempts from the same model/prompt/runtime are not ten independent reviewers.
GitHub labels are a projection of the canonical RoutingDecision, not the source of truth.
Recommended managed labels:
model:t0-deterministic
model:t1-small
model:t2-standard
model:t3-strong
model:t4-peak
model:none
authority:agent-candidate
authority:human-required
authority:human-gate
authority:deterministic
agent:jules-eligible
route:ready
route:blocked
The durable route object/ledger record remains authoritative.
The system should be able to regenerate labels after deletion or repository migration.
Do not make model-tier classification itself add the literal provider dispatch label.
Use two stages:
route says:
agent:jules-eligible
dispatcher checks:
no active claimant/duplicate PR
issue still unchanged
WorkUnit admitted
Jules connection healthy
current capacity available
project policy allows external processing
authority gate satisfied
idempotency key not already consumed
then and only then:
call Jules REST connector
OR add a configured provider-specific trigger label in GitHub-native mode
This prevents an issue edit from becoming an accidental provider invocation.
The GitHub-first profile should work as:
issue opened/edited
-> preview workflow
-> canonical WorkUnit + RoutingDecision
-> routing labels/status comment/check
authorized dispatch action
-> idempotency lookup in durable Git-native run ledger
-> connector admission
-> secret materialization only after policy pass
-> external/local run creation
-> append run event
provider/PR event or scheduled observer
-> recover run from durable ledger
-> update state
-> candidate normalization
-> verification
verification complete
-> evidence publication
-> awaiting human decision
human normal GitHub review/merge
-> integration state recorded
No always-on coordinator is required for the bootstrap profile.
The router must compose with #597.
Minimum persisted route/run facts:
A workflow crash must not make the project forget which provider was already invoked.
The route resolver must consume identity/role policy from #598 before dispatch.
Examples:
issue author:
may propose work
does not automatically gain dispatch authority
authorized maintainer:
may approve low-risk dispatch
agent worker:
may produce candidate
cannot approve itself
automated verifier:
may produce evidence
cannot merge
human reviewer:
may supply required human evidence
only if project policy recognizes the role
integrator:
normal GitHub protected-branch authority
Role checks happen before secrets are resolved or provider work is started.
Escalation is evidence-driven, not “failure -> larger model”.
Recommended transition:
T1
-> T2
-> T3
-> T4
-> T4 + different-family independent reviewer
-> explicit human decision / task redesign
But classify the failure first.
| Failure class | Action |
|---|---|
| provider outage / rate limit | retry or switch equivalent connector at same tier |
| sandbox/environment failure | repair environment; same tier |
| missing secret/authorization | stop; operator configuration |
| task too broad | split WorkUnit; do not buy a larger model to compensate |
| acceptance criteria unclear | improve specification; reroute |
| implementation/reasoning failure on clear task | escalate one tier |
| repeated same-family correlated error | switch provider/model/agent family before another identical attempt |
| verifier disagreement | add independent verifier/reviewer; do not silently choose favorable verdict |
| security/governance boundary | stop at policy gate |
| human-required evidence | wait for human/external actor |
| T4 still inconclusive | preserve uncertainty and return to human/product decision |
Every escalation creates a new attempt identity and append-only event.
#574 should define stable normalized failure categories used by all connectors:
configuration_error
authentication_error
authorization_error
policy_denied
source_not_connected
rate_limited
quota_exhausted
provider_unavailable
capacity_unavailable
sandbox_failure
tool_failure
agent_failed
reasoning_failed
timeout
cancelled
candidate_missing
result_normalization_error
verification_failed
conflict
not_found
human_gate_pending
Do not infer model weakness from provider/network/sandbox failures.
Implement:
Acceptance:
Implement:
Acceptance:
Implement:
Acceptance:
Implement:
env:NAME references only at first;Acceptance:
Implement minimal stdlib-friendly state for development mode:
This can be SQLite locally while #597 defines GitHub-native durable state for no-server deployment.
Target:
idkmesh connections validate
idkmesh connections list
idkmesh connections probe
idkmesh doctor
idkmesh route explain --issue N
The CLI must call the same service/router code that future HTTP/GitHub surfaces use.
At minimum test:
Jules should implement the common agent connector.
The connector should receive:
It returns provider-neutral run events and candidate reference.
Live acceptance should use a T1/T2 low-risk issue, not a T4 core architecture issue.
The OpenAI-compatible connector declares model capability but does not itself become a coding agent.
It should normalize:
A local agent such as goose can then reference this model connection.
A local agent preset combines:
agent preset
+ admitted model connection
+ execution connection
+ WorkUnit
+ RoutingDecision
The preset owns executable/argument templates.
Issue text never chooses:
#578 should consume routing rather than reimplement it.
Flow:
GitHub event
-> verify event/delivery identity
-> build WorkUnit preview
-> call route resolver
-> publish route projection
-> require configured dispatch action
-> role/authority check
-> idempotency check
-> create run
Initial dispatch triggers should be explicit:
Do not dispatch on every issue-open event.
The selected connector becomes irrelevant after candidate normalization.
Both:
Jules PR
local patch bundle
must converge to:
WorkUnit binding
+ worker/connector identity
+ exact source SHA
+ candidate reference
+ artifacts/digests
+ ResultManifest
+ VerificationResult request
This is the proof that the routing layer is provider-neutral.
The CLI, optional HTTP API, and Control Tower GUI should display the same route explanation:
Do not show only “assigned to Jules” without the explanation that produced it.
Exit gate:
PR sequence:
B1 schemas/types/errors
B2 registry/profile validation
B3 fake connectors + probes
B4 route resolver + explanation
B5 local metadata/idempotency store
B6 CLI validate/list/probe/doctor/route-explain
B7 adversarial tests + docs
Keep each PR independently reviewable when practical.
Parallel after C1 contract stabilizes:
C2 Jules REST
C3 OpenAI-compatible model provider
C4 local agent preset
Each connector must prove it can fail without corrupting canonical state.
Implement together with explicit dependency coordination:
Exit gate:
Implement #579 and verify:
Implement #580 and #572:
Run >=10 bounded real repository tasks across >=2 heterogeneous connectors.
Measure:
Do not call the system successful merely because agents ran.
Implement #596–#599 and demonstrate:
idkmesh init --github;=10 WorkUnits;
Only after this evidence should GitHub-only be declared the default deployment profile.
Before enabling automatic low-risk dispatch, prove at minimum:
| Scenario | Expected result |
|---|---|
| focused deterministic unit-test issue | T1, agent candidate, cheap connector eligible |
| bounded generator + regenerated artifacts | T2 |
| cross-cutting schema migration | >= T3 |
| statistical uncertainty/research method | T4 |
| release/security/permissions work | strong/peak posture + human gate according to policy |
| independent human review issue | model none / human required |
| workflow-maintained ledger | T0 deterministic |
| low-tier connector on T4 task | rejected: insufficient capability |
| external provider when external processing forbidden | rejected |
| paid provider when project spend max is zero | rejected |
| missing secret | rejected/configuration error |
| same dispatch delivery replayed | existing run returned; no new provider work |
| same-family repeated reasoning failure | next route penalizes/switches family |
| T4 disagreement remains | human decision, no automatic favorable selection |
Routing behavior affects cost, security, and evidence. Treat it as versioned policy.
Each route records:
policy_version
router_implementation_version
connector_profile_revision
project_policy_revision
Do not silently change historical route interpretation after policy updates.
New policy can reroute future attempts while preserving old route records.
The Control Tower should eventually report:
Avoid vanity metrics such as raw agent task count without verified outcome context.
The routing/dispatcher layer must never let issue/comment content directly set:
Untrusted issue text describes work. Maintainer/project policy controls authority and execution.
The routing/dispatcher layer is not done when labels exist.
It is done when:
After the design PR is current and merged, #574 is the next coding target.
The first bounded implementation PR should contain only:
It should contain no live Jules HTTP, no OpenAI/Gemini network calls, no GitHub webhook mutation, and no merge authority.
That gives every later connector one stable contract to implement against.