Skip to content

feat(core): Run aggregate, HiveJournal and the section 9 agent loop - #41

Merged
Dimoshka merged 7 commits into
mainfrom
feat/m2-run-aggregate
Nov 8, 2026
Merged

Dimoshka merged 7 commits into
mainfrom
feat/m2-run-aggregate

Conversation

@Dimoshka

@Dimoshka Dimoshka commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

M2 groundwork for the Run aggregate, the Hive-backed journal, and the section 9 agent loop. This PR turns the draft step 1 into the full verified batch: the domain and loop seams are in place, fail-closed defaults are bound in DI, and the discrepancies found against the spec are recorded as open questions.

What landed

Run aggregate and cancellation

  • Run.taints is a live read-only view over labels copied from the constructor argument; Run.addTaint is the only way to add a label, and it is idempotent. The run itself never removes one.
  • CancelToken.child() derives a token that inherits the parent's cancellation while cancelling independently, so one tool call can be abandoned without cancelling the run.

HiveJournal

  • Constructor uses the Dart 3.13 new _ form (fixes unnecessary_type_name_in_constructor); the Hive boxes are private.
  • The seq counter is flushed before the step record, so a crash cannot reuse a sequence number; a skipped seq is harmless.
  • Tests cover concurrent started calls, reopen durability, denied records, and finished on an unknown seq.

Section 9 agent loop

  • application/agent/ seams: RunResult, ToolSet/ToolRegistry, AgentConfig, ApprovalService, ContextBuilder, AgentDeps, and internal truncateToolOutput.
  • runAgent follows the fixed section 9 order: malformed/unavailable checks, policy, approval, journal started before the call, timeout on a per-invocation child token, taint on untrusted output, non-throwing truncation, a fresh tool snapshot per step, and cancellation re-checks.
  • Fail-closed defaults: DefaultAgentConfig keeps declared risk, DenyAllApprovals refuses, EmptyToolRegistry, PromptContextBuilder starts from the prompt.
  • New types are exported from package:alteri_one_core.

DI

  • AgentDeps is bound lazily in CoreModule, so startup stays green without an LlmPort and only resolution fails (providers arrive in M3).
  • registerJournal({required String directory}) opens the journal after configureCore, registers it as both HiveJournal and JournalPort, and rejects a duplicate registration before opening any box. configureCore stays synchronous and I/O-free.
  • injection.config.dart regenerated.

Docs

  • docs/plan/M2.md rewritten to the plan template with completed steps ticked.
  • Q7-Q14 recorded in docs/spec/open-questions.md.
  • One implementation pointer added to docs/spec/domain.md section 9; no decision was changed.

Verification

  • melos run ci green (format, analyze, arch check, tests).
  • Core suite: 214 tests, all passing.
  • dart run tools/docs_check/bin/docs_check.dart: exit 0.
  • dart run tools/codegen_check/bin/codegen_check.dart: exit 0; melos run gen produces no diff.
  • Reviewer approved the batch.

Deliberate deviations (open questions Q7-Q14)

  • Q7: mutable Run vs copy-with for taints — read-only view plus addTaint.
  • Q8: _truncateUntrusted contract — UTF-8 bytes, rune-safe cut, jsonEncode for non-strings, bounded fallback, no section 13 wrapper in M2.
  • Q9: types of d.config/d.registry/d.context/d.approvals — minimal application-layer interfaces.
  • Q10: journal directory resolution — caller-supplied registerJournal(directory:), no home-directory default.
  • Q11: budget enforcement beyond maxSteps — maxSteps only until providers report usage.
  • Q12: approval refusal is not journalled — spec order kept for M2; revisit with the interactive channel.
  • Q13: model-call journaling and transcript persistence — out of the loop for M2, decided with plan Step 8.
  • Q14: timed-out tool recorded as failed (section 9), with a per-invocation child token.

Explicitly NOT in this PR

  • chat mode end-to-end against a fake LlmPort.
  • The application service that binds runAgent to RunBloc / StatePublisher and projects journal state.
  • Section 14 profile/risk configuration and the interactive approval channel.
  • Section 13 untrusted prompt and tool-output boundary wrapping.
  • Section 2.8 target metrics (postponed to M4, with the daemon).

Closes #42

Use the primary-constructor form for the private constructor and make the Hive boxes private. Flush the sequence counter before writing the step record so a crash cannot reuse a seq, and cover the durability path and the denied/finished branches with tests.
Run exposes taints through an unmodifiable live view and accepts new labels only through addTaint. CancelToken.child() derives a token that inherits the parent's cancellation while cancelling independently, so one tool call can be abandoned without cancelling the run.
Add the application/agent seams (RunResult, ToolSet/ToolRegistry, AgentConfig, ApprovalService, ContextBuilder, AgentDeps), the fail-closed defaults, and runAgent. The loop journals policy denials and executed calls, runs tools concurrently on child cancel tokens, and ends in RunCompleted or RunBudgetExceeded. Export the new types from the package.
Register the agent defaults and AgentDeps in the core module and add registerJournal, which opens a HiveJournal under a caller-supplied directory and registers it as both HiveJournal and JournalPort. Regenerate the injectable config and cover the bindings, the fail-closed defaults and the duplicate-registration guards.
Rewrite the M2 plan to the plan template with the completed steps ticked, record Q7-Q14 in the open-questions list, and add the section 9 implementation pointer to domain.md.
@Dimoshka Dimoshka changed the title feat(core): add the Run aggregate and HiveJournal feat(core): Run aggregate, HiveJournal and the section 9 agent loop Nov 8, 2026
@Dimoshka
Dimoshka marked this pull request as ready for review November 8, 2026 09:29
@Dimoshka
Dimoshka merged commit 32b32d4 into main Nov 8, 2026
1 check passed
@Dimoshka
Dimoshka deleted the feat/m2-run-aggregate branch November 8, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

M2: finish the run journal wiring and the section 9 agent loop

1 participant