Merge pull request #795 from joshuavial/fix/auto-attach-mol-polecat-work
fix(sling): allow auto-attach mol-polecat-work on open polecat beads
This commit is contained in:
@@ -665,46 +665,71 @@ Skip dispatch - system is healthy.
|
|||||||
|
|
||||||
[[steps]]
|
[[steps]]
|
||||||
id = "costs-digest"
|
id = "costs-digest"
|
||||||
title = "Aggregate daily costs"
|
title = "Aggregate daily costs [DISABLED]"
|
||||||
needs = ["session-gc"]
|
needs = ["session-gc"]
|
||||||
description = """
|
description = """
|
||||||
**DAILY DIGEST** - Aggregate yesterday's session cost wisps.
|
**⚠️ DISABLED** - Skip this step entirely.
|
||||||
|
|
||||||
Session costs are recorded as ephemeral wisps (not exported to JSONL) to avoid
|
Cost tracking is temporarily disabled because Claude Code does not expose
|
||||||
log-in-database pollution. This step aggregates them into a permanent daily
|
session costs in a way that can be captured programmatically.
|
||||||
"Cost Report YYYY-MM-DD" bead for audit purposes.
|
|
||||||
|
**Why disabled:**
|
||||||
|
- The `gt costs` command uses tmux capture-pane to find costs
|
||||||
|
- Claude Code displays costs in the TUI status bar, not in scrollback
|
||||||
|
- All sessions show $0.00 because capture-pane can't see TUI chrome
|
||||||
|
- The infrastructure is sound but has no data source
|
||||||
|
|
||||||
|
**What we need from Claude Code:**
|
||||||
|
- Stop hook env var (e.g., `$CLAUDE_SESSION_COST`)
|
||||||
|
- Or queryable file/API endpoint
|
||||||
|
|
||||||
|
**Re-enable when:** Claude Code exposes cost data via API or environment.
|
||||||
|
|
||||||
|
See: GH#24, gt-7awfj
|
||||||
|
|
||||||
|
**Exit criteria:** Skip this step - proceed to next."""
|
||||||
|
|
||||||
|
[[steps]]
|
||||||
|
id = "patrol-digest"
|
||||||
|
title = "Aggregate daily patrol digests"
|
||||||
|
needs = ["costs-digest"]
|
||||||
|
description = """
|
||||||
|
**DAILY DIGEST** - Aggregate yesterday's patrol cycle digests.
|
||||||
|
|
||||||
|
Patrol cycles (Deacon, Witness, Refinery) create ephemeral per-cycle digests
|
||||||
|
to avoid JSONL pollution. This step aggregates them into a single permanent
|
||||||
|
"Patrol Report YYYY-MM-DD" bead for audit purposes.
|
||||||
|
|
||||||
**Step 1: Check if digest is needed**
|
**Step 1: Check if digest is needed**
|
||||||
```bash
|
```bash
|
||||||
# Preview yesterday's costs (dry run)
|
# Preview yesterday's patrol digests (dry run)
|
||||||
gt costs digest --yesterday --dry-run
|
gt patrol digest --yesterday --dry-run
|
||||||
```
|
```
|
||||||
|
|
||||||
If output shows "No session cost wisps found", skip to Step 3.
|
If output shows "No patrol digests found", skip to Step 3.
|
||||||
|
|
||||||
**Step 2: Create the digest**
|
**Step 2: Create the digest**
|
||||||
```bash
|
```bash
|
||||||
gt costs digest --yesterday
|
gt patrol digest --yesterday
|
||||||
```
|
```
|
||||||
|
|
||||||
This:
|
This:
|
||||||
- Queries all session.ended wisps from yesterday
|
- Queries all ephemeral patrol digests from yesterday
|
||||||
- Creates a single "Cost Report YYYY-MM-DD" bead with aggregated data
|
- Creates a single "Patrol Report YYYY-MM-DD" bead with aggregated data
|
||||||
- Deletes the source wisps
|
- Deletes the source digests
|
||||||
|
|
||||||
**Step 3: Verify**
|
**Step 3: Verify**
|
||||||
The digest appears in `gt costs --week` queries.
|
Daily patrol digests preserve audit trail without per-cycle pollution.
|
||||||
Daily digests preserve audit trail without per-session pollution.
|
|
||||||
|
|
||||||
**Timing**: Run once per morning patrol cycle. The --yesterday flag ensures
|
**Timing**: Run once per morning patrol cycle. The --yesterday flag ensures
|
||||||
we don't try to digest today's incomplete data.
|
we don't try to digest today's incomplete data.
|
||||||
|
|
||||||
**Exit criteria:** Yesterday's costs digested (or no wisps to digest)."""
|
**Exit criteria:** Yesterday's patrol digests aggregated (or none to aggregate)."""
|
||||||
|
|
||||||
[[steps]]
|
[[steps]]
|
||||||
id = "log-maintenance"
|
id = "log-maintenance"
|
||||||
title = "Rotate logs and prune state"
|
title = "Rotate logs and prune state"
|
||||||
needs = ["costs-digest"]
|
needs = ["patrol-digest"]
|
||||||
description = """
|
description = """
|
||||||
Maintain daemon logs and state files.
|
Maintain daemon logs and state files.
|
||||||
|
|
||||||
|
|||||||
@@ -158,8 +158,12 @@ func (b *Beads) AttachMolecule(pinnedBeadID, moleculeID string) (*Issue, error)
|
|||||||
return nil, fmt.Errorf("fetching pinned bead: %w", err)
|
return nil, fmt.Errorf("fetching pinned bead: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow pinned beads OR open polecat agent beads (polecats have a lifecycle, not permanent)
|
||||||
if issue.Status != StatusPinned {
|
if issue.Status != StatusPinned {
|
||||||
return nil, fmt.Errorf("issue %s is not pinned (status: %s)", pinnedBeadID, issue.Status)
|
_, role, _, ok := ParseAgentBeadID(pinnedBeadID)
|
||||||
|
if !(issue.Status == "open" && ok && role == "polecat") {
|
||||||
|
return nil, fmt.Errorf("issue %s is not pinned or open polecat (status: %s)", pinnedBeadID, issue.Status)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build attachment fields with current timestamp
|
// Build attachment fields with current timestamp
|
||||||
|
|||||||
@@ -508,8 +508,10 @@ func runSling(cmd *cobra.Command, args []string) error {
|
|||||||
updateAgentHookBead(targetAgent, beadID, hookWorkDir, townBeadsDir)
|
updateAgentHookBead(targetAgent, beadID, hookWorkDir, townBeadsDir)
|
||||||
|
|
||||||
// Auto-attach mol-polecat-work to polecat agent beads
|
// Auto-attach mol-polecat-work to polecat agent beads
|
||||||
// This ensures polecats have the standard work molecule attached for guidance
|
// This ensures polecats have the standard work molecule attached for guidance.
|
||||||
if strings.Contains(targetAgent, "/polecats/") {
|
// Only do this for bare beads (no --on formula), since formula-on-bead
|
||||||
|
// mode already attaches the formula as a molecule.
|
||||||
|
if formulaName == "" && strings.Contains(targetAgent, "/polecats/") {
|
||||||
if err := attachPolecatWorkMolecule(targetAgent, hookWorkDir, townRoot); err != nil {
|
if err := attachPolecatWorkMolecule(targetAgent, hookWorkDir, townRoot); err != nil {
|
||||||
// Warn but don't fail - polecat will still work without molecule
|
// Warn but don't fail - polecat will still work without molecule
|
||||||
fmt.Printf("%s Could not attach work molecule: %v\n", style.Dim.Render("Warning:"), err)
|
fmt.Printf("%s Could not attach work molecule: %v\n", style.Dim.Render("Warning:"), err)
|
||||||
|
|||||||
@@ -665,46 +665,71 @@ Skip dispatch - system is healthy.
|
|||||||
|
|
||||||
[[steps]]
|
[[steps]]
|
||||||
id = "costs-digest"
|
id = "costs-digest"
|
||||||
title = "Aggregate daily costs"
|
title = "Aggregate daily costs [DISABLED]"
|
||||||
needs = ["session-gc"]
|
needs = ["session-gc"]
|
||||||
description = """
|
description = """
|
||||||
**DAILY DIGEST** - Aggregate yesterday's session cost wisps.
|
**⚠️ DISABLED** - Skip this step entirely.
|
||||||
|
|
||||||
Session costs are recorded as ephemeral wisps (not exported to JSONL) to avoid
|
Cost tracking is temporarily disabled because Claude Code does not expose
|
||||||
log-in-database pollution. This step aggregates them into a permanent daily
|
session costs in a way that can be captured programmatically.
|
||||||
"Cost Report YYYY-MM-DD" bead for audit purposes.
|
|
||||||
|
**Why disabled:**
|
||||||
|
- The `gt costs` command uses tmux capture-pane to find costs
|
||||||
|
- Claude Code displays costs in the TUI status bar, not in scrollback
|
||||||
|
- All sessions show $0.00 because capture-pane can't see TUI chrome
|
||||||
|
- The infrastructure is sound but has no data source
|
||||||
|
|
||||||
|
**What we need from Claude Code:**
|
||||||
|
- Stop hook env var (e.g., `$CLAUDE_SESSION_COST`)
|
||||||
|
- Or queryable file/API endpoint
|
||||||
|
|
||||||
|
**Re-enable when:** Claude Code exposes cost data via API or environment.
|
||||||
|
|
||||||
|
See: GH#24, gt-7awfj
|
||||||
|
|
||||||
|
**Exit criteria:** Skip this step - proceed to next."""
|
||||||
|
|
||||||
|
[[steps]]
|
||||||
|
id = "patrol-digest"
|
||||||
|
title = "Aggregate daily patrol digests"
|
||||||
|
needs = ["costs-digest"]
|
||||||
|
description = """
|
||||||
|
**DAILY DIGEST** - Aggregate yesterday's patrol cycle digests.
|
||||||
|
|
||||||
|
Patrol cycles (Deacon, Witness, Refinery) create ephemeral per-cycle digests
|
||||||
|
to avoid JSONL pollution. This step aggregates them into a single permanent
|
||||||
|
"Patrol Report YYYY-MM-DD" bead for audit purposes.
|
||||||
|
|
||||||
**Step 1: Check if digest is needed**
|
**Step 1: Check if digest is needed**
|
||||||
```bash
|
```bash
|
||||||
# Preview yesterday's costs (dry run)
|
# Preview yesterday's patrol digests (dry run)
|
||||||
gt costs digest --yesterday --dry-run
|
gt patrol digest --yesterday --dry-run
|
||||||
```
|
```
|
||||||
|
|
||||||
If output shows "No session cost wisps found", skip to Step 3.
|
If output shows "No patrol digests found", skip to Step 3.
|
||||||
|
|
||||||
**Step 2: Create the digest**
|
**Step 2: Create the digest**
|
||||||
```bash
|
```bash
|
||||||
gt costs digest --yesterday
|
gt patrol digest --yesterday
|
||||||
```
|
```
|
||||||
|
|
||||||
This:
|
This:
|
||||||
- Queries all session.ended wisps from yesterday
|
- Queries all ephemeral patrol digests from yesterday
|
||||||
- Creates a single "Cost Report YYYY-MM-DD" bead with aggregated data
|
- Creates a single "Patrol Report YYYY-MM-DD" bead with aggregated data
|
||||||
- Deletes the source wisps
|
- Deletes the source digests
|
||||||
|
|
||||||
**Step 3: Verify**
|
**Step 3: Verify**
|
||||||
The digest appears in `gt costs --week` queries.
|
Daily patrol digests preserve audit trail without per-cycle pollution.
|
||||||
Daily digests preserve audit trail without per-session pollution.
|
|
||||||
|
|
||||||
**Timing**: Run once per morning patrol cycle. The --yesterday flag ensures
|
**Timing**: Run once per morning patrol cycle. The --yesterday flag ensures
|
||||||
we don't try to digest today's incomplete data.
|
we don't try to digest today's incomplete data.
|
||||||
|
|
||||||
**Exit criteria:** Yesterday's costs digested (or no wisps to digest)."""
|
**Exit criteria:** Yesterday's patrol digests aggregated (or none to aggregate)."""
|
||||||
|
|
||||||
[[steps]]
|
[[steps]]
|
||||||
id = "log-maintenance"
|
id = "log-maintenance"
|
||||||
title = "Rotate logs and prune state"
|
title = "Rotate logs and prune state"
|
||||||
needs = ["costs-digest"]
|
needs = ["patrol-digest"]
|
||||||
description = """
|
description = """
|
||||||
Maintain daemon logs and state files.
|
Maintain daemon logs and state files.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user