pullfrog 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,17 @@ import { type AgentResult, type AgentRunContext, type AgentUsage, type PostRunIs
8
8
  *
9
9
  * the gate is anchored to `hadProgressComment` so silent runs (non-issue
10
10
  * events, dispatcher skipped seeding) don't fire a nudge there's no UI for.
11
+ *
12
+ * `Review` and `IncrementalReview` have different valid exits:
13
+ * - Review: only `create_pull_request_review` counts. `report_progress` is
14
+ * not a substitute — a Review run that exits with just a summary comment
15
+ * has produced nothing reviewable on the PR. matches the hard-fail
16
+ * message at `expected = "create_pull_request_review"` below.
17
+ * - IncrementalReview: `report_progress` is a legitimate "no review
18
+ * warranted" exit, so either toolState flag short-circuits.
19
+ * splitting per mode also closes the bypass where a subagent (e.g. a
20
+ * `task`-dispatched `reviewfrog` lens) calls `report_progress` and silences
21
+ * the gate even though the orchestrator never submitted a review.
11
22
  */
12
23
  export declare function getUnsubmittedReview(toolState: ToolState): "Review" | "IncrementalReview" | null;
13
24
  /**
@@ -56,6 +67,16 @@ export declare function buildPostRunPrompt(issues: PostRunIssues): string;
56
67
  * the file is the single source of truth — there is no separate MCP tool
57
68
  * call. the server reads the file at end-of-run and persists any edits to
58
69
  * `Repo.learnings`.
70
+ *
71
+ * the prompt copy is shaped by repo-wide audits of the actual content the
72
+ * agent has been writing (issue #619 in pullfrog/app). recurring failure
73
+ * modes the framing pushes back on:
74
+ * - massive multi-paragraph "bullets" that are really mini-articles
75
+ * - PR-/review-/commit-/date-anchored facts that decay within weeks
76
+ * - rediscovery of pullfrog-tool quirks that belong in tool descriptions,
77
+ * not per-repo learnings
78
+ * - sections growing into giant flat lists with no internal structure,
79
+ * forcing future runs to read kilobytes to find one fact
59
80
  */
60
81
  export declare function buildLearningsReflectionPrompt(filePath: string): string;
61
82
  /**
@@ -36,32 +36,52 @@ export declare const ORCHESTRATOR_LABEL = "orchestrator";
36
36
  */
37
37
  export declare function deriveLabelFromTaskInput(input: TaskDispatchInput): string;
38
38
  /**
39
- * Stateful tracker mapping sessionIDs to human labels.
39
+ * Stateful tracker mapping subagent activity back to human-readable labels.
40
40
  *
41
- * Lifecycle:
42
- * - First call to `labelFor()` returns ORCHESTRATOR_LABEL and binds that
43
- * sessionID to it. Every subsequent event from that session gets the
44
- * same label.
45
- * - When the orchestrator emits a Task tool_use, the harness calls
46
- * `recordTaskDispatch()` to push the dispatch's derived label onto a
47
- * pending FIFO queue.
48
- * - The next previously-unseen sessionID consumes the head of the queue.
49
- * - If `labelFor()` is called for a new session with an empty queue
50
- * (e.g. a subagent emitted events before the parent's tool_use was
51
- * parsed, or the runtime spawned a session we didn't expect), the
52
- * labeler falls back to `subagent#N` so log lines remain attributable.
41
+ * Two attribution channels are supported because the runtimes differ:
42
+ *
43
+ * - **OpenCode** spawns each subagent as its own opencode `Session` with
44
+ * a distinct `sessionID`. The harness records each Task dispatch into a
45
+ * pending FIFO queue; the next previously-unseen sessionID consumes the
46
+ * head of the queue and binds it to that label.
47
+ *
48
+ * - **Claude Code** runs subagents inside the orchestrator's session they
49
+ * all share `session_id` and instead stamps every subagent message with
50
+ * `parent_tool_use_id` pointing at the Agent tool_use id that spawned them.
51
+ * The harness binds each Agent tool_use id to its dispatched label up
52
+ * front, then `labelFor` looks the label up directly when an event arrives
53
+ * carrying that `parent_tool_use_id`.
54
+ *
55
+ * `labelFor(sessionID, parentToolUseId?)` accepts both: when
56
+ * `parentToolUseId` is set and known it short-circuits to the direct mapping;
57
+ * otherwise it falls through to the FIFO/sessionID path.
53
58
  */
54
59
  export declare class SessionLabeler {
55
60
  private readonly labels;
61
+ private readonly labelsByToolUseId;
56
62
  private readonly pendingLabels;
57
63
  private fallbackCounter;
58
- recordTaskDispatch(input: TaskDispatchInput): string;
59
64
  /**
60
- * Return a label for the given sessionID. Binds on first call.
61
- * Pass undefined/empty for events that lack a session id — the caller
62
- * gets ORCHESTRATOR_LABEL so the line is still attributable.
65
+ * Record a Task/Agent tool dispatch.
66
+ *
67
+ * @param input Task tool input used to derive the lens label.
68
+ * @param toolUseId Optional Agent tool_use id. When provided, future events
69
+ * carrying `parent_tool_use_id === toolUseId` resolve
70
+ * directly to this label without consuming the FIFO queue
71
+ * (Claude path). Always also pushed to the FIFO queue so
72
+ * the OpenCode path still works when toolUseId is absent.
73
+ */
74
+ recordTaskDispatch(input: TaskDispatchInput, toolUseId?: string | null): string;
75
+ /**
76
+ * Return a label for the given event.
77
+ *
78
+ * @param sessionID Session id from the event (OpenCode: per-session;
79
+ * Claude: shared across orchestrator + subagents).
80
+ * @param parentToolUseId Claude's `parent_tool_use_id` — non-null on
81
+ * subagent messages. When set and known, takes
82
+ * priority over the FIFO/sessionID path.
63
83
  */
64
- labelFor(sessionID: string | undefined | null): string;
84
+ labelFor(sessionID: string | undefined | null, parentToolUseId?: string | null): string;
65
85
  /** number of distinct sessions seen so far (for diagnostics) */
66
86
  size(): number;
67
87
  /** all (sessionID, label) pairs, oldest first */
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Derive a cheaper subagent model override from the orchestrator's resolved
3
+ * model spec.
4
+ *
5
+ * This is a pure registry lookup: every alias in `action/models.ts` declares
6
+ * its own `subagentModel` (alias key in the same provider). At runtime we
7
+ * reverse-lookup the orchestrator's resolved slug to find the alias that
8
+ * produced it, follow the `subagentModel` pointer, and return the target
9
+ * alias's resolve / openRouterResolve depending on which route the
10
+ * orchestrator was using.
11
+ *
12
+ * Returns `{ reviewer: undefined }` when the orchestrator's alias has no
13
+ * `subagentModel` (e.g. it's already at a sufficiently cheap tier, or its
14
+ * provider doesn't have a clean cheaper-but-capable sibling). See models.ts
15
+ * for the wiring + per-provider rationale.
16
+ */
17
+ export declare function deriveSubagentModels(orchestratorSpec: string | undefined): {
18
+ reviewer: string | undefined;
19
+ };