merge: integrate feat/backlog-burndown into master
master had advanced 16 commits past feat/backlog-burndown's base, and the two branches independently built four of the same features. Resolved 26 conflicts. Overlap features — kept master's implementation (more complete / production-wired / more robust), dropped the feature branch's parallel constellation: - llama-server health probe: kept master's event-store-backed tps probe; dropped the branch's LlamaLivenessClient (liveness-only, throughput unwired). - event-store probe: kept master's EventStoreHealthProbe; dropped EventStoreLatencyProbe. - brief echo-back gate: kept master's BriefEchoDiff (Jaccard, tolerates rewording); dropped the branch's exact-set-diff BriefEchoComparator/Extractor. - static-first reviewer: kept master's command/exit-code gate (ProcessStaticAnalysisRunner, wired); dropped the branch's structured-finding static_check stage (no-op seam). Its structured-findings model is filed as a follow-up in BACKLOG. Feature-branch net-new work brought in and kept (master had none): - native task tracking (aggregate, agent tools wired into analyst/implementer/reviewer, dependency graph + gates, decompose, REST/CLI, TUI task board) - critique-outcome producer (role-rel §6 — master had deferred it) - stage-level plan checkpointing (C-A2, folded into runPostStageGates) - CLAUDE.md/AGENTS.md L0 standing context - cross-session grants + TUI (grant scopes/revoke, @ picker, session resume browser) Verified: full Gradle compile (all modules + tests) green; tests pass for core:events, core:kernel, infrastructure:workflow, apps:server, apps:cli, testing:integration; tui-go go build + go test green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -56,6 +56,8 @@ const (
|
||||
TypeSessionStats = "session.stats"
|
||||
TypeIdeaList = "idea.list"
|
||||
TypeHealthChecks = "health.checks"
|
||||
TypeFileList = "file.list"
|
||||
TypeGrantList = "grant.list"
|
||||
)
|
||||
|
||||
// ServerMessage is a flat decode of every server->client variant. Field names
|
||||
@@ -154,6 +156,23 @@ type ServerMessage struct {
|
||||
|
||||
// idea.list — the cross-session idea board
|
||||
Ideas []IdeaDto `json:"ideas"`
|
||||
|
||||
// file.list — the session workspace's file paths (for the @ file-ref picker)
|
||||
Paths []string `json:"paths"`
|
||||
|
||||
// grant.list — the active cross-session (PROJECT/GLOBAL) standing grants
|
||||
Grants []GrantDto `json:"grants"`
|
||||
}
|
||||
|
||||
// GrantDto is one standing cross-session grant. Mirrors the Kotlin GrantDto.
|
||||
type GrantDto struct {
|
||||
GrantID string `json:"grantId"`
|
||||
Scope string `json:"scope"` // "PROJECT" | "GLOBAL"
|
||||
ToolName string `json:"toolName"`
|
||||
ProjectID string `json:"projectId"`
|
||||
Tiers []string `json:"tiers"`
|
||||
Reason string `json:"reason"`
|
||||
ExpiresAtMs *int64 `json:"expiresAtMs"`
|
||||
}
|
||||
|
||||
// IdeaDto is one idea on the cross-session board. Mirrors the Kotlin IdeaDto.
|
||||
@@ -410,6 +429,12 @@ func ListArtifacts(sessionID string) []byte {
|
||||
return encode("ListArtifacts", map[string]any{"sessionId": sessionID})
|
||||
}
|
||||
|
||||
// ListFiles asks the server for the session workspace's file paths (replied to with file.list),
|
||||
// used to populate the @ file-reference picker.
|
||||
func ListFiles(sessionID string) []byte {
|
||||
return encode("ListFiles", map[string]any{"sessionId": sessionID})
|
||||
}
|
||||
|
||||
// GetSessionStats asks the server for a session's derived metrics (replied to with session.stats).
|
||||
func GetSessionStats(sessionID string) []byte {
|
||||
return encode("GetSessionStats", map[string]any{"sessionId": sessionID})
|
||||
@@ -471,7 +496,8 @@ func ClearModelPin() []byte {
|
||||
}
|
||||
|
||||
// CreateGrant pre-authorizes a tool/tier so future calls skip the approval gate.
|
||||
// scope is "SESSION" or "STAGE"; permittedTiers are tier names like "T3".
|
||||
// scope is "SESSION", "PROJECT", or "GLOBAL"; permittedTiers are tier names like "T3".
|
||||
// For PROJECT/GLOBAL the server derives the projectId from the session's workspace.
|
||||
func CreateGrant(sessionID, scope string, permittedTiers []string, reason, toolName string) []byte {
|
||||
return encode("CreateGrant", map[string]any{
|
||||
"sessionId": sessionID,
|
||||
@@ -484,6 +510,16 @@ func CreateGrant(sessionID, scope string, permittedTiers []string, reason, toolN
|
||||
})
|
||||
}
|
||||
|
||||
// RevokeGrant revokes a standing (PROJECT/GLOBAL) grant by id; replies with a fresh grant.list.
|
||||
func RevokeGrant(grantID string) []byte {
|
||||
return encode("RevokeGrant", map[string]any{"grantId": grantID})
|
||||
}
|
||||
|
||||
// ListGrants requests the active cross-session grants (replied to with a grant.list).
|
||||
func ListGrants() []byte {
|
||||
return encode("ListGrants", map[string]any{})
|
||||
}
|
||||
|
||||
// Hello is the first frame sent on every (re)connect. It carries the client's
|
||||
// working directory so the server can bind a workspace before any session starts.
|
||||
func Hello(workingDir string) []byte {
|
||||
|
||||
Reference in New Issue
Block a user