Technical Design 2.en - jiale-li-orion/SecFusionAgent GitHub Wiki
SecFusionAgent Technical Design 2
English · 2 | 中文 · 2 | Technical Design 1
Interactive view: M4–M6 Investigation and Execution Plane — 中文 · English
This document continues the M1–M3 Evidence/Knowledge data plane and the existing Case / Trajectory / Experience storage seams, and defines a shared Agent Task Runtime: Task protocol, reference-preserving context, asynchronous multi-loop execution, M4 investigation state, the M5 Investigation Role, Capability / Policy / Sandbox control, M6 decision output, and the replay/operations contracts required by M7/M8. M3 still owns its domain state/operators/canonical writes; its Enrichment Role may execute on the shared Task Runtime defined here. 本地wiki/tech design cache02.md and tech design cache03.md preserve the derivation history; this document holds the runtime contract that enters implementation and testing.
The runtime is not organized around chat history and does not use natural-language summaries as the primary handoff between Agents. It operates over an evolving Evidence World, revisioned Task/Context/State references, and multiple independently recoverable loops: simple lookup terminates after a current projection read; the M3 Enrichment Role continuously closes canonical enrichment gaps; the M5 Investigation Role resolves task-conditioned EvidenceNeeds; WATCH uses event-driven short episodes. Agents read through controlled perception, change durable state only through State/Knowledge gates, and execute real actions only through the Capability Broker.
Design status — 2026-10-04
Technical Design 2 is now being accepted slice by slice against implementation evidence. The Task Runtime / duplex TaskEvent, the unified TaskIntent → task_admission → TaskContract compilation entry point, M3 EnrichmentRole, M4 Investigation State, Context handoff, canonical VERIFY, Incident WATCH/async enrichment, and Slice 9 M6 Decision + A2A mapping are closed; background enrichment is now the first production caller wired through unified task admission instead of constructing executable contracts directly. M6 reads only materialized M4 state: model proposals must normalize into typed DecisionDraft or ContinuationRequest, fact conclusions may cite only confirmed M4 EvidenceRefs, durable decision writes remain behind the M4-owned DecisionCommit event gate, and evidence gaps follow ContinuationRequest → TaskIntent → M4 ContinuationGate before creating an EvidenceNeed. A2A now has deterministic Task/Artifact/Message/status/artifact stream/push mapping plus a read-only HTTP GetTask compatibility seam; internal Context identity is not reused as A2A contextId. Slice 10 now implements durable replay checkpoints, single-loop/multi-loop replay, one-variable context/policy/sandbox/Skill/Capability interventions, historical M4 state-event replay, baseline/candidate regression comparison, and the Experience → ExperiencePattern → SkillPatchCandidate → support/counterexample/regression replay → promotion gate. When the pinned M1–M3 Knowledge revision cannot be read exactly from the current projection, M7 fails closed so future facts cannot leak into historical replay. The current formal code coordinate passes make check: 522 passed / 12 skipped, Ruff is clean, mypy reports 534 source files / 0 errors, and the real PostgreSQL/Redis + LocalStack integration suite passes 12/12. The Product-facing M6 path defined here now participates in the same-deployment formal live benchmark: all 14 single-turn Product-QA cases and two two-turn sessions completed, with durable Decision/Continuation, ContextManifest, ModelRequest/Attempt, and retrieval-invocation refs available for trace drill-down. The main open boundaries are a real OpenShell/Firecracker substrate, production external Capability catalog/binding, complete A2A SendMessage/Subscribe/push transport, and an M1–M3 versioned read path for true historical Agent re-execution; reference-vs-summary is now an independent experiment rather than an architecture-completion prerequisite. Cross-module ownership, Task/Context/State/Skill/Capability/Policy protocols, and security boundaries remain frozen; algorithms, thresholds, provider composition, and Skill-promotion criteria may still be revised by coding and evaluation evidence.
Two infrastructure choices are also fixed early. The internal Task Event Plane uses a PostgreSQL durable event log plus a separate logical Redis Streams delivery role; Celery remains coarse-grained worker dispatch and Hot Cache Redis remains M1–M3 transient state. Sandbox v1 selects OpenShell as sandbox supervisor/enforcement runtime and an OCI container (Docker/Podman backend) as the default executable boundary; high-risk arbitrary-code work uses a Firecracker microVM profile and fails with sandbox_unavailable when KVM/backend support is absent rather than silently downgrading to a normal container. A2A is an external interoperability adapter aligned with Task / Artifact / SSE streaming / push-notification semantics; internal duplex semantics are independent of A2A transport. Low-latency bidirectional transport may use an A2A custom WebSocket binding without changing the internal Task/Event contract.
Runtime architecture
SecFusionAgent uses one shared Task Runtime for different domain roles instead of cloning an orchestrator per Agent persona. Task defines the work contract first; a compatible Role is selected next; Role supplies state model, planner profile, and skill/capability preferences; the Execution Control Plane finally determines which real actions are permitted.
flowchart LR
Entry[User request / KnowledgeChange / Watch wake]
Task[Task Runtime
Contract / Run / Event / Context]
Enrich[M3 Enrichment Role
EnrichmentState]
Investigate[M5 Investigation Role
InvestigationState]
Perception[Perception Runtime]
Decision[M6 Decision Runtime]
World[M1-M3 Evidence World]
Event[Async Event Plane
TaskEvent / StateChanged]
Control[Execution Control Plane
Capability / Policy / Budget / Identity / Network / Sandbox]
Entry --> Task
Task --> Enrich
Task --> Investigate
World --> Perception
Enrich --> World
Investigate --> Perception
Perception --> Investigate
Investigate --> Decision
Enrich --> Event
Investigate --> Event
World --> Event
Event --> Task
Control -.enforces.-> Enrich
Control -.enforces.-> Investigate
Control -.enforces.-> Perception
The boundaries are fixed as follows.
- Task Runtime owns TaskContract, TaskRun, parent/child dependencies, ContextManifest, TaskEvent, and scheduling state; it owns no vulnerability/Incident facts.
- Enrichment Role is the routine M3 Agent workload. It consumes M3 EnrichmentState plus operator/source catalogs for background or delegated enrichment; results re-enter Acquisition/Evidence/Knowledge gates.
- Investigation Role is the active M5 workload. It consumes M4 InvestigationState/EvidenceNeed and may delegate EnrichmentTask, but child natural-language output never becomes fact by itself.
- Evidence World remains owned by M1–M3 for durable facts, relations, Incident, Insight, EvidenceRef, document revisions, and Current Projection.
- Perception Runtime is the controlled interface for Evidence World/external observation reads; tool/provider results first become EphemeralObservation.
- M4 State Runtime owns Case, EvidenceNeed, and confirmed/conflict/unknown/tentative investigation state; it is not a parallel Knowledge store.
- M6 Decision Runtime reads current M4 state only. When state is insufficient it emits a ContinuationRequest; M4 decides whether to open an EvidenceNeed.
- Async Event Plane carries Task/Context/Knowledge/Enrichment/Investigation state changes. A deterministic relevance gate decides refresh/wake/defer before any model is invoked.
- Execution Control Plane owns capability, authorization, obligations, budget, identity, network, sandbox, and side-effect enforcement; prompts and Roles cannot bypass it.
Agents do not directly receive arbitrary database access, provider credentials, unrestricted HTTP, shell, browser, or Docker socket access. Tool/MCP metadata is implementation discovery only; CapabilityContract and PolicyDecision are the runtime trust contracts.
Task Protocol, Role, and execution profiles
The design order is fixed as Task → Role → Context/Handoff → Loop/Scheduling → Capability → Policy. The system does not start from Researcher/Analyst/Reporter personas and then force tasks into them. A workload becomes an independent Agent Role only when it has its own TaskContract, domain state, completion predicate, capability/policy envelope, and can work from scoped references instead of a copy of the parent's entire context.
TaskIntent, TaskContract, and TaskRun
User requests, M1–M3 change events, background enrichment triggers, WATCH wake-ups, and M6 ContinuationRequests first become TaskIntent. Stable identifiers/objects/versions/time expressions are parsed deterministically before ambiguous fields are structured by a lightweight model.
TaskIntent
raw_request / trigger_ref
parsed_identifiers[]
candidate_task_kind
candidate_targets[]
temporal_expression
requested_output
requested_actions[]
context_refs[]
TaskIntent may be ambiguous and grants no execution authority. Deterministic normalization and task_admission first produce an executable TaskContract; RoleRegistry then selects a Role, and ContextBinder builds ContextManifest from TaskContract, Role, and the intent's existing context_refs[]:
TaskContract
task_contract_id / contract_revision
principal / on_behalf_of?
task_kind
target_resources[]
desired_state
evidence_contract
output_contract
temporal_contract
effect_ceiling
delegation_ceiling
completion_predicate
cancellation_semantics
policy_revision
Requested actions and desired state describe intent, not permission. Effect/delegation ceilings are contract upper bounds; every concrete invocation still requires PolicyDecision.
TaskRun is one actual execution. A Case may live for hours or days; one VERIFY, one WATCH wake, or one child enrichment is a distinct TaskRun, and a terminal TaskRun never transitions back to running.
TaskRun
run_id
task_contract_id
case_id?
parent_run_id?
role_id / role_version
context_manifest_ref
status = submitted | queued | running | waiting_input | waiting_dependency
| blocked | completed | failed | cancelled | timed_out
base_context_revision
execution_envelope_ref
result_ref?
stop_reason?
The initial task domain follows Requirements and documents 01–05: lookup/retrieve, version/fix verification, conflict resolution, relation investigation, Incident investigation/watch, research/insight, normative applicability, live asset observation, and M3 EnrichmentTask. Task kinds may evolve, but completion predicates and effect/delegation ceilings must remain mechanically evaluable.
Role is selected after Task
Role is a runtime configuration bundle, not a prompt persona:
RoleProfile
role_id / version
accepts_task_kinds[]
state_model
planner_profile
skill_scope[]
seed_skill_refs[]
mandatory_guard_refs[]
capability_preferences[]
default_execution_profile
delegation_rules[]
v1 fixes two canonical Agent workloads:
| Role | Accepted Task | Domain state | Completion | Delegation |
|---|---|---|---|---|
EnrichmentRole |
background/delegated EnrichmentTask |
M3 EnrichmentState |
required dimensions reach resolved/conflict/unknown; if still missing with no executable path, TaskRun terminates blocked/partial |
no Investigation delegation by default; parallel child operator tasks allowed |
InvestigationRole |
VERIFY / INVESTIGATE / WATCH |
M4 InvestigationState |
TaskContract desired state / evidence sufficiency / explicit blocked | may delegate EnrichmentTask and controlled child execution |
skill_scope defines only the Skill namespaces available to the Role; seed_skill_refs are validated procedural priors discoverable by default; mandatory_guard_refs preserve investigation guards that a Planner may not omit, while still not replacing Policy enforcement. These Skills are not injected wholesale: SkillResolver / ContextMaterializer decides materialization per step. DIRECT / RETRIEVE remain non-Agent fast paths. Reporter/Researcher/Analyst remain Skill/prompt specializations unless later evidence shows an independent state machine and completion semantics.
Reference-preserving Context Handoff
Agents exchange references and revisions by default rather than a prose “handoff summary” as a fact source. Logical context is separate from prompt/KV cache:
ContextManifest
context_id / context_revision
parent_context_id?
task_contract_ref
role_ref
case_ref?
knowledge_revision
investigation_state_ref?
enrichment_state_refs[]
evidence_refs[]
object_refs[] / relation_refs[]
trajectory_checkpoint_ref?
skill_selection_refs[] / experience_pattern_refs[]
policy_context_ref
capability_envelope_ref
budget_ref
cache_hint?
The manifest supports inherit / filter / pin / refresh / diff / fork / merge. A child derives the minimum scope from the parent and returns based_on_context_revision; State/Knowledge gates classify the result as valid / rebase_required / stale / conflict. cache_hint is an optional performance hint that may later map to a prefix/KV-cache handle; it carries neither fact nor permission authority.
ContextMaterializer builds the actual model prompt from Task/Role/current revisions. Summaries are UI/model-compression artifacts only and never replace EvidenceRef, StateRef, ArtifactRef, or SnapshotRef.
Asynchronous multi-loop and duplex Event Plane
Multi-Agent means multiple independently bounded TaskRuns with distinct TaskContract/state scope/capability-policy envelopes cooperating through typed task/event/result contracts and one shared durable world. It does not mean multiple personas chatting.
Internal v1 event contract:
TaskEvent
event_id
task_run_id / parent_run_id?
seq
event_type
producer
base_context_revision
payload_ref
idempotency_key
emitted_at
Minimum event set:
TaskCreated / TaskStarted / TaskPatched / ContextUpdated
EvidenceFound / KnowledgeChanged / EnrichmentStateChanged / InvestigationStateChanged
TaskBlocked / NeedInput / NeedContext / BudgetWarning
ArtifactProduced / Progress / TaskCompleted / TaskFailed / TaskCanceled
Parent→Child may patch priority/context/budget, cancel/resume, or update policy context; Child→Parent may publish progress, blocked/NeedContext, Knowledge/State changes, and typed TaskResult. Each TaskRun owns its Agent Loop; Task/Event/State-Projection loops are independent, and an event never implies a model invocation by itself.
TaskEvent first commits to an append-only PostgreSQL event log, then outbox delivery publishes to Redis Streams on a separate logical redis_task_bus_url. Each TaskRun has monotonic seq ordering; consumers deduplicate by event_id/idempotency key and can replay from the durable log. Celery is not used as pub/sub and Hot Cache Redis does not share Task Event semantics.
External interoperability uses an A2A Adapter: TaskRun lifecycle maps to A2A Task, TaskResult/ArtifactRef to Artifact, and progress/state events to SSE streaming/push updates. TaskContract, ContextManifest, and Capability/Policy refs are exposed through extensions/data parts. Internal runtime does not use A2A Message/Context ID as its Context Store. Standard SSE/push and custom WebSocket bindings are transport/interoperability choices only and do not change the internal Task/Event/Context contract.
Task delegation and Multi-Agent
v1 now fixes one canonical multi-agent workload instead of waiting for an abstract benchmark decision: EnrichmentRole + InvestigationRole. They share Task Runtime / Event Plane / Capability-Policy Control Plane while owning different domain state and completion predicates.
Investigation TaskRun
-> identifies task-relevant enrichment gap
-> delegates EnrichmentTask
-> Enrichment Role reads EnrichmentState / operators
-> Evidence/Knowledge write gate
-> emits EnrichmentStateChanged / TaskResult
-> parent relevance gate refreshes Percept / InvestigationState
The multi-agent unit is an independently bounded TaskRun, not a persona. Multiple EnrichmentTasks may run concurrently on one EnrichmentRole implementation. A third Role is added only if it has an independent TaskContract, state model, completion semantics, capability/policy profile, and can operate from ContextManifest rather than a full parent transcript.
Delegation enforces parent-child ceilings: child effect/delegation/capability/budget/deadline never exceed the parent grant, and child credentials are narrower. Peer/child messages and TaskResults carry sender, task_run_id, context revision, and provenance; internal origin never grants fact or instruction authority.
Cross-Agent handoff prefers ContextManifest + typed TaskResult + Artifact/Evidence/State refs. Natural-language summaries are model/human presentation only, not durable state transfer. If a child returns from an older revision, the parent gate decides valid/rebase/stale/conflict.
ExecutionProfile
Role defines the domain loop; ExecutionProfile defines how expensive one TaskRun may become. v1 keeps five profiles:
| Profile | Agent loop | Default capabilities | Loop | Typical terminal state |
|---|---|---|---|---|
DIRECT |
no | exact/structured/current projection | none | answered / not_found |
RETRIEVE |
no; one synthesis allowed | lexical+dense+metadata+known graph | none | answered / escalate |
VERIFY |
bounded | graph + evidence zoom + primary + optional sandbox | short | verified/conflict/blocked |
INVESTIGATE |
bounded | read perception + delegated enrichment + policy-gated external/sandbox | bounded | success/partial/wait/fail |
WATCH |
short episode per wake | delta/refresh/follow-up | wake→episode→sleep | waiting/escalated/resolved |
The ordinary QA ≤5s target is served by DIRECT/RETRIEVE. Profile escalation creates a new TaskRun/ExecutionEnvelope and recomputes capability visibility, budget, and policy; it cannot silently inherit broader permissions.
M4 Investigation State
M4 exposes two context forms. DIRECT/RETRIEVE fast paths use a read-only ContextView materialized from ContextManifest + Evidence World; a durable Case is created only when unknown/conflict/EvidenceNeed/WATCH state or continuity across TaskRuns must be written. Durable Cases use append-only CaseStateEvent plus materialized InvestigationState. Both forms are served to M6 through the same ContextBinding/State read interface.
Case types and lifecycle
Case is an investigation container spanning TaskRuns; it does not reuse the terminal-state machine of one execution. A durable Case is materialized only when InvestigationState, EvidenceNeed, WATCH, or repeated follow-up continuity is required. DIRECT / RETRIEVE default to TaskRun + ContextManifest only; escalation to VERIFY/INVESTIGATE or durable continuity binds or creates a Case.
Case: created -> active <-> waiting -> resolved -> closed
\-> cancelled
TaskRun: submitted -> queued -> running
-> waiting_input / waiting_dependency
-> completed / failed / cancelled / timed_out / blocked
Persistent Cases may live for hours or days around Incident, patch/advisory, and other world-changing work, while no model process remains alive. Every wake creates a fresh TaskRun and prior TaskRuns remain terminal-immutable. Case reuse is based on target, TaskContract signature, time scope, world/context revision, and freshness; current/live work does not reuse an expired ContextManifest.
InvestigationState
InvestigationState
case_id / case_revision
goal
targets[]
confirmed[]
tentative[]
conflicts[]
unknowns[]
hypotheses[]
open_questions[]
decision_variables[]
evidence_needs[]
active_skills[]
normative_context_refs[]
unresolved_applicability[]
current_decision?
last_world_revision
last_perception_at
For “is vLLM 0.21.0 still affected?”, state can simultaneously contain a GHSA affected range, an OSV candidate fix commit, a tentative commit→PR relation, and the unknown “which release first contains this commit?” The Agent reads and updates these explicit fields instead of reinterpreting the whole token history every turn.
A normative task references M3-structured Requirement / Control plus explicit applicability conditions through normative_context_refs. M4 stores Case-local contextual applicability; not_evaluated / uncertain enters unresolved_applicability and opens EvidenceNeed, while applicable / not_applicable retains supporting system facts and rule revision. M4 does not compile regulatory text into execution restrictions; the Execution Control Plane consumes only RuntimePolicy approved under document 03.
M3 EnrichmentState to M4 EvidenceNeed
M3 background enrichment and M5 active investigation share one Evidence/Knowledge World while keeping state ownership separate. M3 owns the Requirements-frozen four-state EnrichmentState: a canonical dimension is only resolved / conflict / unknown / missing. M4 does not define a parallel EnrichmentRequirement protocol; it projects only TaskContract-relevant missing / conflict / unknown states into Case-local EvidenceNeed. An internal M3 planner may maintain its own processing/enrichment requirements, but those are not the M3→M4 handoff contract. Execution blockage is recorded separately on EnrichmentTask/attempt state and does not extend the semantic status enum.
M3 EnrichmentState
-> task-relevant gap
-> M4 EvidenceNeed
-> InvestigationRole / delegated EnrichmentTask
-> EphemeralObservation
-> AcquisitionService / EvidenceIngress
-> M3 processor / Knowledge write gate
-> EnrichmentStateChanged
-> M4 refresh / resolve EvidenceNeed
missing means the canonical dimension still lacks evidence sufficient for resolved/conflict/unknown; unknown means the relevant evaluator/authority lookup ran and evidence explicitly supports only unknown. If source/policy/credential/budget blocks execution, the dimension remains missing while TaskRun/attempt records blocked_reason and remaining eligible paths. M4 does not automatically spawn one Agent Task for every missing vulnerability dimension; TaskContract determines relevance.
EvidenceNeed
EvidenceNeed is Case-local state for evidence still required by the current Task. M4 creates and maintains it; M5/InvestigationRole resolves it; Perception Runtime and delegated EnrichmentTask use it to select sources/capabilities; M7 evaluates whether the gap was correctly identified and closed.
EvidenceNeed
need_id / case_id
derived_from_enrichment_requirement?
proposition_or_question
purpose
target_objects[]
evidence_contract
preferred_source_roles[]
rejected_evidence_patterns[]
freshness_requirement
completion_predicate
priority
status = open | resolved | blocked | abandoned
resolution_evidence_refs[]
For “which release first contains fix commit abc123?”, tag ancestry, GitHub compare, or a package changelog may satisfy the need; PR merged_at is explicitly rejected because merge time does not establish release containment.
State events and concurrency
Every state change is a CaseStateEvent:
CaseStateEvent
event_id
case_id
base_case_revision
event_type
fact_confirmed | fact_retracted
tentative_added | tentative_removed
conflict_opened | conflict_resolved
unknown_opened | unknown_resolved
hypothesis_added | hypothesis_rejected
evidence_need_opened | evidence_need_resolved
evidence_attached | decision_changed
proposition / target_ref
evidence_refs[]
writer
reason_code
created_at
Writes use optimistic concurrency. Commutative events returned by asynchronous tasks can be rematerialized against the latest revision; mutually exclusive updates to one proposition do not use last-write-wins and instead create conflict or enter State Integration Gate adjudication. M4 current state can be rebuilt from events, so audit and historical replay do not depend on chat transcript.
StatePatch and write gate
Model and Perception Runtime can only propose StatePatch; they cannot mutate InvestigationState directly:
StatePatch
patch_id
case_id
base_case_revision
operations[]
proposition
proposed_state
evidence_refs[]
reasoning_relation?
resolves_need_id?
producer
model_prompt_revision?
State Integration Gate validates object identity, EvidenceRef, source/revision/time alignment, authority requirements, whether the relation is deterministic or inferred, current conflict state, base revision, and write policy.
“release v0.22.0 contains commit abc123” must carry commit/release EvidenceRefs and evidence for release_contains_commit; PR merged_at alone leaves the proposition tentative or keeps the EvidenceNeed open. An external observation that cannot resolve back to an M2/M3 EvidenceRef cannot write a confirmed fact.
M3 semantic candidate -> evidence/write gate -> Knowledge and M4 StatePatch -> State Integration Gate -> InvestigationState use the same ownership: the model proposes semantic candidates; deterministic runtime owns source-of-truth write permission.
World change and state invalidation
A confirmed fact remains scoped to world revision. If KnowledgeChange, incident.changed, source revision, or index revision touches evidence/object used by a Case, State Runtime follows dependency links:
- display-only changes update current projection;
- changes that affect factual support mark the related proposition stale and reopen its EvidenceNeed;
- contradictory evidence opens conflict;
- a
waitingCase can use any of these change events as a wake condition.
A historical answer can still replay against its old Snapshot; a current query reads state after the new world revision. Ordinary QA and continuous watch therefore share one fact lifecycle.
InvestigationSnapshot
At episode start, major state commits, and final Decision, runtime can store a Snapshot pointer:
InvestigationSnapshot
snapshot_id / case_id / case_revision
knowledge_revision
incident_revision
document_index_revision
experience_revision
policy_revision
capability_registry_revision
routing_query_planner_revision
model_revision
prompt_assembly_revision
source_availability_snapshot
created_at
Snapshot stores revision/pointers rather than copying the whole Evidence World. M7 restores what was published, ingested, and accessible at a historical time so a later patch or postmortem cannot leak into an earlier task.
Query Construction and Perception Runtime
After M4 has established current InvestigationState / EvidenceNeed, query and perception decide what to read, where to read it, and at what granularity. Physical retrieval operators only read the M1–M3 Evidence World. Perception Planner composes those operators with controlled external observations and progressive zoom, then emits Percept for M5. This layer has no Knowledge-write authority.
Four query-construction levels
L0 pass-through is used when the original query is already suitable for retrieval, for example RAG poisoning defenses. The raw string goes directly to lexical/dense search or a provider's native full-text search. No “query optimization” model is inserted first, avoiding loss of security identifiers, function names, versions, or user terminology.
L1 deterministic normalization parses stable identifiers, versions, time constraints, and predicates. For “does CVE-X affect vLLM 0.11.0?”, the system first extracts vulnerability, package/version, and affected / fixed predicates, then generates exact, structured, or graph queries. No Agent starts on this path.
L2 semantic query construction handles comparison, compound constraints, cross-source explanation, and open-text tasks. For “what attack-entry and fund-handling patterns does this Bitget incident share with recent similar incidents?”, the model produces target incidents, time range, comparison dimensions, required evidence types, and candidate subquestions; the Query Planner then compiles them into physical queries.
L2 output is constrained by QueryIntent:
QueryIntent
original_text
targets[]
requested_predicates[]
comparison_dimensions[]
time_scope
evidence_requirements[]
candidate_subquestions[]
query_revision
L3 investigation planning derives EvidenceNeed and PerceptionRequest from current InvestigationState and answers “what evidence is still missing, and what should be observed next?” L3 belongs to the M5 loop and does not act as ordinary query rewriting.
The escalation order is fixed: bind object and time; try exact / structured reads; use lexical / dense retrieval for document discovery and semantic neighbors; use graph traversal for object relations; open an EvidenceNeed if a proposition is still unresolved. The Agent investigation loop starts only after escalation to L3.
Physical retrieval routing
Query Planner and Perception Planner share physical read operators but have different responsibilities: the first serves one query construction; the second serves an EvidenceNeed. Routing chooses the narrowest operator that can express the current need.
| Operator | Applicable information | Current implementation / interface |
|---|---|---|
exact |
CVE/GHSA/DOI/SHA/version/IP/domain/address | PostgreSQL index / provider exact API |
structured |
current views, metadata, version range, Incident state | PostgreSQL query |
lexical |
function names, endpoint, package, IOC, technical terms, long-form text | PostgreSQL FTS |
dense |
mechanism similarity, research topic, semantically related documents | pgvector retrieval contract |
graph |
issue–PR–commit–release, dependency, risk/control, evidence relations | Knowledge / structured graph recursive traversal |
evidence |
Claim/Relation→EvidenceRef→locator→artifact | evidence read surface |
external |
latest provider state, Internet assets, missing primary / authority evidence | AcquisitionService / provider adapter |
sandbox |
git ancestry, repo inspection, controlled analysis | Execution Sandbox |
The order is not a fixed pipeline. A strong identifier prefers exact lookup; known-object current state prefers current projection; relation questions prefer graph traversal; document discovery uses lexical/dense retrieval; external access happens only when the local world cannot satisfy freshness or authority requirements; code execution or repository-state verification enters the sandbox path.
Candidate-set assembly
All retrievers emit RetrievedCandidate, preserving object/relation/evidence/document identity, source role, source family, upstream source, revision, valid time, locator, index version, and individual score channels. Retrieval score is a matching signal, not evidence authority.
RetrievedCandidate
candidate_id
candidate_kind
object_id / relation_id / evidence_ref / document_chunk_id
source_id / source_role / source_family / upstream_source
revision
observed_at / valid_time
score_channels
exact / lexical / dense / graph / freshness
locator
index_version
retrieval_run_id
M4/M5 assemble evidence as a set and do not equate relevance-ranked top-k documents with a final evidence set. The assembler checks task coverage, primary / authority requirements, source independence, candidate complementarity, temporal fit, and syndication/duplication. RRF, weighted fusion, cross-encoder, or learned reranking may change, while these evidence-set constraints remain fixed.
Research / Insight retrieval also performs publication resolution. Meeting notes, GitHub guides, and secondary material can discover a paper; title, authors, acceptance status, revision, and actual content return to formal proceedings, DOI, arXiv, or author/institution pages for confirmation. A paper revision is fixed under durable_managed once it becomes part of an investigation, citation, or benchmark.
PerceptionRequest and physical plan
The Agent does not directly emit a BM25 query or provider endpoint. It expresses a cognitive operation:
PerceptionRequest
request_id / case_id / need_id
operation
target
desired_observation
evidence_requirement
time_scope
current_context_refs[]
budget_ref
The first semantic operations are:
inspect: read the current projection of an object;expand: expand a requested relation neighborhood;trace: follow provenance, source, or dependency;zoom: increase read resolution on the same evidence;search: discover an unknown object or document;corroborate: find independent support;contrast: actively seek refuting or conflicting evidence;refresh: re-observe a potentially stale object;observe_external: obtain a current observation absent from the local Evidence World;watch: turn an EvidenceNeed into a future wake condition.
Perception Planner compiles the semantic request into a physical plan. trace(commit abc123 → containing release) may try the local relation graph, GitHub exact lookup, tag / release metadata, then request a git sandbox ancestry check if the relation remains unresolved. Each step declares dependencies, expected output, capability requirement, estimated cost, stop conditions, and fallbacks; the next round can re-plan from the previous Percept.
PhysicalPerceptionPlan
request_id
steps[]
operator
input
dependency
expected_output_type
capability_requirement
estimated_cost
stop_condition
fallback_order
planner_revision
Progressive reads
The same fact is exposed at multiple read resolutions. The Agent starts from low-cost projections and drills down only when conflict, unknown state, staleness, or citation requirements demand it.
| Level | Content | Main use |
|---|---|---|
| L0 | current projection | ordinary query, fast path |
| L1 | Claim / Relation / Incident timeline state | existing fact and relation checks |
| L2 | EvidenceRef, snippet, source alternatives | evidence comparison, citation choice |
| L3 | source section / page / JSON locator | inspect exact context |
| L4 | raw Artifact / complete source revision | inspect complete source, parser verification |
| L5 | external reacquisition / live observation | missing or stale local state |
M7 records every resolution transition so it can distinguish “the world did not contain the evidence,” “the Agent selected the wrong evidence,” “the read resolution was insufficient,” and “Percept compression dropped a critical detail.”
Ephemeral observation and evidence promotion
External providers, browser, sandbox, search results, and peer-agent results first become EphemeralObservation by default. They may guide the next step or create a hypothesis / EvidenceNeed, but cannot directly support an M4 confirmed fact.
EphemeralObservation
observation_id
request_id
capability_id
source / provenance
observed_at
raw_result_ref
extracted_candidates[]
trust_label
ttl
tool/provider output
-> EphemeralObservation
-> Percept
-> discard / zoom / corroborate / promote
-> promotion returns through AcquisitionService / EvidenceIngress
-> fixed source revision + EvidenceRef
-> StatePatch
When an observation must become a durable fact, answer citation, Case confirmed state, benchmark evidence, or reusable relation, it returns through the Acquisition / EvidenceIngress / Knowledge path defined by Technical Design 1, fixes the source revision, and obtains an EvidenceRef. Temporary observation and durable knowledge therefore remain separate; tool output cannot directly contaminate durable Knowledge or InvestigationState.
Percept assembly
Percept is the structured slice of the world actually seen by the Agent in one step; it is not list[RetrievedChunk]. corroborate(fixed_release=0.22.0) may read dozens of candidates underneath, while the resulting Percept keeps independent support, refutation, unresolved questions, freshness, evidence handles, and cost.
Percept
percept_id / request_id
target_refs[]
observed_propositions[]
statement
support_refs[]
refute_refs[]
source_groups[]
freshness
relations[]
timeline_slice[]
unresolved[]
candidate_evidence[]
evidence_handles[]
observation_handles[]
cost
assembler_revision
Percept assembler preserves source_family / upstream_source so syndication is not counted as independent corroboration; revision and valid time so stale evidence is not mixed into a current question; and explicit unresolved items so “not found” is not silently rewritten into “does not exist.”
Cross-document semantic relations
Cross-document enrichment and investigation allow an LLM to propose ClaimCandidate / RelationCandidate from papers, vendor reports, repositories, and Incident evidence. The deterministic layer owns object identity, source attribution, time/version semantics, EvidenceRef binding, and duplicate/conflict detection; the Agent decides which candidates are worth verifying; M4 decides how verified results change the current Case. A candidate cannot become confirmed state before source binding and validation.
This follows the same ownership used by M3 semantic writes: the model proposes semantic relations, deterministic runtime binds them to object/source/revision, and the state layer decides whether the relation is strong enough to change the investigation.
Tool, Capability, and Execution Control Plane
The Agent Security Control Plane from document 04 becomes an executable protocol here. Planner operates on semantic Capability rather than native MCP/OpenAPI/CLI schemas. ToolImplementation says what physical implementation exists; CapabilityContract says what the action means in SecFusion semantics; CapabilityBinding connects the two. Provider, MCP-server, or SDK changes therefore cannot silently redefine Agent actions or security boundaries.
ToolImplementation, CapabilityContract, and Binding
ToolImplementation is a physical implementation record and may represent a local function, retrieval operator, provider API, MCP tool, OpenAPI operation, CLI, browser/computer-use action, sandbox program, or child-task adapter:
ToolImplementation
tool_impl_id / implementation_revision
implementation_kind
native_name
transport
native_input_schema / native_output_schema
server_identity? / server_origin?
auth_class
network_destinations[]
execution_backend?
health_ref
native_schema_hash
implementation_metadata
MCP/OpenAPI/tool annotations assist discovery only and do not automatically become trusted security semantics. Runtime authorizes the stable, versioned CapabilityContract:
CapabilityContract
capability_id / contract_revision
action
applicable_resource_types[]
canonical_input_schema / canonical_output_schema
observation_semantics
effect_semantics
authority_semantics
preconditions[] / postconditions[]
idempotency
reversibility / compensation?
data_ingress_class / data_egress_class
failure_semantics
risk_class
One Capability may have multiple ToolImplementations; one ToolImplementation may expose several restricted Capabilities through different bindings. CapabilityBinding fixes the canonical-to-native mapping:
CapabilityBinding
binding_id / binding_revision
capability_id / contract_revision
tool_impl_id / implementation_revision
canonical_to_native_args
native_to_canonical_result
resource_resolver
effect_resolver
authority_mapper
execution_class
credential_profile
network_profile
sandbox_profile
health_requirement
cost_class / latency_class
fallback_rank
native_schema_hash
A native schema/hash or server-identity change makes the Binding stale; high-impact changes require revalidation or version rollover rather than reusing an old CapabilityContract under the same tool name. Execution classes remain trusted local read, proxied provider read, restricted process, OCI container, microVM, and full VM/browser. Source authority and Tool permission are independent.
CapabilityView and progressive disclosure
capability_visibility computes VisibleCapabilitySet from TaskContract, Role, EvidenceNeed, object/source requirements, effect/delegation ceilings, Policy, budget, credentials/provider health, and sandbox requirements. The model does not receive the full catalog, credentials, server secrets, or native endpoints.
The first disclosure is a lightweight CapabilityCard:
CapabilityCard
capability_id / contract_revision
action
purpose
applicable_resource_types[]
observation_semantics
effect_semantics
authority_semantics
limitations[]
risk_class
cost_class / latency_class
After Planner selects a Capability, ContextMaterializer loads CapabilitySchemaView:
CapabilitySchemaView
capability_id / contract_revision
canonical_input_schema
canonical_output_schema
relevant_preconditions[]
failure_semantics
obligation_hints[]
ToolImplementation, Binding-native schema, credentials, and concrete network/sandbox grants stay outside the model prompt by default. Provider 403/rate limit, missing credentials, health failure, or exhausted budget removes the CapabilityCard from the current view; recovery exposes it through a new revision/view.
CapabilityRequest, InvocationPlan, and CapabilityResult
Planner emits canonical CapabilityRequest, never a raw tool call:
CapabilityRequest
request_id
task_contract_id / task_run_id / case_id?
principal
capability_id / contract_revision
action
resource
canonical_arguments
intended_effect
evidence_purpose
execution_context
Broker resolves Resource/Effect, selects a healthy Binding, and creates an authorization candidate InvocationPlan:
InvocationPlan
invocation_plan_id
capability_request_ref
binding_id / binding_revision
resolved_resource
resolved_effect
canonical_arguments_digest
native_arguments_ref
execution_class
credential_requirement
network_requirement
sandbox_requirement
deadline_at
budget_reservation_ref
capability_visibility only controls whether the model may consider a Capability. After concrete resource/arguments resolution, capability_invocation PolicyDecision runs again. Permit plus satisfiable obligations produces CapabilityInvocation; Identity/Network/Sandbox brokers derive minimum grants and execute the ToolImplementation:
CapabilityInvocation
invocation_id / invocation_plan_id
policy_decision_ref
credential_grant_ref?
network_grant_ref?
sandbox_instance_ref?
started_at
CapabilityResult
invocation_id
status = succeeded | partial | failed | blocked | timed_out
canonical_output_ref?
raw_artifact_ref?
effect_receipt_ref?
observation_class
provenance
latency / cost
failure_code / failure_detail?
CapabilityResult carries no factual authority by itself. Read results first become EphemeralObservation and pass Result/Data/Promotion Policy before EvidenceIngress/M3. Side effects additionally pass effect-receipt/commit gates. Approved Tool does not imply Trusted Output.
PolicyRequest / PolicyDecision
Document 03 RuntimePolicy may contain rule effects such as allow/deny/require_review/require_log; PolicyCompiler turns them at a concrete decision point into authorization plus obligations rather than treating require_log as an authorization result.
PolicyRequest
decision_point
principal
action
resource
context
task_contract_id / task_run_id
via_agent?
parent_execution_id?
capability_id?
arguments_digest?
intended_effect?
evidence_purpose?
world_revision
budget_state
PolicyDecision
authorization = permit | deny | indeterminate
constraints[]
obligations[]
advice[]
matched_policy_ids[]
determining_policy_ids[]
policy_revision
expires_at?
require_human_approval, require_audit_log, sandbox>=container, network allowlist, credential scope, and side-effect staging are obligations/constraints. A permitted action whose obligations cannot be satisfied does not execute.
v1 decision points are task_admission / task_delegation / capability_visibility / capability_invocation / credential_issuance / network_egress / sandbox_selection / side_effect_commit / observation_promotion / state_patch_commit / child_execution / watch_resume. Authorization, capability, data/evidence, side-effect, sandbox/network, delegation, and budget policy may share Policy IR while retaining distinct enforcement points and input types.
Three invariants become concrete protocol:
Budget != Permission
Source Authority != Tool Permission
Approved Tool != Trusted Output
Sandbox runtime selection and configuration
Sandbox substrate is no longer postponed until late implementation. v1 fixes:
process_restricted / container_standard: OpenShell as sandbox supervisor/enforcement runtime; OCI workload through Docker or Podman. SecFusion PolicyEngine authorizes task/action/resource, while SandboxBroker compiles approved filesystem/network/credential obligations into OpenShell policy; OpenShell does not decide whether the business Task itself is authorized. Defaults: non-root, dropped capabilities,no_new_privs, constrained filesystem, default-deny network, credentials injected by supervisor/gateway for approved destinations; Agents never read raw secrets.microvm_untrusted: Firecracker for high-risk arbitrary code / untrusted repo / PoC fixtures. KVM/host support is required; when unavailable, returnsandbox_unavailable/ human review rather than silently downgrade to a normal container.fullvm_browser: interface retained but not a v1 required substrate; browser/computer-use receives a separate probe before entering this profile.- DSec remains an architecture reference for multi-backend lifecycle/image/elastic scheduling rather than a hard runtime dependency of this repository.
Upper layers see only SandboxProfile:
SandboxProfile
profile_id / revision
isolation_class
none | process_restricted | container_standard
| microvm_untrusted | fullvm_browser
backend
image_ref_or_digest
run_as_uid_gid
cpu_limit / memory_limit / pids_limit
wall_timeout
rootfs = read_only | overlay
writable_paths[]
readonly_mounts[]
seccomp_profile
landlock_profile
linux_capabilities[]
no_new_privs
network_mode = deny | allowlist | proxied
allowed_destinations[]
credential_injection = none | gateway
artifact_export_policy
teardown_policy
Initial deployment config uses a dedicated block; numeric limits remain deployment values rather than Requirements:
sandbox:
provider: openshell
container_runtime: docker # podman allowed
default_profile: container_standard
profiles:
process_restricted:
network: deny
rootfs: read_only
container_standard:
network: proxied
rootfs: read_only
writable_paths: [/workspace, /tmp]
capabilities: []
no_new_privs: true
microvm_untrusted:
backend: firecracker
require_hardware_virtualization: true
fallback: deny
Images are pinned by digest. Imported workspace/artifacts remain untrusted. Docker socket, host credential store, host network, and arbitrary host mounts never enter the Agent namespace. Sandbox config revision is recorded in ExecutionEnvelope, Trajectory, and M7 replay.
ExecutionEnvelope and budget propagation
Every Agent episode, Perception action, RPC, and child execution runs inside ExecutionEnvelope:
ExecutionEnvelope
execution_id / parent_execution_id
task_contract_id / task_run_id
case_id?
role_revision
context_manifest_revision
execution_profile
capability_scope
deadline_at
budget_ref
policy_revision
identity_scope
network_policy
side_effect_policy
sandbox_profile_revision
trace_context
deadline_at is absolute. A child timeout is the minimum of its local maximum and parent remaining time; retries, provider fallback, sandbox steps, or subagents never receive a fresh root budget. This is what lets “every RPC has a timeout” compose into “the whole operation is bounded.”
TaskRun is the basic execution budget account. A persistent Case may additionally hold an aggregate CaseBudget across wake episodes, while DIRECT/RETRIEVE/EnrichmentTask without a Case do not depend on it:
CaseBudget? # optional aggregate for persistent Case
-> TaskRunBudget
-> ActionBudget
-> RPCAttemptBudget
Parent TaskRunBudget
-> Child TaskRunBudget # delegation reserve
Initial resource dimensions include wall time, model tokens, agent turns, tool calls, RPC calls, retries, external cost, bytes read, concurrency, and recursion depth. Every TaskRun receives an explicit budget account. Concurrent work or a child TaskRun reserves from its parent TaskRun/Case aggregate before launch; actual consumption is committed and unused reservable quota is released. Consumed wall time, provider token/cost, and RPCs are not refunded, and total child reservations cannot exceed the parent's remaining budget.
budget_exhausted is a normal domain outcome. Runtime preserves already-confirmed facts, marks unresolved EvidenceNeeds blocked/partial, and stops further perception. M6 can then state which conclusions are verified and which verification was terminated by budget.
Skill and Experience Runtime
Skill stores reusable investigation procedure; Capability stores the semantic contract of an executable action; Experience stores condition-bound success, failure, and fallback patterns from prior executions. Skill/Experience influence how to investigate and carry no factual authority or Policy authority. The runtime uses progressive disclosure: a Role may own a broad Skill scope, while the model sees only lightweight manifests relevant to the current task and loads procedure, current step, or provenance only when needed.
Skill objects and seeded skills
Skill is split into four objects so applicability, procedure, trajectory history, and prompt text do not collapse into one large document:
SkillManifest
skill_id / version
status = candidate | validated | active | superseded | deprecated
source_type = seeded | experience_derived | imported
task_patterns[]
evidence_need_patterns[]
applicable_object_types[]
applicability_conditions[]
required_inputs[]
required_capability_classes[]
optional_capability_classes[]
expected_outcomes[]
risk_hint / cost_hint
procedure_ref
provenance_ref
validation_ref
supersedes?
SkillProcedure
skill_id / version
steps[]
evidence_expectations[]
failure_guards[]
fallbacks[]
stop_conditions[]
budget_profile?
SkillStepFragment
skill_id / version / step_id
semantic_instruction
required_state_refs[]
required_capability_classes[]
success_predicate
failure_predicate
fallback_refs[]
SkillProvenance
origin
supporting_trajectory_refs[]
supporting_experience_pattern_refs[]
validation_case_refs[]
promotion_history[]
A procedure contains semantic steps such as “inspect the fix commit” or “trace which release contains that commit,” not REST endpoints, MCP tool names, or CLI commands; Capability Binding owns physical execution. Initial seeded Skills come from repeatedly validated investigation rules in the current project: VerifyFixBoundary, ResolveSourceConflict, TraceIncidentEvidence, AssessAffectedDeployment, and AssessApplicability. Stable negative knowledge is preferably seeded as guards: PR merged_at does not establish release containment, public PoC does not establish known exploitation, absence does not imply not_affected, and a shared CDN-edge observation does not establish asset ownership. Seeded procedure is a prior; a Skill still passes conformance/replay validation before becoming active.
Skill discovery and progressive disclosure
SkillResolver consumes TaskContract, RoleProfile skill_scope, current EvidenceNeed / InvestigationState signature, visible Capability classes, and budget. It retrieves SkillManifest first and never expands the entire Skill library:
Task / Role / EvidenceNeed / State
-> manifest retrieval
-> SkillCard shortlist
-> selected SkillProcedure
-> current SkillStepFragment
-> Provenance only on failure / ambiguity / eval / debug
Four disclosure levels are fixed. manifest exposes purpose, applicability, expected outcome, risk/cost, and required capability classes. procedure loads after the Planner selects a Skill. step injects only current local instruction, evidence expectation, guard, and fallback. provenance stays out of the online prompt by default. mandatory_guard_refs allow a guard to enter ContextMaterializer without loading the full procedure, but guards remain planning constraints rather than permission enforcement.
SkillSelection
selection_id
task_run_id
candidate_skill_refs[]
selected_skill_ref?
disclosure_level
selection_reason
state_signature
capability_view_revision
Skill version, materialization level, selection reason, and content hash enter PromptAssembly/Trajectory. M7 can then distinguish wrong Skill selection, defective procedure, and a correct Skill blocked by Capability/Policy availability.
Experience compression and Skill evolution
Trajectory is raw execution history and is never directly a Skill. Experience compression preserves condition/action/outcome structure rather than summarizing many trajectories into prose:
Trajectory
-> ExperienceCandidate
-> condition/action/outcome normalization
-> ExperiencePattern
-> SkillPatchCandidate | SkillCandidate
-> M7 replay / regression
-> validated / active SkillVersion
ExperienceCandidate
task_signature
state_signature
evidence_need_signature
action_sequence[]
capability_refs[]
observed_outcomes[]
failure_points[]
fallback_taken[]
stop_reason
trajectory_ref
ExperiencePattern
pattern_id / version
condition_signature
reusable_procedure_fragment?
failure_guard_candidate?
fallback_candidate?
stop_condition_candidate?
capability_preference_candidate?
support_refs[]
counterexample_refs[]
Several Experiences may produce a new procedure or only patch an existing Skill's failure guard, fallback, stop condition, or capability preference. A model may propose SkillCandidate / SkillPatchCandidate but cannot promote it to active Skill. M7 performs replay, multi-Case validation, and regression under fixed world/model/task/budget. Clustering algorithm, minimum support, promotion threshold, and automated-vs-human approval ratio remain implementation/evaluation decisions rather than TD2 constants.
The Experience Store defined by TD1 continues to persist versioned investigation memory, applicability, recommended actions, and outcomes; this section does not retire that layer. ExperienceCandidate / ExperiencePattern are intermediate structured representations used to extract and compress Trajectory/Experience, while Skill is the procedural layer promoted through stricter replay/regression for progressive runtime disclosure and execution reuse. An active Experience may affect Skill retrieval/ranking or remain a planning prior indefinitely; it is not forced to become a Skill.
Experience retrieval supplies procedural prior only. Facts, source authority, and evidence relations for the current Case are reacquired through Evidence World/Perception; a historically successful trajectory is not current evidence.
Runtime Context Materialization
ContextManifest is durable, inheritable logical context. This section defines only how one TaskRun/step materializes its references, Skills, and Capabilities into model input. ContextMaterializer cannot expand Task/Policy authority and cannot promote summaries, Skill text, or Tool descriptions into factual sources.
Prompt layering
From stable to dynamic, composition is: platform invariants; TaskContract / Role / ExecutionProfile; compiled policy context; currently selected Skill disclosure; current Capability disclosure; InvestigationState / EvidenceNeed / Percept; then the current step/goal and newly produced EphemeralObservation. Policy context explains constraints to the model; concrete invocation authorization is recomputed at execution time.
MaterializedFragment
fragment_id
kind
source_ref / source_revision
disclosure_level?
selection_reason?
trust_class
cache_class = static | task_stable | state_dynamic | ephemeral
content_hash
Lower-layer external content, Skill text, Tool descriptions, and peer-Agent messages cannot overwrite platform invariants. Free-text last-write-wins is not a context-merge rule; every fragment retains source/revision/hash.
Progressive Skill / Capability disclosure
The default prompt carries only a small set of SkillManifest/CapabilityCard objects. After the Planner selects a Skill, SkillProcedure is loaded; at execution time only the current SkillStepFragment is injected. After the Planner selects a Capability, CapabilitySchemaView is loaded. SkillProvenance, native ToolImplementation schema, Binding, credentials, and network/sandbox grants stay out of model context by default.
This controls both token cost and attack surface: a large MCP server does not expand hundreds of native tools into the prompt, and an Experience library does not inject complete historical trajectories. Selection failure, current-step failure, M7 replay/debug, or explicit diagnostics may load deeper provenance/implementation information.
PromptAssembly and cache partitioning
PromptAssembly
assembly_id
execution_id
task_contract_id / task_run_id
role_revision
context_manifest_revision
platform_invariant_revision
execution_profile_revision
policy_context_revision
materialized_skill_refs[]
materialized_capability_view_refs[]
state_projection_revision
percept_refs[]
materialized_fragment_refs[]
materialized_ref_set_digest
ordered_fragment_ids[]
cache_handle_hints[]
assembly_hash
static fragments suit platform/Role immutable prefix; task_stable may contain TaskContract, selected Skill manifests/procedures, and stable CapabilityCards; state_dynamic carries InvestigationState, EvidenceNeed, and Percept; ephemeral carries current observations/tool results. cache_handle_hints may later map to prefix/KV caches, but cache hit/miss affects performance only and never determines Context revision, factual freshness, or permission.
Prompt constraints are instructions. Real boundaries remain enforced by TaskContract, Capability/Policy, Network/Sandbox, and State/Knowledge gates. A prompt saying “no network” does not replace Network Gateway.
M5 Investigation Runtime
M5 handles only active-investigation profiles VERIFY / INVESTIGATE / WATCH. One episode is a recoverable bounded state machine: it reads the current Case and Snapshot, selects an EvidenceNeed, resolves applicable Skill / Experience, computes current capabilities, performs perception, writes state, then decides to continue, wait, or stop. The model may adapt the path, but every step stays inside explicit state, capabilities, and budget.
One episode
An InvestigationRole episode follows this protocol chain. The Planner only proposes what to do next; real action must bind to CapabilityRequest and pass invocation policy.
TaskContract + ContextManifest + InvestigationState
-> select task-relevant EvidenceNeed
-> resolve SkillManifest shortlist / selected SkillProcedure or StepFragment
-> compute policy-filtered CapabilityCard set
-> Planner proposes PerceptionRequest / CapabilityRequest / delegate / wait / stop
-> compile PhysicalPerceptionPlan when perception is needed
-> load selected CapabilitySchemaView
-> resolve CapabilityBinding / InvocationPlan / Resource / Effect
-> invocation PolicyRequest
-> PolicyDecision + obligations
-> reserve budget / derive credential / network / sandbox grant
-> execute CapabilityInvocation or child TaskRun
-> CapabilityResult / EphemeralObservation / TaskEvent
-> result & promotion policy
-> Percept
-> optional M2/M3 Evidence/Knowledge promotion
-> propose StatePatch
-> State Integration Gate
-> evaluate TaskContract completion predicate
EvidenceNeed selection follows TaskContract desired state and priority, then checks whether any current capability can satisfy the evidence contract. A need requiring primary evidence remains open/blocked when only secondary material exists. The Planner may process another need, delegate EnrichmentTask, or enter waiting_dependency / waiting_for_world_update.
SkillResolver first discovers lightweight manifests; only the selected procedure/current step enters context. Capability visibility likewise exposes Cards before loading SchemaView for a selected action. Capability Binding/Policy determines physical implementation and whether the real action may occur. Skill deviation, delegation, policy decisions, Context revisions, and child TaskResults all enter Trajectory so M7 can distinguish adaptation, Skill gaps, Planner error, and protocol error.
TrajectoryEvent minimally records task_run_id / parent_run_id / base_context_revision / state_before_after / evidence_need / skill / perception / capability_request / policy_decision / child_task_ref / observation / state_patch / budget / latency / stop_reason; large outputs remain ArtifactRefs.
Bounded loops
Agent turn is only one loop in the system. Retrieval expansion, source fallback, Incident follow-up, retry, repo traversal, subagent, and Experience replay all use one BoundedLoop contract:
BoundedLoop
loop_id
execution_id
max_iterations
deadline_at
budget_ref
progress_predicate
no_progress_limit
stop_predicate
A timeout on each primitive does not imply a bounded overall operation, and a per-batch limit does not prevent multi-round, fan-out, retry, or recursive child calls from multiplying cost. All loops therefore inherit the root ExecutionEnvelope absolute deadline and hierarchical budget and report no-progress uniformly.
This directly absorbs the OpenViking #4504 replay lesson: an RPC timeout and a per-batch replay limit do not bound the user-visible operation. maxItems / maxRounds + timeBudgetMs + structured progress still require operation-level total-time / batch budgets; SecFusionAgent therefore propagates budget through the entire execution tree rather than limiting only the innermost call.
Progress and stop
Progress is a state delta, not another model paragraph. Initial progress_delta uses five signals:
- open / resolved EvidenceNeed count changed;
- confirmed / conflict / unknown changed;
- a key decision variable converged;
- new independent evidence satisfying the evidence requirement arrived;
- world revision changed with new actionable information.
After no_progress_limit consecutive zero-progress rounds, the loop stops and chooses fallback, waiting, or partial termination. Every loop returns a structured stop reason:
stop_reason
goal_satisfied
evidence_sufficient
budget_exhausted
deadline_reached
provider_blocked
capability_denied
policy_denied
external_failure
no_progress
waiting_for_world_update
human_review_required
High-impact judgment, long-lived source conflict, uncertain normative applicability, or runtime policy requiring manual confirmation moves the Case to human_review_required. Analyst adjudication is written back as a StateEvent / Decision event carrying actor, time, and evidence references; out-of-band database edits do not override investigation state.
Continuous watch
A WATCH Case does not keep a model session running. In waiting, it persists open EvidenceNeeds, wake conditions, next_poll_at, last world revision, expected sources/capabilities, and remaining CaseBudget. A scheduler, source delta, Incident material change, new official publication, or time condition starts a short episode.
Each wake reads only changes after the last Snapshot:
waiting
-> wake(event / time / source change)
-> read delta since last snapshot
-> short investigation episode
-> commit state change
-> resolved / escalated / waiting
An Incident may have three unknowns at T0 from a breaking signal: authenticity, impact scope, and root cause. T1 vendor confirmation closes authenticity; T2 forensic/on-chain evidence updates impact and opens an attack-path question; T3 advisory/CVE links the vulnerability; T4 a patch starts fix verification; T5 postmortem closes root cause and produces Insight / Experience. No single LLM session needs to stay alive for days.
M6 Decision and QA
M6 reads current M4 state and does not directly query raw storage or invoke external tools. DIRECT / RETRIEVE enter M6 through lightweight Context; VERIFY / INVESTIGATE enter the same Decision Runtime after state update. If state is insufficient, M6 emits ContinuationRequest / EvidenceGapRequest only; M4 State Runtime validates/deduplicates and creates EvidenceNeed, then Task Runtime selects InvestigationRole or delegated EnrichmentTask. M6 has no state-write authority.
DecisionResult
decision_id
case_id / case_revision
conclusions[]
statement
type = fact | inference | recommendation
evidence_refs[]
reasoning_relation_refs[]
conflicts[]
unknowns[]
assumptions[]
citations[]
answer_payload
stop_reason
model_prompt_revision
A fact must trace to an M2/M3 evidence-backed Claim / Relation. An inference preserves intermediate relations and supporting evidence. A recommendation cannot masquerade as a normative requirement. Source conflict, insufficient evidence, provider blockage, and budget/deadline exhaustion remain conflict / unknown / partial rather than being completed into certainty by the language model.
Citation binder attaches each conclusion to EvidenceRef and locator. Multi-hop questions preserve intermediate relations. Follow-up questions on the same object use ContextBinding to keep object, revision, time scope, and already-confirmed constraints consistent. Chat, report, API, and timeline UI are presentation adapters over DecisionResult.
End-to-end paths
The six paths below cover exact lookup, ordinary retrieval, active verification, persistent Incident work, normative knowledge, and current external observation. They also form the first integration/evaluation cases.
Exact vulnerability field
For “what is the CVSS of CVE-X?”, deterministic parsing produces TaskIntent and task admission creates a DIRECT TaskContract/TaskRun that reads current_vulnerability_view. If the projection satisfies freshness, M6 binds the EvidenceRef through ContextManifest and returns; no durable Case, Agent, or external provider is required. On projection miss, the TD1 read path checks durable Knowledge; if a current external observation is actually required, an escalated TaskRun is created with a newly computed capability/policy envelope.
Research retrieval
“Which studies cover RAG poisoning defense?” uses a RETRIEVE TaskRun. The raw query enters L0 lexical + dense retrieval; Candidate Assembler builds a document set using topic coverage, publication status, source independence, and time range, followed by at most one synthesis step. A follow-up such as “which defense remains effective under adaptive attack?” becomes a new TaskIntent admitted as a VERIFY / INVESTIGATE TaskContract; M4 binds/creates a Case and opens EvidenceNeeds for concrete threat model, adaptive evaluation, and independent evidence rather than merely increasing top-k.
Fix-version verification
“Is vLLM 0.21.0 fixed?” uses L1 to parse CVE, package, and version, then reads current affected/fix projections, OSV fixed commit, and the GitHub graph. If release containment is already established, the task can terminate. If only a candidate fix commit is known, M4 opens EvidenceNeed first_release_containing(commit).
VerifyFixBoundary recommends local graph → GitHub commit/release → git ancestry → package changelog. capability_visibility derives VisibleCapabilitySet from TaskContract, provider health, budget, and sandbox availability; after the Planner binds a concrete CapabilityRequest, invocation policy evaluates it again. Primary evidence must pass EvidenceIngress/Knowledge gates before StatePatch can cite it; State Integration Gate then validates object/version/EvidenceRef and closes the unknown. PR merged_at remains tentative and cannot establish release containment.
Persistent Incident investigation
A breaking signal first forms an IncidentCandidate in M1–M3. User interest, promotion, or watch criteria create a persistent Case containing open questions for authenticity, impact scope, root cause, fund flow, and fix/recovery. Each source delta wakes only a short episode; M5 prioritizes EvidenceNeeds affected by material change; primary / forensic / authority follow-up routes by source role; syndication is collapsed by source_family / upstream_source.
After the event ends, postmortem can enter Insight Corpus and the complete investigation Trajectory enters Experience Evolution. Historical Case state and Timeline remain replayable from Snapshot.
Normative applicability
“Does this Agent application satisfy Requirement X?” first reads M3 Requirement / Control plus applicability conditions, then the current M4 contextual-applicability state. An evidence-backed applicable / not_applicable result may proceed to M6; not_evaluated / uncertain causes M4 to open EvidenceNeed, and AssessApplicability specifies the required system facts, scope, and exception conditions.
Regulatory/standards text remains evidence data. Only RuntimePolicy that passed document 03 policy compilation/approval enters the Execution Control Plane. M6 output distinguishes binding requirement, control recommendation, and system inference.
Current Internet-asset observation
“Which public assets may currently expose the affected version?” is current / live. Local Knowledge can provide product/version → fingerprint mapping but cannot represent current asset state, so the task requires external observation. Censys / Shodan / FOFA / ZoomEye enter the current capability set according to credential and provider health. Results first become EphemeralObservation carrying query, filter, observed_at, and mapping version.
Only observations used as citations or durable InvestigationState are promoted through EvidenceIngress. M6 retains observation time and mapping version so one point-in-time observation never becomes a permanent fact.
Data storage and recovery
The first version adds no new database product but adds a third logical Redis role. PostgreSQL stores durable Task/Case/Context revisions, the TaskEvent log, EvidenceNeeds, snapshots, Skill/Experience, Trajectory, execution metadata, and materialized state. PostgreSQL FTS/pgvector continue retrieval. Redis is split into Celery broker, M1–M3 Hot Cache, and Task Event Streams logical endpoints/DBs without sharing semantics. S3-compatible ArtifactStore stores large tool/browser/sandbox output and durable raw artifacts.
Durable objects are separated by responsibility:
| Object | Store | Key content |
|---|---|---|
task_contracts / task_runs |
PostgreSQL | principal, desired state, effect/delegation ceiling, completion, parent-child, status |
task_events |
PostgreSQL append-only + Redis Streams delivery | task-local seq, event type, context revision, payload ref, idempotency |
context_manifests |
PostgreSQL | Task/Case/Knowledge/State/Evidence/Artifact refs and revisions |
investigation_cases |
PostgreSQL | Case lifecycle, targets, current task refs, initial_world_revision |
case_state_events |
PostgreSQL, append-only | base_revision, event_type, proposition, evidence_refs, writer, reason |
investigation_state_current |
PostgreSQL, materialized state | confirmed, conflicts, unknowns, needs, current_decision |
evidence_needs |
PostgreSQL | proposition, requirements, priority, status, resolution evidence |
investigation_snapshots |
PostgreSQL, revision pointers | knowledge / index / incident / experience / policy / capability / model revisions |
perception_events |
PostgreSQL | request, plan, observation/percept refs, cost, result |
execution_runs |
PostgreSQL | envelope, parent execution, deadline, stop reason, latency |
budget_ledger |
PostgreSQL + run-local cache | reserve / commit / release, resource type, parent-child relation |
capability_invocations |
PostgreSQL audit | capability version, args digest, policy decision, result ref |
skill_versions |
PostgreSQL | applicability, procedure, failure/fallback, validation state |
trajectories |
PostgreSQL + ArtifactStore refs | state before/after, action, tool, percept, cost, outcome |
Large raw output is not stored directly inside a trajectory row. Runtime writes it to ArtifactStore and stores a reference in StateEvent, PerceptionEvent, or TrajectoryEvent. case_id / execution_id / parent_execution_id join state events, budget ledger, and capability invocations so M8 can trace a DecisionResult back to EvidenceRef, concrete tool calls, consumed budget, and world revision.
This does not create a second usage truth. Trajectory/TrajectoryEvent latency/cost fields are execution summaries and join coordinates: exact model token/cache/attempt facts belong to ModelAttempt/ModelUsage; reserve/commit/release authority belongs to budget_ledger; actual external Capability calls and any exact cost they expose belong to capability_invocations. M7/M8 may aggregate these owners into trajectories/reports but must not write summary values back as provider usage or budget truth.
Both Case state and execution state must be recoverable. A worker crash after committing a state event does not lose confirmed facts; unfinished perception work retries according to execution state and idempotency keys. WATCH wake conditions, next_poll_at, and open EvidenceNeeds are durable so scheduling survives process recovery. Consumed budget and capability invocations are persisted enough to prevent recovery from resetting budget or reissuing high-cost side effects.
Failure and recovery
Recovery depends on failure type, tool idempotency, and current state rather than one global retry count.
| Situation | State change | Default behavior |
|---|---|---|
| exact / structured miss | EvidenceNeed remains open | expand to lexical/graph; access external source only when current evidence is required |
| provider 403 / blocked | capability unavailable | update provider health, remove from catalog, choose independent fallback |
| rate limit | capability temporarily unavailable | honor Retry-After; defer if budget permits or switch provider satisfying the same evidence requirement |
| missing credential | capability denied | do not auto-retry; use a credential-free path or finish partial |
| source conflict | conflict opened | contrast / corroborate, preferring primary / authority evidence |
| stale world revision | used proposition marked stale | refresh; reopen EvidenceNeed when necessary |
| tool timeout | invocation failed | retry only safe/idempotent capabilities according to retry policy |
| non-idempotent side effect has unknown result | effect unknown | stop automatic retry; enter reconciliation / human review |
| sandbox failure | capability failed | record substrate failure; choose lower-risk fallback or finish partial |
| budget/deadline exhausted | unresolved marked blocked | retain confirmed state, emit partial DecisionResult, do not guess remaining conclusions |
| no progress | loop stopped | fallback, waiting, or partial |
| policy deny | capability denied | preserve denial reason; prompt cannot bypass it |
| human review required | Case waiting | resume after analyst event is written back |
All retries reuse the original idempotency key and parent ExecutionEnvelope; evidence obtained from another source still re-enters through M2 EvidenceIngress. Fallback does not silently weaken EvidenceNeed requirements. If GitHub primary source is unavailable, a secondary blog may add tentative information but cannot satisfy “primary confirmation required.”
Provider health is an input to capability visibility. Repeated 403, authentication failure, rate limit, or timeout removes the corresponding CapabilityContract from the current VisibleCapabilitySet and changes the Planner's next action; recovery can restore it. Failure therefore changes execution planning rather than remaining only a log entry.
M7 Replay and evaluation
M7 evaluates both domain outcome and runtime protocol rather than treating final-answer error as the only signal. A fixed case stores TaskContract, ContextManifest, world/time cutoff, source availability, Enrichment/Investigation state, capability/policy/sandbox revisions, model/prompt/skill versions, and expected protocol outcome. Snapshot + Trajectory + TaskEvent checkpoint supports intervention replay from any step.
Failure attribution expands to:
availability
-> enrichment-gap identification
-> task/role routing
-> capability visibility/binding
-> policy/obligation enforcement
-> perception selection/compression
-> state/knowledge integration
-> evidence use
-> decision
Formal M3 enrichment P/R remains owned by Requirements/TD1 through EnrichmentFactKey and micro/dimension-macro metrics. TD2 adds active-enrichment/agent-runtime metrics: critical-gap recall, useful-acquisition precision, final canonical enrichment completeness, wrong-entity/version attachment, redundant acquisition, delegation correctness, context-reuse efficiency, stop correctness, latency, and cost.
Before model-quality evaluation, build a deterministic 30–50 case conformance suite:
- TaskContract admission / completion / cancellation;
- Role acceptance and TaskRun state transitions;
- ContextManifest inherit/filter/fork/rebase/stale conflict;
- TaskEvent ordering/idempotency/replay and parent-child duplex update;
- Capability binding, visibility, invocation policy;
- authorization vs obligation enforcement;
- delegation/effect/budget/deadline ceilings;
- sandbox-profile selection and fail-closed downgrade;
- EphemeralObservation promotion;
- StatePatch authorization;
- WATCH resume and world-change wake;
- Skill-manifest retrieval, procedure/step disclosure, and mandatory-guard materialization;
- ExperiencePattern → SkillPatchCandidate replay, counterexamples, and regression gates;
- CapabilityCard / SchemaView disclosure and Binding schema-drift detection.
Strategy research then compares raw retrieval, progressive zoom, gap-driven, skill-guided, single-loop, and multi-loop/delegated enrichment under the same world/model/task/budget. A schema that cannot mechanically predict conformance outcomes does not enter main implementation.
Security evaluation covers prompt injection, poisoned source, malicious tool output, MCP schema change, memory/state poisoning, inter-agent trust propagation, context-handoff pollution, capability escalation, sandbox/network escape, credential/side-effect misuse. Model defense and substrate enforcement are reported separately.
M8 Operations and observability
Every Case, Execution, Perception, Capability invocation, and RPC shares trace context. Minimum telemetry is:
case_id / task_contract_id / task_run_id / parent_run_id
execution_id / parent_execution_id
context_revision / role_revision / execution_profile
state_revision_before / state_revision_after
evidence_need / perception_request / physical_plan
eligible_capabilities / selected_capability
policy_decision
budget_reserved / budget_consumed / budget_released
model_tokens / tool_calls / rpc_calls / retries
network_destination / sandbox_profile_revision / sandbox_backend
observation_refs / percept_id / evidence_refs
stop_reason / failure_class
latency / external_cost
Secret values do not enter traces; credential use records identity, scope, and audit event only. Policy, Skill, Capability Registry, PromptAssembly, model/provider revision all participate in deployment versioning. Sanitized production failures become M7 regression cases; CI replays affected fixed cases whenever these components change version.
M8 also owns system health for provider status, Celery queue, Task Event Stream lag, TaskRun wake latency, Context stale/rebase rate, abnormal budget consumption, sandbox create/teardown failures, Network Gateway denies, outbox backlog, and replay failures. Business failures and infrastructure failures use different failure classes so “evidence does not exist” is not conflated with “provider is down.”
Interfaces
Stable v1 ports expose Task/Context/Capability/Policy boundaries without leaking physical providers or transports upward. The list below also reflects current implementation owners; a conceptual port does not need to become a same-named god service:
TaskIntentParser.parse -> TaskIntent
TaskContractService.admit -> TaskContract
canonical_roles -> RoleProfile
domain admission compiler + Context service -> ContextManifest
ContextMaterializer.materialize -> PromptAssembly
create_task_run / transition_task_run / create_child_task_run / update_task_context
append_task_event / list_task_events
dispatch_pending_task_events / read_task_event_messages / ack_task_event_message
A2AAdapter.export / import
PerceptionPlanner.plan -> PhysicalPerceptionPlan
PerceptionRuntime.execute -> Percept
InvestigationStateService.open_evidence_need / apply_patch / commit_decision / get_state_at_revision
SkillStore.search_manifests / get_procedure / get_step / get_provenance
SkillResolver.resolve -> SkillSelection
ExperienceStore.retrieve_patterns
ExperienceCompressor.extract / merge / propose_patch
CapabilityRegistry.visible_capabilities / schema_view / resolve_binding
CapabilityBroker.invoke
PolicyEngine.evaluate -> PolicyDecision
BudgetGovernor.reserve / commit / release
SandboxBroker.create / exec / export / destroy
InvestigationRoleRuntime.run
TrajectoryStore.start / append_event / finish
DecisionService.decide -> DecisionResult
ReplayCheckpointService.capture / prepare
M7ReplayService.compare
SkillPromotionGate.evaluate / promote
TaskContract patch/cancel are lifecycle operations over an existing contract/run rather than methods on the admission service. L0/L1 query normalization and physical read planning are currently split across TaskIntentParser, packages.intelligence.retrieval, and investigation.perception; no empty QueryConstructor package is created merely to mirror the design diagram. A separate query owner should appear only if L2/L3 planning gains independent state/evaluation.
Both M3 EnrichmentRole evidence acquisition and M5 InvestigationRole external observation reuse TD1 AcquisitionService / EvidenceIngress / Knowledge Writer; there is no Agent-only network/write side channel. ModelProvider receives ContextMaterializer output only and owns no source authority, credential, or durable state-write permission.
Repository mapping
Implementation separates ownership while allowing Roles to share runtime:
packages/
├── enrichment/
│ ├── runtime/ # EnrichmentRole adapter / EnrichmentTask planner
│ └── ... # existing M3 operators/processors/state owner
│
├── investigation/
│ ├── perception/
│ ├── state/ # M4 InvestigationState / EvidenceNeed / Gate
│ ├── skills/
│ ├── runtime/ # InvestigationRole episode / WATCH
│ ├── cases/
│ ├── trajectory/
│ ├── experience/
│ └── replay/ # M7 checkpoint / historical M4 reconstruction
│
├── task_runtime/
│ ├── contracts/ # TaskIntent / TaskContract / TaskRun / RoleProfile
│ ├── admission/ # TaskIntent -> domain compiler -> policy-admitted TaskContract
│ ├── context/ # ContextManifest / materializer / revision handling
│ ├── events/ # durable TaskEvent + Redis Streams adapter
│ ├── scheduler/ # run/dependency/wake/delegation
│ └── a2a/ # external A2A compatibility adapter
│
├── runtime/
│ ├── capability/ # ToolImplementation / CapabilityContract / Binding / View / Request / Result / Broker
│ ├── policy/ # PolicyRequest / Decision / obligation enforcement
│ ├── budget/
│ ├── sandbox/ # OpenShell adapter / Firecracker adapter / profiles
│ ├── execution/ # ExecutionEnvelope lifecycle / bounded loop
│ └── artifacts/ # runtime artifact != Evidence
│
├── reasoning/
├── decision.py
├── citation.py
└── model.py
│
└── evaluation/
├── m7_replay.py
└── skill_promotion.py
runtime/identity, runtime/network, and an independent runtime/audit package are not physically split yet: their constraints already travel through ExecutionEnvelope, Policy, Sandbox, and owner-local durable audit records. Empty packages are not created before they own an independent lifecycle. apps/api remains an HTTP/application-composition boundary; its local Runtime Workbench composes existing Case/Admission/Decision gates and does not own domain write authority. apps/worker handles coarse-grained task dispatch, WATCH wake-up, and background jobs. The Task Event Plane does not use Celery queues as pub/sub.
Implementation consistency review — 2026-10-04
Current code preserves the TD1→TD2 authority split: M1–M3 own Evidence/Knowledge and provider lifecycle; M4 owns InvestigationState/EvidenceNeed/Decision durable writes; M5 works only through Perception, Task delegation, and controlled Capability paths; M6 consumes materialized M4 state and proposes typed final/continuation results; M7 evaluates frozen coordinates and promotion without becoming an online runtime owner. The packaging differences above do not change these owners.
Executable Task entry has also converged: background enrichment and Runtime Workbench Investigation tasks both go through TaskIntent → domain binding/compiler → TASK_ADMISSION Policy → TaskContract → Context/Budget/ExecutionEnvelope → TaskRun. A2A inbound remains at TaskIntent mapping until authenticated principal, classification, and authoritative domain binding exist.
Implementation slices
The original 0–10 slice numbering is retained below, with status updated to implementation evidence as of 2026-10-04. Open work stays with its existing owner rather than creating another layer.
- Protocol conformance gate — closed: TaskContract, TaskRun state, Role acceptance, ContextManifest revision, TaskEvent ordering, Capability/Policy matrix, and sandbox-profile selection are covered by deterministic contract/test gates.
- Task Runtime + duplex events — closed: PostgreSQL durable TaskEvent, the Redis Streams delivery role, Task start/delegate/cancel/patch/wait/resume, and the parent-child state machine are implemented; Celery remains coarse-grained dispatch only.
- M3 EnrichmentRole — closed: background and delegated triggers share EnrichmentState, operator/source primitives, and the Evidence/Knowledge write path.
- M4 State + InvestigationRole — closed: Case/InvestigationState/EvidenceNeed/StatePatch Gate is aligned with TaskContract desired state, ContinuationGate, and durable episodes.
- Context handoff — protocol closed / experiment ongoing: ContextManifest inherit/filter/fork/rebase/materialize is implemented; reference-vs-summary token, critical-context-retention, and stale/conflict comparisons are M7 experiments rather than runtime blockers.
- Skill + Capability/Policy — substrate closed / production bindings expanding: Skill/Experience promotion, Capability contract/binding/view/invocation, two-stage policy, obligations, and delegation/effect ceilings have implementation and controlled evaluation; real external Capability catalog/binding breadth remains open.
- Sandbox v1 — partial: sandbox profiles, ExecutionEnvelope, policy/fail-closed contracts, and replay/intervention seams are implemented; real OpenShell/OCI enforcement plus Firecracker/KVM substrate remains an explicit deployment boundary and is not claimed from mocks or contract tests.
- VERIFY end-to-end — closed:
VerifyFixBoundaryhas a canonicalTaskContract → Perception → Capability → Policy → Sandbox(optional) → Evidence → Statepath. - Incident WATCH + async enrichment — closed: parallel InvestigationRole/EnrichmentRole episodes, relevance-gated wake, and durable wait/resume are implemented.
- M6 Decision + A2A adapter — Decision closed / transport partial: ContinuationRequest ownership, DecisionResult, and deterministic A2A mapping are implemented; a GetTask compatibility seam exists while SendMessage/Subscribe/push/authentication remain transport work.
- M7 replay — controlled replay closed / historical world open: TaskEvent/Context/Checkpoint, single/multi-loop, and policy/sandbox/Skill/Capability interventions are implemented; true R3 historical Agent re-execution remains blocked by M1–M3 versioned Historical Knowledge Read.
Technical Review and probes
Contracts fixed in this review: Task-first; Role-after-Task; TaskIntent → TaskContract → TaskRun; Case/TaskRun separation; reference-preserving ContextManifest; internal async duplex TaskEvent Plane; EnrichmentRole + InvestigationRole as the v1 canonical multi-agent workload; M3 four-state EnrichmentState separated from M4 EvidenceNeed; ToolImplementation / CapabilityContract / CapabilityBinding separated; progressive CapabilityCard→CapabilitySchemaView disclosure; visibility/invocation policy split; PolicyDecision separates authorization from obligations; progressive SkillManifest→Procedure→Step→Provenance disclosure; seeded Skills and Experience→SkillPatch require M7 replay/regression before promotion; Agent/peer/Capability output first becomes EphemeralObservation; child Tasks cannot exceed parent effect/delegation/budget/deadline ceilings; sandbox defaults to OpenShell + OCI container, high-risk profile uses Firecracker and fails closed; M6 emits ContinuationRequest instead of creating EvidenceNeed; WATCH uses short episodes.
Choices to probe early without changing these contracts: concrete L2 query model/prompt, retrieval fusion/rerank, Percept ranking, numeric profile budgets, Skill retrieval/ranking, Experience clustering/compression, SkillPatch promotion threshold and automated-vs-human approval ratio, Capability-binding fallback ranking, OpenShell deployment across CI/WSL/Linux runner, Docker vs Podman default backend, Firecracker host/KVM availability, browser/full-VM runtime, Redis Streams consumer-group parameters, and A2A adapter SDK/language. Algorithms and thresholds not yet supported by implementation evidence remain unfrozen and may revise TD2 after coding/evaluation.
Priority probes:
- task/context protocol: TaskContract completion, parent-child patch/cancel, Context stale/rebase, reference vs summary handoff;
- duplex scheduling: parallel Investigation/Enrichment TaskRuns, event ordering, backpressure, reconnect/replay, irrelevant events not waking LLM;
- capability/policy: CapabilityCard→SchemaView→Binding→InvocationPlan, capability visible but invocation denied, obligation enforcement, delegation/effect ceilings, schema/server revision drift;
- skill/experience: manifest shortlist, progressive procedure/step disclosure, seeded-guard hits, ExperiencePattern compression, and SkillPatch replay/regression;
- sandbox: OpenShell container filesystem/network/secret isolation and teardown; Firecracker high-risk startup/cost/isolation/fallback;
- enrichment: Website real cases from gap→operator/source→Evidence→Knowledge→EnrichmentState fixed point;
- watch: discrete Incident signal→primary→forensic→patch replay through TaskEvent wake and State/Enrichment refresh;
- A2A interop: Task/Artifact/stream/push mapping without using A2A Context ID as ContextManifest.
This design does not change Requirements ownership: M3 still owns enrichment, M4 investigation context, M5 Agent investigation, M6 decision. Shared Task Runtime is the execution substrate that makes these modules and multi-Agent coordination testable. Competition requirements for autonomous Agent decision, task orchestration, tool use, multi-Agent collaboration, containerized engineering, and automation are directly exercised by these protocols and slices.
Implementation references
- A2A Protocol specification / streaming & async operations: https://a2a-protocol.org/latest/specification/ · https://a2a-protocol.org/latest/topics/streaming-and-async/
- A2A custom protocol bindings (including WebSocket as a bidirectional transport example): https://a2a-protocol.org/latest/topics/custom-protocol-bindings/
- NVIDIA OpenShell: https://github.com/NVIDIA/OpenShell
- GitHub Agentic Workflows Security Architecture: https://github.github.com/gh-aw/introduction/architecture/
- Firecracker design: https://github.com/firecracker-microvm/firecracker/blob/main/docs/design.md
- DeepSeek Elastic Compute (DSec): https://arxiv.org/abs/2609.22978