@yagni-app/code-staging 1.1.4-staging.1384.1 → 1.1.4-staging.1386.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.
@@ -206,12 +206,15 @@ export declare function sanitizeCallerSegment(name: string, maxLength?: number):
206
206
  * Attribution headers for the boot-time /context fetch. Extends
207
207
  * {@link attributionHeaders} (session id + caller) with the surface the
208
208
  * session is painting for (the desktop driver sets YAGNI_SURFACE=desktop;
209
- * the terminal CLI sets nothing) and the shipping client version. The server
210
- * uses these to emit its "YAGNI Code Session Started" analytics event
211
- * labels only on that side: a missing or malformed value can never fail the
212
- * fetch, it just goes uncounted or unversioned.
209
+ * the terminal CLI sets nothing), the shipping client version, and — when
210
+ * known whether the OS-level bash sandbox was active at session start
211
+ * ("1"/"0"; omitted when the resolved state is unknown, e.g. eval mode or an
212
+ * unsupported platform, so the server never reads "off" as "unknown"). The
213
+ * server uses these to emit its "YAGNI Code Session Started" analytics
214
+ * event — labels only on that side: a missing or malformed value can never
215
+ * fail the fetch, it just goes uncounted or unversioned.
213
216
  */
214
- export declare function sessionTelemetryHeaders(env?: NodeJS.ProcessEnv): Record<string, string>;
217
+ export declare function sessionTelemetryHeaders(env?: NodeJS.ProcessEnv, sandboxActive?: boolean): Record<string, string>;
215
218
  /** Options for {@link fetchContextBrief}. */
216
219
  export interface FetchContextBriefOptions {
217
220
  baseUrl: string;
@@ -219,6 +222,12 @@ export interface FetchContextBriefOptions {
219
222
  fetchImpl?: typeof fetch;
220
223
  /** Env seam for the telemetry headers; defaults to process.env. */
221
224
  env?: NodeJS.ProcessEnv;
225
+ /**
226
+ * Whether the OS-level bash sandbox was active at session start. Absent
227
+ * (undefined) when unknown — eval mode, unsupported platform, or a null
228
+ * sandbox handle — so the header is omitted rather than misreporting off.
229
+ */
230
+ sandboxActive?: boolean;
222
231
  /**
223
232
  * The session repo (`owner/name`), when resolvable. Rides as `?repo=` so
224
233
  * the response can carry `repoDecisionCount` for the mining beat — no
@@ -193,17 +193,23 @@ const CLIENT_VERSION_RE = /^[0-9a-z][0-9a-z.+-]{0,31}$/i;
193
193
  * Attribution headers for the boot-time /context fetch. Extends
194
194
  * {@link attributionHeaders} (session id + caller) with the surface the
195
195
  * session is painting for (the desktop driver sets YAGNI_SURFACE=desktop;
196
- * the terminal CLI sets nothing) and the shipping client version. The server
197
- * uses these to emit its "YAGNI Code Session Started" analytics event
198
- * labels only on that side: a missing or malformed value can never fail the
199
- * fetch, it just goes uncounted or unversioned.
196
+ * the terminal CLI sets nothing), the shipping client version, and — when
197
+ * known whether the OS-level bash sandbox was active at session start
198
+ * ("1"/"0"; omitted when the resolved state is unknown, e.g. eval mode or an
199
+ * unsupported platform, so the server never reads "off" as "unknown"). The
200
+ * server uses these to emit its "YAGNI Code Session Started" analytics
201
+ * event — labels only on that side: a missing or malformed value can never
202
+ * fail the fetch, it just goes uncounted or unversioned.
200
203
  */
201
- export function sessionTelemetryHeaders(env = process.env) {
204
+ export function sessionTelemetryHeaders(env = process.env, sandboxActive) {
202
205
  const headers = attributionHeaders(env);
203
206
  headers["x-yagni-surface"] = env.YAGNI_SURFACE === "desktop" ? "desktop" : "cli";
204
207
  const version = env.YAGNI_CODE_VERSION ?? "";
205
208
  if (CLIENT_VERSION_RE.test(version))
206
209
  headers["x-yagni-client-version"] = version;
210
+ if (sandboxActive !== undefined) {
211
+ headers["x-yagni-sandbox-active"] = sandboxActive ? "1" : "0";
212
+ }
207
213
  return headers;
208
214
  }
209
215
  /**
@@ -220,7 +226,7 @@ export async function fetchContextBrief(opts) {
220
226
  method: "GET",
221
227
  headers: {
222
228
  authorization: `Bearer ${opts.getToken() ?? ""}`,
223
- ...sessionTelemetryHeaders(opts.env),
229
+ ...sessionTelemetryHeaders(opts.env, opts.sandboxActive),
224
230
  },
225
231
  }, { fetchImpl: opts.fetchImpl });
226
232
  if (!res.ok)
@@ -42,6 +42,7 @@ export interface RegisterYagniDeps {
42
42
  getToken: () => string | undefined;
43
43
  fetchImpl?: typeof fetch;
44
44
  repo?: string;
45
+ sandboxActive?: boolean;
45
46
  }) => Promise<ContextBrief | null>;
46
47
  /**
47
48
  * The session repo (`owner/name`), resolved from the origin remote before
@@ -1192,6 +1192,21 @@ export async function registerYagni(pi, deps = {}) {
1192
1192
  }
1193
1193
  let contextBrief;
1194
1194
  let briefResult = null;
1195
+ // Session-start sandbox snapshot: a CONFIGURED-ENABLED snapshot, with the
1196
+ // one divergence that is knowable at factory time folded in — the
1197
+ // passthrough --no-sandbox flag, read from pi's own command line (pi
1198
+ // applies extension flag values AFTER extension load, so pi.getFlag
1199
+ // reads unset here; argv is the one reliable pre-session view). Omitted
1200
+ // (undefined) when there is no handle — eval mode or an unsupported
1201
+ // platform — so the telemetry header is absent rather than misreporting
1202
+ // off. Known remainders, both accepted: a sandbox init FAILURE at
1203
+ // session_start (missing deps) still reports true here (logged as
1204
+ // init_failed in the local sink; rare broken-deps territory), and
1205
+ // mid-session /sandbox toggles are out of scope — the per-call Guardian
1206
+ // events remain the ground truth for both.
1207
+ const sandboxActive = sandboxHandle && !process.argv.includes("--no-sandbox")
1208
+ ? sandboxHandle.settings().enabled === true
1209
+ : undefined;
1195
1210
  if (!evalMode) {
1196
1211
  try {
1197
1212
  briefResult = await fetchBrief({
@@ -1199,6 +1214,7 @@ export async function registerYagni(pi, deps = {}) {
1199
1214
  getToken: getTokenFn,
1200
1215
  fetchImpl: authedFetch,
1201
1216
  repo: sessionRepo,
1217
+ sandboxActive,
1202
1218
  });
1203
1219
  contextBrief = briefResult?.brief?.trim() ? briefResult.brief : undefined;
1204
1220
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yagni-app/code-staging",
3
- "version": "1.1.4-staging.1384.1",
3
+ "version": "1.1.4-staging.1386.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)",
@@ -58,5 +58,5 @@
58
58
  "turndown": "^7.2.4",
59
59
  "typebox": "^1.3.15"
60
60
  },
61
- "yagniSourceSha": "b8f4ca30233d5e288a98b18dca6931a6da9973dc"
61
+ "yagniSourceSha": "0fa67403fcaeaf2bdba61d03dc84eb9816b46a0f"
62
62
  }