Skip to content

feat(tape): add contract lineage enforcement - #2107

Merged
yyhhyyyyyy merged 40 commits into
devfrom
feat/tape-contract-lineage
Aug 10, 2026
Merged

feat(tape): add contract lineage enforcement#2107
yyhhyyyyyy merged 40 commits into
devfrom
feat/tape-contract-lineage

Conversation

@yyhhyyyyyy

@yyhhyyyyyy yyhhyyyyyy commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add end-to-end contract lineage for delegated DeepChat execution, from a frozen TaskContract through contract-bearing provider Views, tool dispatch, Handoff format evaluation, and parent-visible settlement.

V1 is intentionally scoped to DeepChat child execution: ordinary interactive chat and ACP compatibility remain on schema-v4 ViewManifests without ExecutionContract construction or dispatch enforcement.

What changed

  • Add canonical, hash-versioned TaskContract, ExecutionContract, and Handoff format evaluation domains.
  • Record structured prompt provenance without changing provider-visible prompt output.
  • Freeze parent TaskContracts atomically with delegation turn creation and inherit them into child Tape before provider dispatch.
  • Embed immutable ExecutionContracts only in contract-bearing DeepChat child schema-v5 ViewManifests while preserving v1-v4 reads.
  • Enforce tool effect, workspace, nesting, permission, and current runtime authority ceilings at dispatch.
  • Validate the fixed required level-two Handoff sections at terminal settlement.
  • Atomically commit evaluation facts, turn/delegation projections, terminal state, and mailbox events.
  • Surface bounded evaluations through inspect, wait, read_result, and Handoff envelopes.

Scope clarifications from review

  • Removed the dormant result_schema branch, direct Ajv dependency, regex/schema safety machinery, and tests because V1 has no production producer for those requirements.
  • Replaced passed/failed plus accepted/parked with evaluationKind=handoff_format and formatStatus=valid|invalid|indeterminate.
  • A format-valid Handoff proves only that the required sections have non-empty bodies; it does not prove task completion, factual correctness, or parent acceptance.
  • Kept persisted TaskContract V1 compatibility: taskHarness.acceptance remains the stored field name, and a golden digest locks the required-sections-only identity.
  • Ordinary chat and ACP-backed subagents write schema-v4 manifests with no ExecutionContract; strict DeepChat children require schema-v5 and fail closed before provider execution when TaskContract context is missing.
  • Removed the unrelated scheduler/startup-migration baseline repairs from the final PR diff.

Reliability and compatibility

  • Prepare child TaskContract context once per send/resume run and reuse the immutable value across provider Views and physical retries.
  • Re-anchor explicitly after Tape reset rather than introducing a session-global latest-contract cache.
  • Quarantine and best-effort cancel children when TaskContract reconciliation fails while retaining fail-closed tool/provider identity.
  • Register all contract/evaluation columns with current-version schema repair.
  • Prevent deferred permission bindings from referencing a manifest whose durable write was not confirmed.
  • Preserve historical ViewManifest schemas, pre-contract delegation rows, fork isolation, and atomic terminal settlement.

Validation

Passed:

  • pnpm run format:check — 2,713 files
  • pnpm run i18n
  • pnpm run lint
  • pnpm run typecheck
  • Full DeepChat Agent harness — 297 tests
  • Focused contract/View/ToolService/Tape/orchestration suites — 226 tests
  • Post-merge feature regression — 5 files, 394 tests
  • Merged fix(settings): validate provider forms #2108 renderer regression — 2 files, 4 tests

pnpm run test:main completed with 568 files / 6,952 tests passing, 1 file / 5 tests skipped, and 3 files / 11 tests failing after restoring the five unrelated baseline owner files to origin/dev. The failures are eight stale MainDatabase API fixtures, one scheduler provider-config fixture, and two startup-migration missing-table fixtures; those owner files are absent from this PR's final diff.

Summary by CodeRabbit

  • New Features

    • Added immutable task and execution contracts to govern delegated work, tool access, workspaces, permissions, and subagent depth.
    • Added structured prompt provenance and degradation information for environment, skills, and tooling.
    • Added evaluations and acceptance outcomes for completed delegated tasks.
    • Added contract inheritance, recovery, quarantine handling, and legacy compatibility.
    • Added schema migrations and support for contract-backed view manifests.
  • Bug Fixes

    • Improved validation of resumed, deferred, and permission-triggered tool execution.
    • Added fail-closed handling for missing, tampered, conflicting, or mismatched execution context.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change introduces immutable TaskContract and ExecutionContract lineage, provenance-aware prompt assemblies, contract-bound View manifests, runtime authority checks, Tape persistence, live-delegation evaluation, recovery handling, and schema migrations.

Changes

Canonical contracts and evaluations

Layer / File(s) Summary
Contract models and validation
src/shared/types/task-contract.ts, src/shared/types/execution-contract.ts, src/main/tape/domain/*
Defines immutable task and execution contracts, canonical hashes, references, workspace ceilings, evaluations, summaries, and schema-v5 View manifests.
Prompt provenance
src/main/agent/deepchat/resources/*, src/main/agent/deepchat/runtime/promptAssemblyService.ts
Builds immutable prompt assemblies with provenance, freshness, degradation metadata, and compatibility string wrappers.
Runtime contract flow
src/main/agent/deepchat/runtime/*, src/main/tool/*
Propagates contracts through provider requests, tool batches, permission pauses, deferred execution, and current authority validation.
Tape and delegation settlement
src/main/tape/application/*, src/main/orchestration/liveDelegationRepository.ts, src/main/orchestration/liveDelegationService.ts
Persists parent and child lineage, evaluates terminal results, exposes bounded summaries, and recovers or quarantines invalid contract state.
Schemas, migrations, and tests
src/main/orchestration/data/tables/*, src/shared/orchestration/*, test/main/*
Adds nullable contract and evaluation projections, migrations through schema versions 65–66, compatibility validation, and focused coverage.
Architecture documentation
docs/architecture/*
Documents contract lineage, evaluation settlement, View enforcement, compatibility rules, acceptance criteria, and validation results.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the pull request's main change: end-to-end contract lineage enforcement for Tape and delegated execution.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tape-contract-lineage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (17)
src/main/tape/domain/executionContract.ts (1)

1103-1118: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider reusing isDeepChatExecutionContract inside verifyExecutionContractHash.

verifyExecutionContractHash repeats the schema, hash version, hash format, and hash recomputation checks that isDeepChatExecutionContract already performs. The two functions can drift when the hash rules change. A thin wrapper keeps one source of truth for hash verification.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tape/domain/executionContract.ts` around lines 1103 - 1118, Update
verifyExecutionContractHash to reuse isDeepChatExecutionContract as the single
validation path, removing its duplicated schema, hash-version, format, and
recomputation checks while preserving the boolean verification contract.
src/main/tape/domain/taskContract.ts (2)

139-162: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Add explicit typeof guards before the SHA-256 tests.

normalizeEvaluationRef receives values that originate from untyped restore paths, for example the contract.taskConfig.predecessorEvaluationRef read in isDeepChatTaskContract. SHA_256_PATTERN.test(value.tapeIdentity) coerces a non-string operand instead of rejecting it, and the returned object then copies the raw value. Add typeof checks so only strings pass.

♻️ Proposed guard
   if (
     value?.schemaVersion !== 1 ||
+    typeof value.tapeIdentity !== 'string' ||
+    typeof value.evaluationHash !== 'string' ||
     !SHA_256_PATTERN.test(value.tapeIdentity) ||
     !SHA_256_PATTERN.test(value.evaluationHash)
   ) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tape/domain/taskContract.ts` around lines 139 - 162, Update
normalizeEvaluationRef to require typeof value.tapeIdentity === 'string' and
typeof value.evaluationHash === 'string' before applying SHA_256_PATTERN.test.
Keep invalid schema or non-string/hash-mismatched values on the existing
TaskContractError path, and only return validated string values.

419-444: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Note the cost of the rebuild-based type guard.

isDeepChatTaskContract rebuilds the whole contract, including the bounded JSON-schema walk, on every call. Callers invoke it on hot paths, for example normalizeTaskContractRef in src/main/tape/domain/executionContract.ts for each provider request and row matching in src/main/tape/application/taskEvaluationService.ts. The work is bounded by MAX_TASK_CONTRACT_BYTES and MAX_RESULT_SCHEMA_NODES, so it is safe. If profiling shows this guard in a hot path, add a fast pre-check on contractHash before the rebuild.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tape/domain/taskContract.ts` around lines 419 - 444, If profiling
identifies isDeepChatTaskContract as a hot-path cost, add an early contractHash
consistency check before the buildTaskContract rebuild and bounded schema walk,
returning false on mismatch while preserving the existing canonical comparison
for matching hashes. Keep the change scoped to isDeepChatTaskContract and retain
all current validation behavior.
src/main/tape/domain/workspacePath.ts (1)

8-18: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Consider stripping a trailing separator during normalization.

path.normalize keeps a trailing separator, so /work/repo/ and /work/repo normalize to different strings. workspacePathsMatch and isWorkspacePathWithin treat them as equal because they use relative, so authority checks stay correct. The stored contract string still differs, which produces two different contract hashes for one directory. If you want one canonical string per directory, strip the trailing separator here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tape/domain/workspacePath.ts` around lines 8 - 18, Update
normalizeAbsoluteWorkspacePath to strip trailing separators from the normalized
POSIX and Windows paths, while preserving filesystem roots such as "/" and drive
roots. Ensure equivalent directory inputs like "/work/repo/" and "/work/repo"
produce the same canonical contract path.
src/main/tape/domain/viewManifest.ts (2)

243-249: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use one form for the schema-5 comparison.

Line 244 uses Number(manifest.schemaVersion) === 5. Line 248 uses manifest.schemaVersion !== 5. The two forms test the same property in adjacent branches of one guard. Use the direct comparison in both places, and add a short comment if a cast is required for type narrowing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tape/domain/viewManifest.ts` around lines 243 - 249, Standardize the
schema-5 checks in the manifest hash-version branches by using the direct
manifest.schemaVersion comparison consistently, updating the check in the
TAPE_VIEW_MANIFEST_LEGACY_HASH_VERSION branch to match the existing comparison
in the TAPE_VIEW_MANIFEST_HASH_VERSION branch. Add a brief narrowing comment
only if the type system requires a cast.

154-166: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Share one contract-to-manifest consistency rule. Both modules independently assert that a schema-5 manifest and its embedded ExecutionContract agree on session, message, request sequence, provider, model, prompt hash, and tool-definitions hash. Adding a provenance field later requires two edits, and a missed edit weakens one of the two validation paths.

  • src/main/tape/domain/viewManifest.ts#L154-L166: export the field-by-field consistency check from executionContractMatchesManifest as a shared helper.
  • src/main/tape/domain/replay.ts#L141-L167: call that shared helper from hasExecutionContractForSchema and keep only the replay-specific checks, that is the hashVersion check and the viewId derivation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tape/domain/viewManifest.ts` around lines 154 - 166, In
src/main/tape/domain/viewManifest.ts lines 154-166, export
executionContractMatchesManifest as the shared field-by-field consistency
helper. In src/main/tape/domain/replay.ts lines 141-167, update
hasExecutionContractForSchema to call that helper and retain only the
replay-specific hashVersion validation and viewId derivation checks, removing
its duplicated contract-to-manifest comparisons.
src/main/tape/domain/taskEvaluation.ts (1)

322-323: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Drop the section identity from the schema cache key.

The cache key combines the section identity and the schema hash. Two requirements that use the same schema on different sections compile and validate separately. The validation result depends on the parsed section value, so the section identity must stay in the key for result caching. If you want to reuse compiled validators, cache the compiled function by schema hash and keep the result cache keyed by section and schema.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tape/domain/taskEvaluation.ts` around lines 322 - 323, Update the
caching logic around schemaEvaluation to separate compiled-validator reuse from
validation-result caching: key compiled validators only by
hashJsonData(requirement.schema), while retaining sectionIdentity in the key
used for parsed-section validation results. Ensure result caching remains
isolated per section and schema.
test/main/session/data/tapeViewManifest.test.ts (1)

39-39: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Annotate the empty tools fixture.

TypeScript infers never[] for const tools = []. The empty array then satisfies every array parameter, so the fixture no longer checks that the tool list matches the manifest and contract element type. The file already imports MCPToolDefinitionBase at line 4. Add the annotation.

♻️ Proposed typing fix
-  const tools = []
+  const tools: MCPToolDefinitionBase[] = []
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/main/session/data/tapeViewManifest.test.ts` at line 39, Annotate the
empty tools fixture in the test setup with MCPToolDefinitionBase[], using the
existing MCPToolDefinitionBase import so TypeScript validates the fixture
against the manifest’s tool contract.
src/main/orchestration/liveDelegationService.ts (1)

1544-1547: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Share one project-directory resolution.

resolveParentProjectDir at lines 1624-1627 repeats the expression in resolveCurrentSafety at lines 1544-1547. Both derive the workspace that is frozen into the TaskContract. If one changes later, the spawn path and the follow-up path can freeze different workspaces for the same delegation. Call resolveParentProjectDir from resolveCurrentSafety.

♻️ Proposed refactor
-    const projectDir =
-      (await this.options.sessions.resolveConversationWorkdir(parent.sessionId)) ||
-      parent.projectDir ||
-      null
+    const projectDir = await this.resolveParentProjectDir(parent)
     return { parent, projectDir }

Also applies to: 1624-1627

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/orchestration/liveDelegationService.ts` around lines 1544 - 1547,
Update resolveCurrentSafety to obtain the project directory by calling
resolveParentProjectDir instead of duplicating the
resolveConversationWorkdir/parent.projectDir fallback expression. Preserve the
existing resolved-or-null behavior and use the shared value in both spawn and
follow-up paths.
test/main/orchestration/liveDelegationService.test.ts (1)

2348-2363: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive the accepted-answer fixture from LIVE_DELEGATION_REQUIRED_RESULT_SECTIONS. Both suites hard-code the same six-section Markdown answer. The shared root cause is that the required-section list is copied as literals instead of derived from the exported constant. If a section is added or renamed, one copy can drift and that suite silently stops producing an accepted verdict while still passing.

  • test/main/orchestration/liveDelegationService.test.ts#L2348-L2363: build the answer by mapping LIVE_DELEGATION_REQUIRED_RESULT_SECTIONS to ## <section> plus a body line, and export the helper from a shared test module.
  • test/main/orchestration/liveDelegationRepository.test.ts#L114-L129: delete the local copy and import the shared helper.

As per path instructions, "Keep committed tests lean and focused on project reliability, stability, and observable contracts".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/main/orchestration/liveDelegationService.test.ts` around lines 2348 -
2363, Derive the accepted-answer fixture from
LIVE_DELEGATION_REQUIRED_RESULT_SECTIONS instead of duplicating section
literals. In test/main/orchestration/liveDelegationService.test.ts:2348-2363,
update completeAcceptedAnswer to map each required section to its heading and
body, then export it from a shared test module. In
test/main/orchestration/liveDelegationRepository.test.ts:114-129, remove the
local fixture and import the shared helper.

Source: Path instructions

src/main/tape/application/taskEvaluationService.ts (1)

258-272: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document why serializeEvaluationRef is called for its side effect.

Line 270 discards the return value. The call exists to assert that the reference serializes, and it throws when the reference is malformed. A future reader can remove it as dead code and silently drop that validation. Add a short comment.

♻️ Proposed comment
+  // Assert the reference is serializable before it becomes part of a receipt.
   serializeEvaluationRef(ref)
   return Object.freeze(ref)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tape/application/taskEvaluationService.ts` around lines 258 - 272,
In buildEvaluationRef, add a short comment immediately before the discarded
serializeEvaluationRef(ref) call explaining that it intentionally validates
serialization and throws for malformed references; preserve the call and its
existing placement before Object.freeze(ref).
test/main/tape/executionContract.test.ts (1)

659-666: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reduce coupling to the internal hashing recipe.

The test rebuilds internalExecutionPolicyHash as hashJsonData(stored.ceilings) and contractHash as hashJsonData(draft). This reproduces the exact internal hashing recipe. If the recipe changes without a behavior change, this test fails.

Prefer a helper exported from the domain module that re-seals a mutated contract, or build the Windows-path contract through buildExecutionContract and assert isDeepChatExecutionContract on the serialized round trip.

As per coding guidelines: "Keep committed tests lean and focused on project reliability, stability, and observable contracts; remove temporary checks that only test implementation internals before handoff."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/main/tape/executionContract.test.ts` around lines 659 - 666, Update the
Windows-path validation test around isDeepChatExecutionContract to avoid
manually recomputing internalExecutionPolicyHash and contractHash. Prefer
constructing the contract through buildExecutionContract and validating its
serialized round trip, or use an exported domain helper that re-seals the
mutated contract, while preserving the assertion that the canonical Windows path
is accepted independently of the replay host platform.

Source: Coding guidelines

src/main/tool/index.ts (2)

938-953: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider one generic definition lookup.

getAgentDefinition duplicates getMcpDefinition exactly, including the globalMapperConversationId !== null fallback rule. A single private helper that takes the conversation map and the global map would keep the two lookups in sync.

♻️ Proposed refactor
+  private lookupDefinition(
+    toolName: string,
+    conversationMaps: Map<string, Map<string, MCPToolDefinition>>,
+    globalMap: Map<string, MCPToolDefinition>,
+    conversationId?: string
+  ): MCPToolDefinition | undefined {
+    const normalizedConversationId = conversationId?.trim()
+    if (normalizedConversationId) {
+      const definitions = conversationMaps.get(normalizedConversationId)
+      if (definitions) return definitions.get(toolName)
+      if (this.globalMapperConversationId !== null) return undefined
+    }
+    return globalMap.get(toolName)
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tool/index.ts` around lines 938 - 953, The getAgentDefinition and
getMcpDefinition lookups duplicate the same conversation/global resolution
logic. Extract one private generic helper that accepts the relevant
conversation-definition map and global-definition map, including the existing
globalMapperConversationId fallback behavior, then update both methods to
delegate to it.

755-757: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Derive dispatch subagent depth from currentDefinition.

src/main/tool/index.ts:756 currently hardcodes 1 for LIVE_DELEGATION_AGENT_TOOL_NAME, while the task contract layer computes depth from the tool definition and checks each tool against maxSubagentDepth. Move the shared rule into src/main/tool/index.ts or export a reusable helper, then pass that value to assertExecutionContractAllowsDispatch; this keeps runtime tool dispatch and task-contract filtering in sync if another tool gains subagent depth later.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tool/index.ts` around lines 755 - 757, Replace the hardcoded
requestedSubagentDepth logic near assertExecutionContractAllowsDispatch with a
shared computation derived from currentDefinition, matching the task contract
layer’s maxSubagentDepth rules. Reuse or export the existing helper from the
task contract implementation, then pass its result for the current tool so
dispatch and contract filtering remain synchronized as definitions gain subagent
depth.
src/main/tool/runtimePorts.ts (1)

72-72: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Collapse the tri-state enabledMcpServerIds.

string[] | null plus the optional marker gives three states for two meanings. The consumer in src/main/tool/index.ts line 732 uses Array.isArray(...), so undefined and null behave identically. Use enabledMcpServerIds: string[] | null to make "no restriction" a single value.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tool/runtimePorts.ts` at line 72, Update the enabledMcpServerIds
declaration in the runtime ports type to remove the optional marker, keeping it
as string[] | null. Ensure all construction and usage sites provide either an
array for restricted IDs or null for no restriction, preserving the consumer’s
Array.isArray behavior.
test/main/agent/deepchat/loop/loopRun.test.ts (1)

108-111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Isolate the stale-sequence rejection.

Line 108 passes both a wrong requestSeq and a null contract. The assertion cannot show which input caused the rejection. Pass a valid contract with the wrong sequence to pin the stale-sequence rule. The contract factory on line 97 already supports sessionId and messageId overrides, so a mismatched session case costs one more line.

💚 Proposed test change
-    expect(() => bindActiveRequestContract(run, requestSeq + 1, null)).toThrow(/request sequence/)
+    expect(() => bindActiveRequestContract(run, requestSeq + 1, contract())).toThrow(
+      /request sequence/
+    )
     expect(() => bindActiveRequestContract(run, requestSeq, contract({ runId: 'other' }))).toThrow(
       /Loop Run/
     )
+    expect(() =>
+      bindActiveRequestContract(run, requestSeq, contract({ sessionId: 'other' }))
+    ).toThrow()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/main/agent/deepchat/loop/loopRun.test.ts` around lines 108 - 111, Update
the stale-sequence assertion around bindActiveRequestContract to pass a valid
contract instead of null, isolating the rejection to requestSeq + 1. Reuse the
existing contract factory and its sessionId/messageId override support to add a
separate mismatched-session case, while preserving the existing wrong-run
assertion.
src/main/agent/deepchat/runtime/deepChatLoopRunner.ts (1)

472-482: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting the effective-system-prompt read.

The same expression appears three times: here, at lines 736-740, and in src/main/agent/deepchat/runtime/process.ts lines 1315-1319. A small shared helper in @/agent/deepchat/resources/promptAssembly would keep the three sites consistent.

♻️ Proposed helper
// src/main/agent/deepchat/resources/promptAssembly.ts
export function readEffectiveSystemPrompt(messages: readonly ChatMessage[]): string {
  const first = messages[0]
  return first?.role === 'system' && typeof first.content === 'string' ? first.content : ''
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/agent/deepchat/runtime/deepChatLoopRunner.ts` around lines 472 -
482, Extract the repeated effective-system-prompt expression into a shared
readEffectiveSystemPrompt helper in promptAssembly, accepting readonly
ChatMessage[] and returning the first string system message or ''. Replace the
local expressions in deepChatLoopRunner and process.ts with this helper,
preserving existing behavior and importing it from the shared module.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/agent/deepchat/resources/promptAssembly.ts`:
- Around line 76-79: Update the assembly return paths in promptAssembly to
snapshot section objects before returning them, rather than only freezing the
sections array. Clone and freeze each section, and clone and freeze its
degradationCodes collection, so later caller mutations to content, contentHash,
or degradationCodes cannot alter returned metadata. Apply the same change to all
assembly boundaries, including the paths corresponding to the other noted return
blocks.

In `@src/main/agent/deepchat/resources/systemPromptBuilder.ts`:
- Around line 10-17: Apply Oxfmt formatting to the changed code in
systemPromptBuilder.ts, including the imports and the referenced ranges. Use
single quotes, remove semicolons, and enforce the 100-column width without
altering behavior.

In `@src/main/agent/deepchat/runtime/process.ts`:
- Around line 1086-1091: Make contract absence fail closed across both sites: in
src/main/agent/deepchat/runtime/process.ts lines 1086-1091, require
run.activeRequestContract when the session must carry a contract and fail the
round instead of assigning a null executionContract; in
src/main/agent/deepchat/runtime/deepChatLoopRunner.ts lines 725-782, update
onBuildError to either abort with a contract-specific terminal reason or
explicitly record the degradation, so the later binding check at lines 839-846
does not misclassify a build failure as lost binding.

In `@src/main/orchestration/liveDelegationRepository.ts`:
- Around line 1053-1096: The projection validation errors in toTurn() currently
throw plain Error instances, preventing runWithAdmission() from quarantining
corrupt stored rows. Replace the incomplete, conflicting, and misbound
TaskContract/evaluation projection throws with LiveDelegationTaskContractError
while preserving their existing validation conditions and messages.
- Around line 1258-1285: Update parseTaskContract, parseTaskContractRef,
parseTaskEvaluation, and parseEvaluationRef to perform JSON.parse inside a guard
and convert parse failures into each helper’s existing “is malformed.” domain
error; preserve the current null handling and restore-function validation
behavior.

In `@src/main/tape/domain/taskContract.ts`:
- Around line 239-248: Extend the key validation in assertBoundedJsonSchema to
reject $dynamicRef, $recursiveRef, $id, and $schema alongside the existing $ref
and $async checks. Keep these failures as invalid_input TaskContractError
results before recursively processing descriptor.value or invoking Ajv.

In `@src/main/tape/infrastructure/sqlite/tapeEntryStore.ts`:
- Around line 377-383: Align the SQL contract-name exclusion predicates in the
projection and search queries with isContractTapeReservedName: exclude every
name beginning with the contract/ namespace rather than only the literal
contract/* pattern. Apply the same matching behavior in both query locations, or
instead update isContractTapeReservedName so its domain behavior exactly matches
the existing SQL predicate.

In `@src/shared/types/task-contract.ts`:
- Line 246: Bound both reasonCodes projections in
src/shared/types/task-contract.ts at lines 246-246 and 266-266 by applying
.max(DEEPCHAT_TASK_EVALUATION_REASON_CODES.length) to each array schema,
including the parent-facing summary.

In `@test/main/agent/deepchat/harness/deepChatAgentHarness.test.ts`:
- Around line 5262-5266: Update the refreshSystemPrompt handling at both
referenced call sites to treat the result as a DeepChatPromptAssembly
unconditionally: remove the typeof string fallback and read its prompt property
directly. This should assert the documented assembly contract and preserve the
existing refreshedSystemPrompt assignment.

In `@test/main/agent/deepchat/resources/systemPromptBuilder.test.ts`:
- Around line 160-165: Update the configured_prompt assertion in the assembly
test to verify the exact SHA-256 contentHash for “BASE PROMPT” instead of only
matching a 64-character hexadecimal format. Keep the existing inclusion
assertion and add only this focused regression expectation.

In `@test/main/agent/deepchat/runtime/process.test.ts`:
- Around line 1022-1030: In the test around finalPauseCall, assert that
finalPauseCall is defined before accessing its blocks or parsing the execution
contract binding, matching the sibling test’s guard. Keep the existing
permissionBlock lookup and binding equality assertion unchanged after this
validation.

---

Nitpick comments:
In `@src/main/agent/deepchat/runtime/deepChatLoopRunner.ts`:
- Around line 472-482: Extract the repeated effective-system-prompt expression
into a shared readEffectiveSystemPrompt helper in promptAssembly, accepting
readonly ChatMessage[] and returning the first string system message or ''.
Replace the local expressions in deepChatLoopRunner and process.ts with this
helper, preserving existing behavior and importing it from the shared module.

In `@src/main/orchestration/liveDelegationService.ts`:
- Around line 1544-1547: Update resolveCurrentSafety to obtain the project
directory by calling resolveParentProjectDir instead of duplicating the
resolveConversationWorkdir/parent.projectDir fallback expression. Preserve the
existing resolved-or-null behavior and use the shared value in both spawn and
follow-up paths.

In `@src/main/tape/application/taskEvaluationService.ts`:
- Around line 258-272: In buildEvaluationRef, add a short comment immediately
before the discarded serializeEvaluationRef(ref) call explaining that it
intentionally validates serialization and throws for malformed references;
preserve the call and its existing placement before Object.freeze(ref).

In `@src/main/tape/domain/executionContract.ts`:
- Around line 1103-1118: Update verifyExecutionContractHash to reuse
isDeepChatExecutionContract as the single validation path, removing its
duplicated schema, hash-version, format, and recomputation checks while
preserving the boolean verification contract.

In `@src/main/tape/domain/taskContract.ts`:
- Around line 139-162: Update normalizeEvaluationRef to require typeof
value.tapeIdentity === 'string' and typeof value.evaluationHash === 'string'
before applying SHA_256_PATTERN.test. Keep invalid schema or
non-string/hash-mismatched values on the existing TaskContractError path, and
only return validated string values.
- Around line 419-444: If profiling identifies isDeepChatTaskContract as a
hot-path cost, add an early contractHash consistency check before the
buildTaskContract rebuild and bounded schema walk, returning false on mismatch
while preserving the existing canonical comparison for matching hashes. Keep the
change scoped to isDeepChatTaskContract and retain all current validation
behavior.

In `@src/main/tape/domain/taskEvaluation.ts`:
- Around line 322-323: Update the caching logic around schemaEvaluation to
separate compiled-validator reuse from validation-result caching: key compiled
validators only by hashJsonData(requirement.schema), while retaining
sectionIdentity in the key used for parsed-section validation results. Ensure
result caching remains isolated per section and schema.

In `@src/main/tape/domain/viewManifest.ts`:
- Around line 243-249: Standardize the schema-5 checks in the manifest
hash-version branches by using the direct manifest.schemaVersion comparison
consistently, updating the check in the TAPE_VIEW_MANIFEST_LEGACY_HASH_VERSION
branch to match the existing comparison in the TAPE_VIEW_MANIFEST_HASH_VERSION
branch. Add a brief narrowing comment only if the type system requires a cast.
- Around line 154-166: In src/main/tape/domain/viewManifest.ts lines 154-166,
export executionContractMatchesManifest as the shared field-by-field consistency
helper. In src/main/tape/domain/replay.ts lines 141-167, update
hasExecutionContractForSchema to call that helper and retain only the
replay-specific hashVersion validation and viewId derivation checks, removing
its duplicated contract-to-manifest comparisons.

In `@src/main/tape/domain/workspacePath.ts`:
- Around line 8-18: Update normalizeAbsoluteWorkspacePath to strip trailing
separators from the normalized POSIX and Windows paths, while preserving
filesystem roots such as "/" and drive roots. Ensure equivalent directory inputs
like "/work/repo/" and "/work/repo" produce the same canonical contract path.

In `@src/main/tool/index.ts`:
- Around line 938-953: The getAgentDefinition and getMcpDefinition lookups
duplicate the same conversation/global resolution logic. Extract one private
generic helper that accepts the relevant conversation-definition map and
global-definition map, including the existing globalMapperConversationId
fallback behavior, then update both methods to delegate to it.
- Around line 755-757: Replace the hardcoded requestedSubagentDepth logic near
assertExecutionContractAllowsDispatch with a shared computation derived from
currentDefinition, matching the task contract layer’s maxSubagentDepth rules.
Reuse or export the existing helper from the task contract implementation, then
pass its result for the current tool so dispatch and contract filtering remain
synchronized as definitions gain subagent depth.

In `@src/main/tool/runtimePorts.ts`:
- Line 72: Update the enabledMcpServerIds declaration in the runtime ports type
to remove the optional marker, keeping it as string[] | null. Ensure all
construction and usage sites provide either an array for restricted IDs or null
for no restriction, preserving the consumer’s Array.isArray behavior.

In `@test/main/agent/deepchat/loop/loopRun.test.ts`:
- Around line 108-111: Update the stale-sequence assertion around
bindActiveRequestContract to pass a valid contract instead of null, isolating
the rejection to requestSeq + 1. Reuse the existing contract factory and its
sessionId/messageId override support to add a separate mismatched-session case,
while preserving the existing wrong-run assertion.

In `@test/main/orchestration/liveDelegationService.test.ts`:
- Around line 2348-2363: Derive the accepted-answer fixture from
LIVE_DELEGATION_REQUIRED_RESULT_SECTIONS instead of duplicating section
literals. In test/main/orchestration/liveDelegationService.test.ts:2348-2363,
update completeAcceptedAnswer to map each required section to its heading and
body, then export it from a shared test module. In
test/main/orchestration/liveDelegationRepository.test.ts:114-129, remove the
local fixture and import the shared helper.

In `@test/main/session/data/tapeViewManifest.test.ts`:
- Line 39: Annotate the empty tools fixture in the test setup with
MCPToolDefinitionBase[], using the existing MCPToolDefinitionBase import so
TypeScript validates the fixture against the manifest’s tool contract.

In `@test/main/tape/executionContract.test.ts`:
- Around line 659-666: Update the Windows-path validation test around
isDeepChatExecutionContract to avoid manually recomputing
internalExecutionPolicyHash and contractHash. Prefer constructing the contract
through buildExecutionContract and validating its serialized round trip, or use
an exported domain helper that re-seals the mutated contract, while preserving
the assertion that the canonical Windows path is accepted independently of the
replay host platform.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ea6b8a6-28c3-40e8-811f-0ae73acbe20f

📥 Commits

Reviewing files that changed from the base of the PR and between da5fc89 and d0e2429.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (92)
  • docs/architecture/proactive-multi-agent-orchestration/spec.md
  • docs/architecture/tape-contract-lineage/plan.md
  • docs/architecture/tape-contract-lineage/spec.md
  • docs/architecture/tape-contract-lineage/tasks.md
  • docs/architecture/tape-system.md
  • package.json
  • src/main/agent/deepchat/harness/createDeepChatAgentHarness.ts
  • src/main/agent/deepchat/harness/runtimeServices.ts
  • src/main/agent/deepchat/instance/deepChatAgentInstance.ts
  • src/main/agent/deepchat/loop/contextCoordinator.ts
  • src/main/agent/deepchat/loop/loopRun.ts
  • src/main/agent/deepchat/loop/ports.ts
  • src/main/agent/deepchat/resources/promptAssembly.ts
  • src/main/agent/deepchat/resources/systemEnvPromptBuilder.ts
  • src/main/agent/deepchat/resources/systemPromptBuilder.ts
  • src/main/agent/deepchat/runtime/deepChatLoopRunner.ts
  • src/main/agent/deepchat/runtime/deferredExecutionContract.ts
  • src/main/agent/deepchat/runtime/deferredToolExecutor.ts
  • src/main/agent/deepchat/runtime/dispatch.ts
  • src/main/agent/deepchat/runtime/interactionCoordinator.ts
  • src/main/agent/deepchat/runtime/process.ts
  • src/main/agent/deepchat/runtime/promptAssemblyService.ts
  • src/main/agent/deepchat/runtime/sessionIdentityService.ts
  • src/main/agent/deepchat/runtime/taskContractCapability.ts
  • src/main/agent/deepchat/runtime/turnCoordinator.ts
  • src/main/agent/deepchat/runtime/types.ts
  • src/main/app/composition.ts
  • src/main/app/startupMigrations/sessionDataMigrations.ts
  • src/main/data/schemaCatalog.ts
  • src/main/orchestration/data/tables/liveDelegationEvents.ts
  • src/main/orchestration/data/tables/liveDelegationTurns.ts
  • src/main/orchestration/data/tables/liveDelegations.ts
  • src/main/orchestration/liveDelegationRepository.ts
  • src/main/orchestration/liveDelegationService.ts
  • src/main/orchestration/liveDelegationTaskContract.ts
  • src/main/session/data/database.ts
  • src/main/tape/application/forkService.ts
  • src/main/tape/application/lineageService.ts
  • src/main/tape/application/taskContractService.ts
  • src/main/tape/application/taskEvaluationService.ts
  • src/main/tape/domain/canonicalJson.ts
  • src/main/tape/domain/contractFacts.ts
  • src/main/tape/domain/effectiveView.ts
  • src/main/tape/domain/executionContract.ts
  • src/main/tape/domain/replay.ts
  • src/main/tape/domain/tapeIdentity.ts
  • src/main/tape/domain/taskContract.ts
  • src/main/tape/domain/taskEvaluation.ts
  • src/main/tape/domain/viewManifest.ts
  • src/main/tape/domain/workspacePath.ts
  • src/main/tape/infrastructure/sqlite/tapeEntryStore.ts
  • src/main/tape/ports/storage.ts
  • src/main/tool/index.ts
  • src/main/tool/runtimePorts.ts
  • src/shared/chat.d.ts
  • src/shared/orchestration/liveDelegation.ts
  • src/shared/orchestration/liveDelegationMarkdown.ts
  • src/shared/types/agent-interface.d.ts
  • src/shared/types/core/chat.ts
  • src/shared/types/execution-contract.ts
  • src/shared/types/prompt-assembly.ts
  • src/shared/types/tape-view-manifest.ts
  • src/shared/types/task-contract.ts
  • src/shared/types/tool.d.ts
  • test/main/agent/deepchat/harness/deepChatAgentHarness.test.ts
  • test/main/agent/deepchat/loop/contextCoordinator.test.ts
  • test/main/agent/deepchat/loop/loopRun.test.ts
  • test/main/agent/deepchat/resources/promptAssembly.test.ts
  • test/main/agent/deepchat/resources/systemEnvPromptBuilder.test.ts
  • test/main/agent/deepchat/resources/systemPromptBuilder.test.ts
  • test/main/agent/deepchat/runtime/deferredExecutionContract.test.ts
  • test/main/agent/deepchat/runtime/deferredToolExecutor.test.ts
  • test/main/agent/deepchat/runtime/process.test.ts
  • test/main/agent/deepchat/runtime/promptAssemblyService.test.ts
  • test/main/agent/deepchat/runtime/sessionIdentityService.test.ts
  • test/main/app/startupMigrations/sessionDataMigrations.sqlite.test.ts
  • test/main/app/startupMigrations/sessionDataMigrations.test.ts
  • test/main/data/mainDatabase.test.ts
  • test/main/orchestration/liveDelegationMigration.test.ts
  • test/main/orchestration/liveDelegationRepository.test.ts
  • test/main/orchestration/liveDelegationService.test.ts
  • test/main/scheduler/schedulerService.test.ts
  • test/main/session/data/tapeFork.test.ts
  • test/main/session/data/tapeViewManifest.test.ts
  • test/main/session/runtimeIntegration.test.ts
  • test/main/tape/canonicalJson.test.ts
  • test/main/tape/executionContract.test.ts
  • test/main/tape/taskContract.test.ts
  • test/main/tape/taskContractPersistence.test.ts
  • test/main/tape/taskEvaluation.test.ts
  • test/main/tool/agentTools/agentToolDependencies.ts
  • test/main/tool/toolService.test.ts

Comment thread src/main/agent/deepchat/resources/promptAssembly.ts
Comment thread src/main/agent/deepchat/resources/systemPromptBuilder.ts Outdated
Comment thread src/main/agent/deepchat/runtime/process.ts
Comment thread src/main/orchestration/liveDelegationRepository.ts
Comment thread src/main/orchestration/liveDelegationRepository.ts
Comment thread src/main/tape/infrastructure/sqlite/tapeEntryStore.ts
Comment thread src/shared/types/task-contract.ts Outdated
Comment thread test/main/agent/deepchat/harness/deepChatAgentHarness.test.ts
Comment thread test/main/agent/deepchat/resources/systemPromptBuilder.test.ts
Comment thread test/main/agent/deepchat/runtime/process.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/agent/deepchat/resources/systemPromptBuilder.ts`:
- Around line 197-205: Update the active-skill filtering in the system prompt
builder around normalizeSkillMetadata so metadata lookup failure does not remove
requested skills; distinguish successful empty metadata from a failed lookup,
retain the pinned_skill_unavailable degradation, and allow loadSkillContent to
attempt the requested skills when metadata is unavailable. Add a focused Vitest
regression covering this user-visible failure path.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b267d442-4f2e-439a-8f1e-eb1ed5229aa0

📥 Commits

Reviewing files that changed from the base of the PR and between d0e2429 and 3b2f18c.

📒 Files selected for processing (13)
  • src/main/agent/deepchat/resources/promptAssembly.ts
  • src/main/agent/deepchat/resources/systemPromptBuilder.ts
  • src/main/orchestration/liveDelegationRepository.ts
  • src/main/orchestration/liveDelegationService.ts
  • src/main/tape/domain/taskContract.ts
  • src/shared/types/task-contract.ts
  • test/main/agent/deepchat/resources/promptAssembly.test.ts
  • test/main/agent/deepchat/resources/systemPromptBuilder.test.ts
  • test/main/agent/deepchat/runtime/process.test.ts
  • test/main/orchestration/liveDelegationRepository.test.ts
  • test/main/orchestration/liveDelegationService.test.ts
  • test/main/tape/taskContract.test.ts
  • test/main/tape/taskEvaluation.test.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • test/main/agent/deepchat/resources/systemPromptBuilder.test.ts
  • test/main/tape/taskContract.test.ts
  • test/main/agent/deepchat/runtime/process.test.ts
  • src/main/orchestration/liveDelegationService.ts
  • src/main/tape/domain/taskContract.ts
  • src/shared/types/task-contract.ts
  • src/main/orchestration/liveDelegationRepository.ts

Comment thread src/main/agent/deepchat/resources/systemPromptBuilder.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/main/app/composition.ts (2)

1146-1151: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Use one fail-closed subagent policy predicate.

At Line 1149, !== false treats an unset subagentEnabled value as enabled. The session projection uses === true at Line 1180. A missing or legacy setting can therefore pass execution authority checks while the session reports subagent capability as disabled. Normalize this setting once and use the same value in both paths.

Proposed fix
-          agentPolicyEnabled: agentConfig.subagentEnabled !== false,
+          agentPolicyEnabled: agentConfig.subagentEnabled === true,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/app/composition.ts` around lines 1146 - 1151, Normalize the
subagent-enabled setting once in the surrounding composition flow using a
fail-closed predicate (`=== true`), then reuse that normalized value for both
`resolveDeepChatSubagentCapability` and the session capability projection.
Replace the inline `agentConfig.subagentEnabled !== false` check while
preserving the existing `=== true` behavior and keeping both paths consistent.

1497-1500: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Do not write the stable session identifier to the error log.

The new warning records update.sessionId in application logs. Remove this field or replace it with a redacted correlation identifier.

Proposed fix
           logger.warn('[YoBrowser] Failed to release inactive preview', {
-            sessionId: update.sessionId,
             error
           })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/app/composition.ts` around lines 1497 - 1500, Remove
update.sessionId from the logger.warn payload in the releaseInactivePreview
error handler, or replace it with an approved redacted correlation identifier
while preserving the error details and warning context.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/main/app/composition.ts`:
- Around line 1146-1151: Normalize the subagent-enabled setting once in the
surrounding composition flow using a fail-closed predicate (`=== true`), then
reuse that normalized value for both `resolveDeepChatSubagentCapability` and the
session capability projection. Replace the inline `agentConfig.subagentEnabled
!== false` check while preserving the existing `=== true` behavior and keeping
both paths consistent.
- Around line 1497-1500: Remove update.sessionId from the logger.warn payload in
the releaseInactivePreview error handler, or replace it with an approved
redacted correlation identifier while preserving the error details and warning
context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 71128fbd-7174-44cf-b49d-2257f4d0c154

📥 Commits

Reviewing files that changed from the base of the PR and between 3b2f18c and 6c7a266.

📒 Files selected for processing (11)
  • src/main/agent/deepchat/harness/createDeepChatAgentHarness.ts
  • src/main/agent/deepchat/loop/ports.ts
  • src/main/agent/deepchat/runtime/deferredToolExecutor.ts
  • src/main/agent/deepchat/runtime/dispatch.ts
  • src/main/agent/deepchat/runtime/interactionCoordinator.ts
  • src/main/agent/deepchat/runtime/turnCoordinator.ts
  • src/main/app/composition.ts
  • src/main/tool/index.ts
  • src/shared/types/agent-interface.d.ts
  • test/main/agent/deepchat/harness/deepChatAgentHarness.test.ts
  • test/main/tool/toolService.test.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/main/agent/deepchat/harness/createDeepChatAgentHarness.ts
  • src/shared/types/agent-interface.d.ts
  • test/main/tool/toolService.test.ts
  • src/main/agent/deepchat/runtime/deferredToolExecutor.ts
  • src/main/agent/deepchat/runtime/interactionCoordinator.ts
  • src/main/agent/deepchat/loop/ports.ts
  • src/main/tool/index.ts
  • src/main/agent/deepchat/runtime/dispatch.ts
  • test/main/agent/deepchat/harness/deepChatAgentHarness.test.ts
  • src/main/agent/deepchat/runtime/turnCoordinator.ts

@yyhhyyyyyy
yyhhyyyyyy requested a review from zerob13 August 9, 2026 06:42

@zerob13 zerob13 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes because the implementation scope is substantially wider than the product contract that exists today.

  1. The only production TaskContract producer, createLiveDelegationTaskContractInput(), always emits one fixed required_sections requirement for six Markdown headings. There is no src/ caller that creates a result_schema requirement; all current references are inside the domain/type implementation. Please remove the dormant result_schema branch, the Ajv runtime dependency, the regex/schema safety machinery, and their test matrix from this PR. Reintroduce them with the concrete user/API/configuration path that can actually supply such a requirement.

  2. The current evaluator marks a result passed/accepted when those six sections merely have non-empty bodies. That proves output shape, not completion of the delegated task. Do not expose this as a task-success verdict. Either narrow the terminology/contract to format validation, or add a real task-specific acceptance input before assigning passed/accepted.

  3. Although strict manifest admission is limited to subagents, DeepChatLoopRunner builds schema-v5 ExecutionContracts for every ordinary interactive View, and every successfully built contract is carried into ToolService dispatch checks. This puts prompt/tool hashing, manifest persistence, workdir/tool identity checks, and deferred bindings on the normal-chat hot path for a delegation feature. Restrict generation and dispatch enforcement to contract-bearing child sessions in V1, or split global interactive-View attestation into a separately motivated PR with its own failure/performance analysis.

After reducing the scope, prune tests that only prove the unused schema/canonicalization machinery. Keep the observable contracts: delegation settlement, atomic persistence/recovery, and live authority revocation. Also move the explicitly noted scheduler/startup-migration baseline repairs out of this feature PR unless a direct dependency is documented.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/tape/domain/taskEvaluation.ts (1)

61-87: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Hash and size the raw terminal candidate.

Lines 61-67 hash the trimmed candidate. Two outputs that differ only in leading or trailing bytes then have the same candidate hash, byte count, and evaluation idempotency identity. Preserve trimming only for blank detection and section evaluation. Hash and measure the original non-empty input.

Proposed fix
-  const candidateResult = input.candidateResult?.trim() || null
+  const rawCandidateResult = input.candidateResult ?? ''
+  const candidateResult = rawCandidateResult.trim() || null
   const candidate = candidateResult
     ? {
         kind: 'answer' as const,
-        sha256: createHash('sha256').update(candidateResult, 'utf8').digest('hex'),
-        utf8Bytes: Buffer.byteLength(candidateResult, 'utf8')
+        sha256: createHash('sha256').update(rawCandidateResult, 'utf8').digest('hex'),
+        utf8Bytes: Buffer.byteLength(rawCandidateResult, 'utf8')
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/tape/domain/taskEvaluation.ts` around lines 61 - 87, Update
candidate construction in the task evaluation flow to retain the original
non-empty input for SHA-256 hashing and UTF-8 byte measurement, rather than
using the trimmed value. Continue using the trimmed candidate only for blank
detection and evaluateRequirements, preserving the existing absent-candidate
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/architecture/tape-system.md`:
- Around line 234-241: Clarify the terminal evaluation contract in the
architecture section by distinguishing live delegation state “idle” from
evaluation disposition “parked.” Add an explicit mapping table covering
completed, failed, cancelled, interrupted, and indeterminate outcomes, defining
their verdict and disposition; enforce that only passed maps to accepted and
every other outcome maps to parked, so terminal consumers apply one settlement
rule.

---

Outside diff comments:
In `@src/main/tape/domain/taskEvaluation.ts`:
- Around line 61-87: Update candidate construction in the task evaluation flow
to retain the original non-empty input for SHA-256 hashing and UTF-8 byte
measurement, rather than using the trimmed value. Continue using the trimmed
candidate only for blank detection and evaluateRequirements, preserving the
existing absent-candidate behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 33f513bd-a486-4d67-b97e-c7046160179a

📥 Commits

Reviewing files that changed from the base of the PR and between 8660f9d and bf46ac6.

📒 Files selected for processing (19)
  • docs/architecture/proactive-multi-agent-orchestration/spec.md
  • docs/architecture/tape-contract-lineage/plan.md
  • docs/architecture/tape-contract-lineage/spec.md
  • docs/architecture/tape-contract-lineage/tasks.md
  • docs/architecture/tape-system.md
  • src/main/agent/deepchat/runtime/deepChatLoopRunner.ts
  • src/main/agent/deepchat/runtime/turnCoordinator.ts
  • src/main/orchestration/liveDelegationService.ts
  • src/main/orchestration/liveDelegationTaskContract.ts
  • src/main/tape/domain/taskContract.ts
  • src/main/tape/domain/taskEvaluation.ts
  • src/shared/types/task-contract.ts
  • test/main/agent/deepchat/harness/deepChatAgentHarness.test.ts
  • test/main/orchestration/liveDelegationRepository.test.ts
  • test/main/orchestration/liveDelegationService.test.ts
  • test/main/tape/executionContract.test.ts
  • test/main/tape/taskContract.test.ts
  • test/main/tape/taskContractPersistence.test.ts
  • test/main/tape/taskEvaluation.test.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • test/main/tape/taskContractPersistence.test.ts
  • src/main/tape/domain/taskContract.ts
  • test/main/orchestration/liveDelegationRepository.test.ts
  • docs/architecture/tape-contract-lineage/plan.md
  • docs/architecture/proactive-multi-agent-orchestration/spec.md
  • src/main/agent/deepchat/runtime/turnCoordinator.ts
  • test/main/tape/executionContract.test.ts
  • test/main/orchestration/liveDelegationService.test.ts
  • src/main/orchestration/liveDelegationService.ts
  • src/shared/types/task-contract.ts

Comment thread docs/architecture/tape-system.md
@yyhhyyyyyy
yyhhyyyyyy requested a review from zerob13 August 9, 2026 10:07

@zerob13 zerob13 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous scope/design blockers are resolved, and the current CI plus focused local validation pass. One persisted-data compatibility issue still blocks merge.

Comment thread src/shared/types/task-contract.ts
@yyhhyyyyyy
yyhhyyyyyy requested a review from zerob13 August 9, 2026 15:22
@yyhhyyyyyy
yyhhyyyyyy merged commit afc90b5 into dev Aug 10, 2026
12 checks passed
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.

2 participants