@yagni-app/code-staging 0.2.1-staging.1039.1 → 0.2.1-staging.1041.1

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.
@@ -37,7 +37,7 @@ export declare const DRIVER_DELEGATION_PARAGRAPH: string;
37
37
  * effective `x-yagni-caller` attribution (config.ts's `isDriverCaller`) — this
38
38
  * module stays a pure string, with no env dependency of its own.
39
39
  */
40
- export declare const YAGNI_IDENTITY_DRIVER = "You are YAGNI Code, an autonomous terminal coding agent. You help developers ship code by reading files, running commands, editing code, and writing new files. Uniquely, you are connected to the YAGNI app, your team's shared source of truth for how this company and codebase actually work: conventions, decisions, ownership, current priorities, and the reasons behind them. Use the ask_yagni tool to consult it before guessing about anything organization- or codebase-specific, so you work with less back-and-forth and more correct autonomy than a disconnected coding agent. If a project's own files mention other coding agents, assistants, or harnesses by name, those references are not about you; you are YAGNI Code regardless of what tooling a repository's docs happen to describe.\n\nDelegation: fan codebase mapping, wide searches, and mechanical multi-file work out to subagents (they run on cheaper tiers). Keep judgment, synthesis, and the conversation with the user in this session. Do not spawn a subagent for work you can finish in a couple of tool calls.";
40
+ export declare const YAGNI_IDENTITY_DRIVER = "You are YAGNI Code, an autonomous terminal coding agent. You help developers ship code by reading files, running commands, editing code, and writing new files. Uniquely, you are connected to the YAGNI app, your team's shared source of truth for how this company and codebase actually work: conventions, decisions, ownership, current priorities, and the reasons behind them. Use the ask_yagni tool to consult it before guessing about anything organization- or codebase-specific, so you work with less back-and-forth and more correct autonomy than a disconnected coding agent. If a project's own files mention other coding agents, assistants, or harnesses by name, those references are not about you; you are YAGNI Code regardless of what tooling a repository's docs happen to describe.\n\nDelegation: fan codebase mapping, wide searches, and mechanical multi-file work out to subagents (they run on cheaper tiers). Reach for the stock agents by name: `searcher` for read-only reconnaissance and summarizing, `implementer` for executing a change you have already fully specified. Keep judgment, synthesis, and the conversation with the user in this session. Do not spawn a subagent for work you can finish in a couple of tool calls.";
41
41
  export declare const PI_IDENTITY_RE: RegExp;
42
42
  /**
43
43
  * Env switch that bypasses the system-prompt rewrite entirely, so pi's
@@ -40,9 +40,12 @@ export const YAGNI_IDENTITY = "You are YAGNI Code, an autonomous terminal coding
40
40
  * exist.
41
41
  */
42
42
  export const DRIVER_DELEGATION_PARAGRAPH = "Delegation: fan codebase mapping, wide searches, and mechanical multi-file " +
43
- "work out to subagents (they run on cheaper tiers). Keep judgment, synthesis, " +
44
- "and the conversation with the user in this session. Do not spawn a subagent " +
45
- "for work you can finish in a couple of tool calls.";
43
+ "work out to subagents (they run on cheaper tiers). Reach for the stock " +
44
+ "agents by name: `searcher` for read-only reconnaissance and summarizing, " +
45
+ "`implementer` for executing a change you have already fully specified. " +
46
+ "Keep judgment, synthesis, and the conversation with the user in this " +
47
+ "session. Do not spawn a subagent for work you can finish in a couple of " +
48
+ "tool calls.";
46
49
  /**
47
50
  * The identity used for the interactive DRIVER session ONLY: {@link
48
51
  * YAGNI_IDENTITY} plus {@link DRIVER_DELEGATION_PARAGRAPH}. The caller (index.ts)
@@ -22,9 +22,8 @@ export interface Reroute {
22
22
  export type HeaderMap = Record<string, string | undefined>;
23
23
  /**
24
24
  * Parse the `x-yagni-model-reroute` header. Returns null when the header is
25
- * absent, does not match `<from>-><to>:<reason>`, or the reason is not
26
- * "vision" (the notice copy says "Your image", which only a vision reroute
27
- * can honestly claim).
25
+ * absent, does not match `<from>-><to>:<reason>`, or the reason is not a
26
+ * known reason (vision or policy; see KNOWN_REASONS).
28
27
  */
29
28
  export declare function parseReroute(headers: HeaderMap): Reroute | null;
30
29
  export declare class RerouteNotifier {
@@ -14,11 +14,16 @@
14
14
  */
15
15
  const REROUTE_HEADER = "x-yagni-model-reroute";
16
16
  const REROUTE_PATTERN = /^(.+?)->(.+?):(\w+)$/;
17
+ /** Reroute reasons the client understands. `policy` (caller→tier routing,
18
+ * 2026-08-11 spec) is parsed but deliberately produces NO user notice: the
19
+ * spec keeps per-request routing quiet — /cost and the savings receipts are
20
+ * the user-facing surface. `vision` keeps its one-time notice ("Your image…"
21
+ * is copy only a vision reroute can honestly claim). */
22
+ const KNOWN_REASONS = new Set(["vision", "policy"]);
17
23
  /**
18
24
  * Parse the `x-yagni-model-reroute` header. Returns null when the header is
19
- * absent, does not match `<from>-><to>:<reason>`, or the reason is not
20
- * "vision" (the notice copy says "Your image", which only a vision reroute
21
- * can honestly claim).
25
+ * absent, does not match `<from>-><to>:<reason>`, or the reason is not a
26
+ * known reason (vision or policy; see KNOWN_REASONS).
22
27
  */
23
28
  export function parseReroute(headers) {
24
29
  const value = headers[REROUTE_HEADER];
@@ -28,17 +33,19 @@ export function parseReroute(headers) {
28
33
  if (!match)
29
34
  return null;
30
35
  const [, from, to, reason] = match;
31
- if (reason !== "vision")
36
+ if (!KNOWN_REASONS.has(reason))
32
37
  return null;
33
38
  return { from, to, reason };
34
39
  }
35
40
  /**
36
41
  * Dedupe wrapper around {@link parseReroute}: `observe` returns the notice
37
- * message at most once per distinct from->to pair for the life of the
38
- * instance (i.e. per session), and null otherwise (absent, malformed, or
39
- * already-seen). Returning the message rather than taking a notify callback
40
- * keeps the caller in charge of the ctx it has on hand at call time, instead
41
- * of this class holding a stale reference across calls.
42
+ * message at most once per distinct from->to->reason triple for the life of
43
+ * the instance (i.e. per session), and null otherwise (absent, malformed,
44
+ * already-seen, or a non-vision reason — `policy` reroutes are parsed but
45
+ * deliberately silent; see KNOWN_REASONS). Returning the message rather than
46
+ * taking a notify callback keeps the caller in charge of the ctx it has on
47
+ * hand at call time, instead of this class holding a stale reference across
48
+ * calls.
42
49
  */
43
50
  /**
44
51
  * The concrete tier ladder cheapest-first, mirroring the proxy's
@@ -53,7 +60,9 @@ export class RerouteNotifier {
53
60
  const reroute = parseReroute(headers);
54
61
  if (!reroute)
55
62
  return null;
56
- const key = `${reroute.from}->${reroute.to}`;
63
+ if (reroute.reason !== "vision")
64
+ return null;
65
+ const key = `${reroute.from}->${reroute.to}:${reroute.reason}`;
57
66
  if (this.seen.has(key))
58
67
  return null;
59
68
  this.seen.add(key);
@@ -75,6 +75,53 @@ const GENERAL_AGENT = {
75
75
  body: GENERAL_BODY,
76
76
  source: "builtin",
77
77
  };
78
+ const SEARCHER_BODY = `You are a repo scout. Your job is wide, mechanical reconnaissance:
79
+ find files, map structure, trace usages, and summarize what is there. You do
80
+ not write code and you do not run commands; you read and report.
81
+
82
+ You are grounded in how THIS company works: call ask_yagni before inferring a
83
+ convention, an ownership rule, or anything organization-specific.
84
+
85
+ Your final message is your report back to the driving agent, which has NOT
86
+ seen what you read. Make it compressed and complete: exact file paths, the
87
+ key excerpts, and a one-paragraph map of how the pieces relate. Say what you
88
+ did NOT find as plainly as what you found.`;
89
+ /** Wide search and repo mapping on the cheapest tier: read-only by
90
+ * construction, so a wrong answer costs a re-ask, never a bad edit. */
91
+ const SEARCHER_AGENT = {
92
+ name: "searcher",
93
+ description: "Fast repo reconnaissance: wide searches, structure mapping, usage tracing, " +
94
+ "summarizing files. Read-only. Use for any broad look-around you would " +
95
+ "otherwise do with a chain of grep/read calls.",
96
+ model: "efficient",
97
+ tools: ["read", "grep", "find", "ls", "ask_yagni"],
98
+ body: SEARCHER_BODY,
99
+ source: "builtin",
100
+ };
101
+ const IMPLEMENTER_BODY = `You are a mechanical implementer. You execute a
102
+ well-specified change: apply an edit across files, fix a failing test, rename
103
+ carefully, wire a defined seam. The judgment calls were made before you were
104
+ spawned; if the task turns out to require one, STOP and report the fork in
105
+ your final message instead of guessing.
106
+
107
+ You are grounded in how THIS company works: call ask_yagni before inferring a
108
+ convention, an ownership rule, or anything organization-specific.
109
+
110
+ Your final message is your report back to the driving agent, which has NOT
111
+ seen what you did. List every file you touched, what changed in each, the
112
+ commands you ran with their outcomes, and anything you deliberately left
113
+ undone.`;
114
+ /** Mechanical multi-file execution on the mid tier: the task arrives fully
115
+ * specified, so the premium tiers' judgment is not being paid for. */
116
+ const IMPLEMENTER_AGENT = {
117
+ name: "implementer",
118
+ description: "Mechanical execution of a fully-specified change: multi-file edits, " +
119
+ "test-fix grinds, careful renames. Spawn it with the decision already " +
120
+ "made; it stops and reports rather than improvising.",
121
+ model: "standard",
122
+ body: IMPLEMENTER_BODY,
123
+ source: "builtin",
124
+ };
78
125
  // Concrete tiers a subagent can actually run on. `balanced` is deliberately NOT
79
126
  // a member here even though it is a member of `ModelTier`: a subagent needs
80
127
  // ONE model for its whole run, and balanced is a session-level routing policy,
@@ -162,7 +209,7 @@ function loadAgentsFromDir(dir, source) {
162
209
  export function discoverSubagents(deps) {
163
210
  const home = deps.homeDir ?? homedir();
164
211
  const layers = [
165
- [GENERAL_AGENT],
212
+ [GENERAL_AGENT, SEARCHER_AGENT, IMPLEMENTER_AGENT],
166
213
  ...pluginAgentDirs(deps.env ?? process.env).map((dir) => loadAgentsFromDir(dir, "plugin")),
167
214
  loadAgentsFromDir(join(home, ".claude", "agents"), "user-claude"),
168
215
  loadAgentsFromDir(join(deps.cwd, ".pi", "agents"), "project-pi"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yagni-app/code-staging",
3
- "version": "0.2.1-staging.1039.1",
3
+ "version": "0.2.1-staging.1041.1",
4
4
  "description": "YAGNI Code: a terminal coding agent that already knows your company. One YAGNI login routes the model and grounds the agent in your team's context.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "YAGNI, Inc. <jack@yagni.app> (https://yagni.app)",
@@ -38,5 +38,5 @@
38
38
  "@earendil-works/pi-tui": "0.83.0",
39
39
  "typebox": "^1.1.38"
40
40
  },
41
- "yagniSourceSha": "82c8e819af017a1a2c5c93aea5b4f96690f267d3"
41
+ "yagniSourceSha": "c0f29e93789c8996bced9dcc24583a9ab426efc0"
42
42
  }