feat(recovery,context): tier-2 intent-holder arbiter + remaining-delta pinning + surfaced signal events

- recovery: two-tier repair ladder — owner then arbiter (recovery stage recast
  as intent-holder, holds initial intent, reconciles cross-file contract disputes)
  with independent INTENT_ROUTE_BUDGET; RecoveryRoutingTest coverage
- context: remaining-delta checklist pinning (RemainingDelta{Pinning,Entry}Test)
- surface write-only events (session name, quality signals) into stats/browse
- parseToolArguments lenient-Json fallback for bare-key drift
- tools: ChildProcess seam
This commit is contained in:
2026-07-11 23:56:52 +04:00
parent 3d5e05c1fb
commit 15248cae8a
55 changed files with 1932 additions and 231 deletions
+45 -23
View File
@@ -36,6 +36,7 @@ const (
TypeApprovalResolved = "approval.resolved"
TypeClarification = "clarification.required"
TypeWorkflowProposed = "workflow.proposed"
TypeSessionRenamed = "session.renamed"
TypeWorkspaceBound = "session.workspace_bound"
TypeStageManifest = "stage.tool_manifest"
TypeProviderStatus = "provider.status_changed"
@@ -70,30 +71,34 @@ const (
type ServerMessage struct {
Type string `json:"type"`
SessionID string `json:"sessionId"`
WorkflowID string `json:"workflowId"`
StageID string `json:"stageId"`
ToolName string `json:"toolName"`
Role string `json:"role"`
TurnID string `json:"turnId"`
Reason string `json:"reason"`
Summary string `json:"outputSummary"`
Response string `json:"responseText"`
LastOutput string `json:"lastOutput"` // session_snapshot: last stage output (reopen)
LastResponse string `json:"lastResponse"` // session_snapshot: last stage response (reopen)
Content string `json:"content"`
Diff *string `json:"diff"`
SessionID string `json:"sessionId"`
WorkflowID string `json:"workflowId"`
StageID string `json:"stageId"`
ToolName string `json:"toolName"`
Role string `json:"role"`
TurnID string `json:"turnId"`
Reason string `json:"reason"`
Summary string `json:"outputSummary"`
Response string `json:"responseText"`
Reasoning string `json:"reasoning"` // inference.completed: model thinking trace (collapsed view)
LastOutput string `json:"lastOutput"` // session_snapshot: last stage output (reopen)
LastResponse string `json:"lastResponse"` // session_snapshot: last stage response (reopen)
Content string `json:"content"`
Diff *string `json:"diff"`
// tool.completed: file/dir path(s) the tool read, wrote, or listed.
AffectedEntities []string `json:"affectedEntities"`
Tier string `json:"tier"`
Message string `json:"message"`
RequestID string `json:"requestId"`
ArtifactID string `json:"artifactId"`
ProviderID string `json:"providerId"`
Preview *string `json:"preview"`
Disposition string `json:"disposition"`
Outcome string `json:"outcome"` // approval.resolved: APPROVED | REJECTED | AUTO_APPROVED
WorkspaceRoot string `json:"workspaceRoot"` // session.workspace_bound: the bound cwd
// tool.started: pretty "key=value" call arguments (path=…, command="…").
Params []string `json:"params"`
Tier string `json:"tier"`
Message string `json:"message"`
RequestID string `json:"requestId"`
ArtifactID string `json:"artifactId"`
ProviderID string `json:"providerId"`
Preview *string `json:"preview"`
Disposition string `json:"disposition"`
Outcome string `json:"outcome"` // approval.resolved: APPROVED | REJECTED | AUTO_APPROVED
WorkspaceRoot string `json:"workspaceRoot"` // session.workspace_bound: the bound cwd
Name string `json:"name"` // session.renamed: human title derived from intent
// plan.locked: the compiled phase-2 stage ids in execution order
StageIDs []string `json:"stageIds"`
@@ -134,6 +139,7 @@ type ServerMessage struct {
PendingAppr []ApprovalDto `json:"pendingApprovals"`
Tools []ToolRecordDto `json:"tools"`
RecentEvents []EventEntryDto `json:"recentEvents"`
Transcript []TranscriptRowDto `json:"transcript"`
Stages []StageToolDecl `json:"stages"`
Workflows []WorkflowDto `json:"workflows"`
AssessedIssues []AssessedIssueDto `json:"issues"`
@@ -387,6 +393,22 @@ type ToolRecordDto struct {
Diff *string `json:"diff"`
}
// TranscriptRowDto is one raw OUTPUT-transcript source row from a session_snapshot; the client
// folds these into RouterEntry rows on reopen, applying its own diff/param/action formatting.
type TranscriptRowDto struct {
Kind string `json:"kind"`
Role string `json:"role"`
Content string `json:"content"`
ToolName string `json:"toolName"`
Status string `json:"status"`
Diff *string `json:"diff"`
Params []string `json:"params"`
Summary string `json:"summary"`
AffectedEntities []string `json:"affectedEntities"`
LatencyMs *int64 `json:"latencyMs"`
TotalTokens *int `json:"totalTokens"`
}
type WorkflowDto struct {
WorkflowID string `json:"workflowId"`
Description string `json:"description"`
@@ -413,7 +435,7 @@ func (m ServerMessage) IsEventBearing() bool {
TypeToolAssessed,
TypeApprovalRequired, TypeApprovalResolved, TypeClarification,
TypeWorkflowProposed,
TypeWorkspaceBound, TypeArtifactCreated,
TypeSessionRenamed, TypeWorkspaceBound, TypeArtifactCreated,
TypeArtifactValid, TypePlanLocked,
TypeRouterNarration, TypeReviewFindings:
return true