@integrity-labs/agt-cli 0.28.891 → 0.28.893

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.
Files changed (27) hide show
  1. package/dist/bin/agt.js +5 -5
  2. package/dist/{chunk-BH5RFBUM.js → chunk-5464FJVN.js} +86 -22
  3. package/dist/chunk-5464FJVN.js.map +1 -0
  4. package/dist/{chunk-2IVLMJXQ.js → chunk-5YD7HEY7.js} +4 -4
  5. package/dist/{chunk-SXYTFXPO.js → chunk-RAEBKUW2.js} +2 -2
  6. package/dist/{claude-pair-runtime-TCDKO2CZ.js → claude-pair-runtime-3MK5MUPN.js} +2 -2
  7. package/dist/lib/manager-worker.js +14 -39
  8. package/dist/lib/manager-worker.js.map +1 -1
  9. package/dist/mcp/augmented-admin.js +22 -6
  10. package/dist/mcp/direct-chat-channel.js +85 -21
  11. package/dist/mcp/index.js +85 -21
  12. package/dist/mcp/origami.js +85 -21
  13. package/dist/mcp/slack-channel.js +85 -21
  14. package/dist/mcp/telegram-channel.js +85 -21
  15. package/dist/{persistent-session-ZDZSEODJ.js → persistent-session-5HSYQBF7.js} +3 -3
  16. package/dist/{responsiveness-probe-7CY5VZMG.js → responsiveness-probe-ZSB3DLLI.js} +3 -3
  17. package/dist/{session-auth-dead-65TG2DLW.js → session-auth-dead-J7SQAYRR.js} +2 -2
  18. package/package.json +2 -2
  19. package/dist/assets/review/SKILL.md +0 -223
  20. package/dist/assets/review/SWEEP.md +0 -169
  21. package/dist/chunk-BH5RFBUM.js.map +0 -1
  22. /package/dist/{chunk-2IVLMJXQ.js.map → chunk-5YD7HEY7.js.map} +0 -0
  23. /package/dist/{chunk-SXYTFXPO.js.map → chunk-RAEBKUW2.js.map} +0 -0
  24. /package/dist/{claude-pair-runtime-TCDKO2CZ.js.map → claude-pair-runtime-3MK5MUPN.js.map} +0 -0
  25. /package/dist/{persistent-session-ZDZSEODJ.js.map → persistent-session-5HSYQBF7.js.map} +0 -0
  26. /package/dist/{responsiveness-probe-7CY5VZMG.js.map → responsiveness-probe-ZSB3DLLI.js.map} +0 -0
  27. /package/dist/{session-auth-dead-65TG2DLW.js.map → session-auth-dead-J7SQAYRR.js.map} +0 -0
@@ -35724,6 +35724,12 @@ var CURSOR_SHORTFALL_REASONS = [
35724
35724
  var NON_SHORTFALL_KEYS = new Set(CURSOR_ADVANCE_NON_SHORTFALL_KEYS);
35725
35725
  var KNOWN_REASONS = new Set(CURSOR_SHORTFALL_REASONS.filter((k) => !NON_SHORTFALL_KEYS.has(k)));
35726
35726
 
35727
+ // ../core/dist/direct-chat/agent-history-notices.js
35728
+ var AGENT_HISTORY_TURNS_ONLY_OR_FILTER = [
35729
+ "payload->>kind.is.null",
35730
+ `payload->>kind.in.("",${[...USER_FACING_NOTICE_KINDS].sort().join(",")})`
35731
+ ].join(",");
35732
+
35727
35733
  // ../core/dist/onboarding/state-machine.js
35728
35734
  var AREA_ORDER = [
35729
35735
  "framing",
@@ -38380,28 +38386,72 @@ var FLAG_REGISTRY = [
38380
38386
  },
38381
38387
  {
38382
38388
  key: "app-top-nav-shell",
38383
- description: "Global top-navigation shell redesign (ENG-8478 epic / ENG-8486). When ON, the dashboard chrome replaces the left sidebar with a top navigation bar (team switcher \xB7 destinations \xB7 command palette + account) so the left side is free for an agent-scoped rail; when OFF, the existing left sidebar is unchanged. Additive layout gate \u2014 no data-model change. Composes independently with agent-unified-screen (the two flags are reconciled in ENG-8488). Ships dark.",
38389
+ description: "Global top-navigation shell redesign (ENG-8478 epic / ENG-8486). When ON, the dashboard chrome replaces the left sidebar with a top navigation bar (team switcher \xB7 destinations \xB7 command palette + account) so the left side is free for an agent-scoped rail; when OFF, the existing left sidebar is unchanged. Additive layout gate \u2014 no data-model change. Composes independently with agent-unified-screen (the two flags are reconciled in ENG-8488). NO LONGER DARK: ENG-9831 cutover step 1 flipped the default to true, so an org with no override now gets the top-nav shell. The key survives only until cutover step 2 deletes it.",
38384
38390
  flagType: "boolean",
38385
- // Declared safe value is `false` = the current left sidebar. Fail-closed to the
38386
- // shell that ships today if the flag DB is unreachable.
38387
- defaultValue: false,
38388
- // Read CLIENT-SIDE by the dashboard layout + sidebar ("use client") via
38389
- // usePublicBooleanFlag, so the key must be in the browser-exposed public map.
38390
- // Additive layout gate not sensitive.
38391
+ // ENG-9831 (cutover step 1): flipped `false` -> `true`. The comment this
38392
+ // replaces called `false` the fail-closed direction — "the shell that ships
38393
+ // today". That was true while the sidebar was the shell that shipped; the
38394
+ // top nav is now the one being cut over to, so `false` points at the layout
38395
+ // being retired. The old rationale is recorded rather than deleted because
38396
+ // it was correct under a premise that has expired.
38397
+ //
38398
+ // NOTE the same split as ninjafy-brand below: this value is consulted by the
38399
+ // API evaluator when building the `GET /flags` map for an org with no
38400
+ // override. It is NOT the fallback the webapp uses on an outage — that is
38401
+ // the argument passed at the call site. Four call sites carry `true` to
38402
+ // match: (dashboard)/layout.tsx and the three legacy redirect hubs
38403
+ // (settings, team, organization/settings). Flipping the registry alone
38404
+ // leaves the cutover half-applied.
38405
+ defaultValue: true,
38406
+ // ENG-9831: NO LONGER read client-side. It was — via usePublicBooleanFlag in
38407
+ // sidebar.tsx (twice) and top-nav.tsx — and that is precisely what this
38408
+ // slice removed: a client hook starts at its default and corrects after an
38409
+ // async GET /flags, so the console painted the sidebar and then replaced the
38410
+ // WHOLE dashboard chrome after hydration. The ENG-8858/ENG-9227 flash at
38411
+ // layout scale. It is now resolved once server-side in (dashboard)/
38412
+ // layout.tsx and passed to both shells as a required prop.
38413
+ //
38414
+ // `public` MUST STAY ANYWAY — the same trap documented on ninjafy-brand.
38415
+ // getPublicBooleanFlagServer resolves against the very same public-filtered
38416
+ // `GET /flags` the browser uses (routes/flags.ts filters to
38417
+ // listPublicFlagKeys()). Drop `public` and the key is simply absent from the
38418
+ // map, the server helper falls through to its default forever, and every org
38419
+ // silently gets whatever that default happens to be with no error anywhere.
38420
+ // `public` means "readable through the public map", not "read by a browser".
38391
38421
  public: true
38392
38422
  },
38393
38423
  {
38394
38424
  key: "ninjafy-brand",
38395
- description: 'Present the product under the Ninjafy brand instead of Augmented Team (ENG-8250). This is the UMBRELLA brand gate, not a one-off nav toggle: every subsequent rebrand surface (page titles, email templates, marketing-facing copy) reads THIS key rather than adding its own flag, so the whole rebrand keeps a single kill switch. First surface is the left-hand nav wordmark \u2014 ON replaces the human+robot mark and the "augmented.team" text with italic lowercase "ninjafy"; OFF renders exactly what shipped before. Scope is the USER-FACING BRAND PRESENTATION \u2014 text AND VISUAL THEME. ENG-8858 widened this from text alone: the Ninjafy palette is gated here too, because a colour theme is not text. It stays ONE key rather than gaining a `ninjafy-theme` sibling, so a half-branded state \u2014 ninjafy wordmark over Augmented green \u2014 is unreachable and the rebrand keeps a single kill switch. It must never gate a code identifier, package name, env var or CLI name. EXISTING identifiers stay `Augmented`/`agt` per the CLAUDE.md naming contract, which protects them from premature renaming \u2014 the deep rename is workstream C of docs/runbooks/rebrand-ninjafy-migration.md and is out of scope here. That contract does NOT require NEW code to carry the old brand: artefacts created specifically for the rebrand take Ninjafy naming (ENG-8078 decision 9; see the CLAUDE.md rebrand carve-out). Either way it is a naming rule, not a flag concern \u2014 this key gates presentation, never an identifier. Set the stage-wide default to flip a whole environment, or add a feature_flag_overrides row to pilot a subset while everyone else still sees Augmented. Overrides resolve at FOUR grains, most specific first \u2014 agent, team, host, then org-wide (evaluate.ts:79-81); organization_id is always required, so there is no global override. Org and team are the useful pilot grains for THIS flag: there is now exactly ONE consumer \u2014 (dashboard)/layout.tsx via getPublicBooleanFlagServer \u2014 evaluating in the active-org cookie scope, so a host- or agent-scoped row is accepted by the table but never reached by the console. It resolves the key ONCE per request and passes the boolean down to sidebar.tsx and top-nav.tsx as a required prop. Resolution is SERVER-side deliberately: the client hook starts at its default and updates after an async GET /flags, so anything gated on it paints Augmented and then repaints. ENG-8858 moved the PALETTE for that reason (a full-page colour flash); ENG-9227 moved the WORDMARK, which had been the last surface still swapping after hydration. A consequence worth knowing: /login and the marketing routes stay on the Augmented palette whatever an org sets, because getPublicBooleanFlagServer returns the default without a verified session and a pre-auth page has neither a session nor an active org \u2014 a PER-ORG flag structurally cannot brand one. Those surfaces follow only when the stage-wide default flips. Ships dark.',
38425
+ description: 'Present the product under the Ninjafy brand instead of Augmented Team (ENG-8250). This is the UMBRELLA brand gate, not a one-off nav toggle: every subsequent rebrand surface (page titles, email templates, marketing-facing copy) reads THIS key rather than adding its own flag, so the whole rebrand keeps a single kill switch. First surface is the left-hand nav wordmark \u2014 ON replaces the human+robot mark and the "augmented.team" text with italic lowercase "ninjafy"; OFF renders exactly what shipped before. Scope is the USER-FACING BRAND PRESENTATION \u2014 text AND VISUAL THEME. ENG-8858 widened this from text alone: the Ninjafy palette is gated here too, because a colour theme is not text. It stays ONE key rather than gaining a `ninjafy-theme` sibling, so a half-branded state \u2014 ninjafy wordmark over Augmented green \u2014 is unreachable and the rebrand keeps a single kill switch. It must never gate a code identifier, package name, env var or CLI name. EXISTING identifiers stay `Augmented`/`agt` per the CLAUDE.md naming contract, which protects them from premature renaming \u2014 the deep rename is workstream C of docs/runbooks/rebrand-ninjafy-migration.md and is out of scope here. That contract does NOT require NEW code to carry the old brand: artefacts created specifically for the rebrand take Ninjafy naming (ENG-8078 decision 9; see the CLAUDE.md rebrand carve-out). Either way it is a naming rule, not a flag concern \u2014 this key gates presentation, never an identifier. Set the stage-wide default to flip a whole environment, or add a feature_flag_overrides row to pilot a subset while everyone else still sees Augmented. Overrides resolve at FOUR grains, most specific first \u2014 agent, team, host, then org-wide (evaluate.ts:79-81); organization_id is always required, so there is no global override. Org and team are the useful pilot grains for THIS flag: there is now exactly ONE consumer \u2014 (dashboard)/layout.tsx via getPublicBooleanFlagServer \u2014 evaluating in the active-org cookie scope, so a host- or agent-scoped row is accepted by the table but never reached by the console. It resolves the key ONCE per request and passes the boolean down to sidebar.tsx and top-nav.tsx as a required prop. Resolution is SERVER-side deliberately: the client hook starts at its default and updates after an async GET /flags, so anything gated on it paints Augmented and then repaints. ENG-8858 moved the PALETTE for that reason (a full-page colour flash); ENG-9227 moved the WORDMARK, which had been the last surface still swapping after hydration. A consequence worth knowing: /login and the marketing routes stay on the Augmented palette whatever an org sets, because fetchPublicFlags returns null without a verified session and a pre-auth page has neither a session nor an active org \u2014 a PER-ORG flag structurally cannot brand one. ENG-9830 CORRECTS what used to be written here ("those surfaces follow only when the stage-wide default flips"): they do not follow it at all. Two reasons. The value returned on a null fetch is the CALL SITE\u2019s passed argument, not this registry default; and six such pages (/login, /reset-password, /auth/confirm, the pre-redeem member-signin gate and the two public Slack-install terminal pages) do not mount <BrandStamp/> AT ALL \u2014 deliberately, enumerated with per-page reasons in eng-9266-brand-stamp-coverage.test.ts. They become branded when the flag is REMOVED at cutover step 2 and the palette moves into bare :root, with no read left to gate it. NO LONGER DARK: ENG-9830 cutover step 1 flipped the default to true, so an org with no override now sees Ninjafy. The key survives only until cutover step 2 deletes it.',
38396
38426
  flagType: "boolean",
38397
- // Declared safe value is `false`: the pre-rebrand brand. `false` is also the
38398
- // fail-closed direction if the flag DB is unreachable we must show the brand
38399
- // that is currently live and contractually correct, never leak an unannounced
38400
- // rebrand to every customer at once.
38401
- defaultValue: false,
38427
+ // ENG-9830 (cutover step 1): flipped `false` -> `true`. The comment this
38428
+ // replaces argued `false` was the fail-closed direction "never leak an
38429
+ // UNANNOUNCED rebrand to every customer at once". That was correct for as
38430
+ // long as the rebrand was unannounced. It is not any more: Ninjafy is the
38431
+ // live, announced brand (ENG-9613 reconciled the console onto the master
38432
+ // assets while the flag was already ON in production), so `false` now points
38433
+ // at the brand we no longer ship. A flags outage that reverted a customer to
38434
+ // Augmented would be the incident, not the safe harbour.
38435
+ //
38436
+ // The old rationale is recorded rather than deleted because it is a correct
38437
+ // argument whose PREMISE expired — reading the change without it looks like
38438
+ // someone overriding a deliberate fail-closed default.
38439
+ //
38440
+ // NOTE this value is only consulted by the API evaluator when building the
38441
+ // `GET /flags` map for an org with no override. It is NOT the fallback the
38442
+ // webapp uses on an outage: `getPublicBooleanFlagServer(key, defaultValue)`
38443
+ // returns its own PASSED argument when the fetch fails, so the call sites in
38444
+ // (dashboard)/layout.tsx and components/brand-stamp.tsx carry `true` too.
38445
+ // Flipping only one of the two leaves the cutover half-applied.
38446
+ defaultValue: true,
38402
38447
  // ENG-9227: there are NO client readers of this key left. (dashboard)/
38403
38448
  // layout.tsx resolves it ONCE server-side via getPublicBooleanFlagServer and
38404
38449
  // passes the boolean down to sidebar.tsx and top-nav.tsx as a required prop.
38450
+ // "ONCE" is about the chrome, not the key: components/brand-stamp.tsx is a
38451
+ // SECOND, independent server read of `ninjafy-brand` (CodeRabbit, #5385).
38452
+ // Both are listed in the note above because both carry an outage fallback
38453
+ // that has to move together — reading this paragraph alone would leave you
38454
+ // updating one of the two.
38405
38455
  // ENG-8858 did that for the THEME; ENG-9227 finished the job for the
38406
38456
  // WORDMARK, which had kept usePublicBooleanFlag and so kept swapping
38407
38457
  // "augmented.team" to "ninjafy" after hydration.
@@ -38423,24 +38473,38 @@ var FLAG_REGISTRY = [
38423
38473
  },
38424
38474
  {
38425
38475
  key: "ninjafy-logo",
38426
- description: "Which Ninjafy logo TREATMENT the console chrome renders (ENG-9365). This is a SUB-SELECTION under ninjafy-brand, not a second brand gate: it is consulted only once ninjafy-brand has already resolved ON, so with the brand off the value is inert and the half-branded state that flag's description calls unreachable stays unreachable. ninjafy-brand remains the single kill switch for the rebrand. It exists so candidate logo treatments can be put in front of a human and compared in the running console, rather than judged from a static export. lockup = mark and wordmark together, both in the brand blue \u2014 exactly what ENG-9298 shipped, so an unset flag is a no-op. two-tone = the mark in brand blue with the wordmark in the neutral text colour (the treatment of the blue-icon/black-wordmark artwork). wordmark = the word alone, no mark. Every treatment is composed from the ENG-9298 geometry \u2014 ENG-9312 pins that the lockup's blue path IS the mark subpath followed by the wordmark subpaths, byte for byte \u2014 so a new treatment is a composition, never a fresh trace, and the three drawings cannot drift apart. Surfaces are the dashboard sidebar and the top nav. The top nav shows the WORDMARK portion at every width whatever the treatment, because ENG-9342 decided that deliberately (a full lockup at the header's icon height crowds the team switcher on a phone) \u2014 so a treatment changes the word's colour there, never whether a mark appears. The admin sidebar (ENG-9323) is NOT wired to this key and always renders the mark; widening it is a separate decision. Resolved SERVER-SIDE in (dashboard)/layout.tsx via getPublicEnumFlagServer, beside ninjafy-brand and in the same single GET /flags round trip, then passed down as a required prop. That is not a style preference: the client hook starts at its default and updates after an async fetch, so a client read would paint one logo and swap it after hydration \u2014 the exact flash ENG-9227 removed from the wordmark and ENG-8858 removed from the palette. Org and team are the useful pilot grains, as for ninjafy-brand: the single consumer evaluates in the active-org cookie scope, so a host- or agent-scoped override row is accepted by the table but never reached by the console.",
38476
+ description: "Which Ninjafy logo TREATMENT the console chrome renders (ENG-9365). This is a SUB-SELECTION under ninjafy-brand, not a second brand gate: it is consulted only once ninjafy-brand has already resolved ON, so with the brand off the value is inert and the half-branded state that flag's description calls unreachable stays unreachable. ninjafy-brand remains the single kill switch for the rebrand. It existed so candidate logo treatments could be put in front of a human and compared in the running console, rather than judged from a static export. That comparison has happened: ENG-9830 cutover step 1 chose TWO-TONE, so that is now the default and an unset flag renders it. NOTE this reverses the property this description used to claim \u2014 an unset flag was a no-op while the default was lockup (what ENG-9298 shipped), and that is deliberately given up at cutover: the default MOVING is the change. The key survives only until cutover step 2 hardcodes the chosen treatment and deletes it. lockup = mark and wordmark together, both in the brand blue \u2014 what ENG-9298 shipped. two-tone = the mark in brand blue with the wordmark in the neutral text colour (the treatment of the blue-icon/black-wordmark artwork); the chosen one. wordmark = the word alone, no mark. Every treatment is composed from the ENG-9298 geometry \u2014 ENG-9312 pins that the lockup's blue path IS the mark subpath followed by the wordmark subpaths, byte for byte \u2014 so a new treatment is a composition, never a fresh trace, and the three drawings cannot drift apart. Surfaces are the dashboard sidebar and the top nav. The top nav shows the WORDMARK portion at every width whatever the treatment, because ENG-9342 decided that deliberately (a full lockup at the header's icon height crowds the team switcher on a phone) \u2014 so a treatment changes the word's colour there, never whether a mark appears. The admin sidebar (ENG-9323) is NOT wired to this key and always renders the mark; widening it is a separate decision. Resolved SERVER-SIDE in (dashboard)/layout.tsx via getPublicEnumFlagServer, beside ninjafy-brand and in the same single GET /flags round trip, then passed down as a required prop. That is not a style preference: the client hook starts at its default and updates after an async fetch, so a client read would paint one logo and swap it after hydration \u2014 the exact flash ENG-9227 removed from the wordmark and ENG-8858 removed from the palette. Org and team are the useful pilot grains, as for ninjafy-brand: the single consumer evaluates in the active-org cookie scope, so a host- or agent-scoped override row is accepted by the table but never reached by the console.",
38427
38477
  flagType: "enum",
38428
38478
  allowedValues: ["lockup", "two-tone", "wordmark"],
38429
- // Declared safe value is `lockup` what ENG-9298 shipped. This flag has no
38430
- // "off" direction: it selects among presentations that are all live-safe, so
38431
- // fail-safe here means "the treatment currently in production", not the
38479
+ // ENG-9830 (cutover step 1): `lockup` -> `two-tone`. The treatments existed
38480
+ // so they could be compared in the running console rather than judged from a
38481
+ // static export (ENG-9365); that comparison has now happened and `two-tone`
38482
+ // — the mark in brand blue with the wordmark in the neutral text colour — is
38483
+ // the chosen treatment. It becomes the hardcoded one when this key is
38484
+ // removed at cutover step 2.
38485
+ //
38486
+ // The rule this value obeys is unchanged: this flag has no "off" direction,
38487
+ // so fail-safe means "the treatment currently in production", not the
38432
38488
  // narrowest one. A flag-DB read error, an archived row, or a stored value
38433
38489
  // outside allowedValues all resolve here (evaluate.ts normalizeFlagValue),
38434
- // which is what makes an experimental value impossible to strand.
38435
- defaultValue: "lockup",
38490
+ // which is what makes an experimental value impossible to strand. Only which
38491
+ // treatment holds that position has moved.
38492
+ //
38493
+ // Same split as ninjafy-brand above: this governs the API evaluation path
38494
+ // only. The webapp's outage fallback is the argument passed at the
38495
+ // (dashboard)/layout.tsx call site, which carries 'two-tone' to match.
38496
+ defaultValue: "two-tone",
38436
38497
  // Same trap as ninjafy-brand, and it bites harder here because there are no
38437
38498
  // client readers of this key AT ALL — it is server-resolved by construction.
38438
38499
  // `public` does NOT mean "read by a browser"; it means "readable through the
38439
38500
  // public map". getPublicEnumFlagServer resolves against the same GET /flags
38440
38501
  // endpoint the browser uses, and that route filters to listPublicFlagKeys()
38441
38502
  // (routes/flags.ts). Drop `public` and the key is simply absent from the map,
38442
- // so the helper falls through to its default and returns `lockup` FOREVER
38443
- // the dropdown appearing to do nothing, with no error raised anywhere.
38503
+ // so the helper falls through to the fallback passed at that call site and
38504
+ // returns it FOREVER — the dropdown appearing to do nothing, with no error
38505
+ // raised anywhere. Named as the call site rather than as a literal on
38506
+ // purpose: this comment said `lockup` for exactly as long as `lockup` was
38507
+ // the answer, and ENG-9830 flipping the winner is what made it a lie.
38444
38508
  public: true
38445
38509
  },
38446
38510
  {
@@ -35774,6 +35774,12 @@ var CURSOR_SHORTFALL_REASONS = [
35774
35774
  var NON_SHORTFALL_KEYS = new Set(CURSOR_ADVANCE_NON_SHORTFALL_KEYS);
35775
35775
  var KNOWN_REASONS = new Set(CURSOR_SHORTFALL_REASONS.filter((k) => !NON_SHORTFALL_KEYS.has(k)));
35776
35776
 
35777
+ // ../core/dist/direct-chat/agent-history-notices.js
35778
+ var AGENT_HISTORY_TURNS_ONLY_OR_FILTER = [
35779
+ "payload->>kind.is.null",
35780
+ `payload->>kind.in.("",${[...USER_FACING_NOTICE_KINDS].sort().join(",")})`
35781
+ ].join(",");
35782
+
35777
35783
  // ../core/dist/onboarding/state-machine.js
35778
35784
  var AREA_ORDER = [
35779
35785
  "framing",
@@ -38430,28 +38436,72 @@ var FLAG_REGISTRY = [
38430
38436
  },
38431
38437
  {
38432
38438
  key: "app-top-nav-shell",
38433
- description: "Global top-navigation shell redesign (ENG-8478 epic / ENG-8486). When ON, the dashboard chrome replaces the left sidebar with a top navigation bar (team switcher \xB7 destinations \xB7 command palette + account) so the left side is free for an agent-scoped rail; when OFF, the existing left sidebar is unchanged. Additive layout gate \u2014 no data-model change. Composes independently with agent-unified-screen (the two flags are reconciled in ENG-8488). Ships dark.",
38439
+ description: "Global top-navigation shell redesign (ENG-8478 epic / ENG-8486). When ON, the dashboard chrome replaces the left sidebar with a top navigation bar (team switcher \xB7 destinations \xB7 command palette + account) so the left side is free for an agent-scoped rail; when OFF, the existing left sidebar is unchanged. Additive layout gate \u2014 no data-model change. Composes independently with agent-unified-screen (the two flags are reconciled in ENG-8488). NO LONGER DARK: ENG-9831 cutover step 1 flipped the default to true, so an org with no override now gets the top-nav shell. The key survives only until cutover step 2 deletes it.",
38434
38440
  flagType: "boolean",
38435
- // Declared safe value is `false` = the current left sidebar. Fail-closed to the
38436
- // shell that ships today if the flag DB is unreachable.
38437
- defaultValue: false,
38438
- // Read CLIENT-SIDE by the dashboard layout + sidebar ("use client") via
38439
- // usePublicBooleanFlag, so the key must be in the browser-exposed public map.
38440
- // Additive layout gate not sensitive.
38441
+ // ENG-9831 (cutover step 1): flipped `false` -> `true`. The comment this
38442
+ // replaces called `false` the fail-closed direction — "the shell that ships
38443
+ // today". That was true while the sidebar was the shell that shipped; the
38444
+ // top nav is now the one being cut over to, so `false` points at the layout
38445
+ // being retired. The old rationale is recorded rather than deleted because
38446
+ // it was correct under a premise that has expired.
38447
+ //
38448
+ // NOTE the same split as ninjafy-brand below: this value is consulted by the
38449
+ // API evaluator when building the `GET /flags` map for an org with no
38450
+ // override. It is NOT the fallback the webapp uses on an outage — that is
38451
+ // the argument passed at the call site. Four call sites carry `true` to
38452
+ // match: (dashboard)/layout.tsx and the three legacy redirect hubs
38453
+ // (settings, team, organization/settings). Flipping the registry alone
38454
+ // leaves the cutover half-applied.
38455
+ defaultValue: true,
38456
+ // ENG-9831: NO LONGER read client-side. It was — via usePublicBooleanFlag in
38457
+ // sidebar.tsx (twice) and top-nav.tsx — and that is precisely what this
38458
+ // slice removed: a client hook starts at its default and corrects after an
38459
+ // async GET /flags, so the console painted the sidebar and then replaced the
38460
+ // WHOLE dashboard chrome after hydration. The ENG-8858/ENG-9227 flash at
38461
+ // layout scale. It is now resolved once server-side in (dashboard)/
38462
+ // layout.tsx and passed to both shells as a required prop.
38463
+ //
38464
+ // `public` MUST STAY ANYWAY — the same trap documented on ninjafy-brand.
38465
+ // getPublicBooleanFlagServer resolves against the very same public-filtered
38466
+ // `GET /flags` the browser uses (routes/flags.ts filters to
38467
+ // listPublicFlagKeys()). Drop `public` and the key is simply absent from the
38468
+ // map, the server helper falls through to its default forever, and every org
38469
+ // silently gets whatever that default happens to be with no error anywhere.
38470
+ // `public` means "readable through the public map", not "read by a browser".
38441
38471
  public: true
38442
38472
  },
38443
38473
  {
38444
38474
  key: "ninjafy-brand",
38445
- description: 'Present the product under the Ninjafy brand instead of Augmented Team (ENG-8250). This is the UMBRELLA brand gate, not a one-off nav toggle: every subsequent rebrand surface (page titles, email templates, marketing-facing copy) reads THIS key rather than adding its own flag, so the whole rebrand keeps a single kill switch. First surface is the left-hand nav wordmark \u2014 ON replaces the human+robot mark and the "augmented.team" text with italic lowercase "ninjafy"; OFF renders exactly what shipped before. Scope is the USER-FACING BRAND PRESENTATION \u2014 text AND VISUAL THEME. ENG-8858 widened this from text alone: the Ninjafy palette is gated here too, because a colour theme is not text. It stays ONE key rather than gaining a `ninjafy-theme` sibling, so a half-branded state \u2014 ninjafy wordmark over Augmented green \u2014 is unreachable and the rebrand keeps a single kill switch. It must never gate a code identifier, package name, env var or CLI name. EXISTING identifiers stay `Augmented`/`agt` per the CLAUDE.md naming contract, which protects them from premature renaming \u2014 the deep rename is workstream C of docs/runbooks/rebrand-ninjafy-migration.md and is out of scope here. That contract does NOT require NEW code to carry the old brand: artefacts created specifically for the rebrand take Ninjafy naming (ENG-8078 decision 9; see the CLAUDE.md rebrand carve-out). Either way it is a naming rule, not a flag concern \u2014 this key gates presentation, never an identifier. Set the stage-wide default to flip a whole environment, or add a feature_flag_overrides row to pilot a subset while everyone else still sees Augmented. Overrides resolve at FOUR grains, most specific first \u2014 agent, team, host, then org-wide (evaluate.ts:79-81); organization_id is always required, so there is no global override. Org and team are the useful pilot grains for THIS flag: there is now exactly ONE consumer \u2014 (dashboard)/layout.tsx via getPublicBooleanFlagServer \u2014 evaluating in the active-org cookie scope, so a host- or agent-scoped row is accepted by the table but never reached by the console. It resolves the key ONCE per request and passes the boolean down to sidebar.tsx and top-nav.tsx as a required prop. Resolution is SERVER-side deliberately: the client hook starts at its default and updates after an async GET /flags, so anything gated on it paints Augmented and then repaints. ENG-8858 moved the PALETTE for that reason (a full-page colour flash); ENG-9227 moved the WORDMARK, which had been the last surface still swapping after hydration. A consequence worth knowing: /login and the marketing routes stay on the Augmented palette whatever an org sets, because getPublicBooleanFlagServer returns the default without a verified session and a pre-auth page has neither a session nor an active org \u2014 a PER-ORG flag structurally cannot brand one. Those surfaces follow only when the stage-wide default flips. Ships dark.',
38475
+ description: 'Present the product under the Ninjafy brand instead of Augmented Team (ENG-8250). This is the UMBRELLA brand gate, not a one-off nav toggle: every subsequent rebrand surface (page titles, email templates, marketing-facing copy) reads THIS key rather than adding its own flag, so the whole rebrand keeps a single kill switch. First surface is the left-hand nav wordmark \u2014 ON replaces the human+robot mark and the "augmented.team" text with italic lowercase "ninjafy"; OFF renders exactly what shipped before. Scope is the USER-FACING BRAND PRESENTATION \u2014 text AND VISUAL THEME. ENG-8858 widened this from text alone: the Ninjafy palette is gated here too, because a colour theme is not text. It stays ONE key rather than gaining a `ninjafy-theme` sibling, so a half-branded state \u2014 ninjafy wordmark over Augmented green \u2014 is unreachable and the rebrand keeps a single kill switch. It must never gate a code identifier, package name, env var or CLI name. EXISTING identifiers stay `Augmented`/`agt` per the CLAUDE.md naming contract, which protects them from premature renaming \u2014 the deep rename is workstream C of docs/runbooks/rebrand-ninjafy-migration.md and is out of scope here. That contract does NOT require NEW code to carry the old brand: artefacts created specifically for the rebrand take Ninjafy naming (ENG-8078 decision 9; see the CLAUDE.md rebrand carve-out). Either way it is a naming rule, not a flag concern \u2014 this key gates presentation, never an identifier. Set the stage-wide default to flip a whole environment, or add a feature_flag_overrides row to pilot a subset while everyone else still sees Augmented. Overrides resolve at FOUR grains, most specific first \u2014 agent, team, host, then org-wide (evaluate.ts:79-81); organization_id is always required, so there is no global override. Org and team are the useful pilot grains for THIS flag: there is now exactly ONE consumer \u2014 (dashboard)/layout.tsx via getPublicBooleanFlagServer \u2014 evaluating in the active-org cookie scope, so a host- or agent-scoped row is accepted by the table but never reached by the console. It resolves the key ONCE per request and passes the boolean down to sidebar.tsx and top-nav.tsx as a required prop. Resolution is SERVER-side deliberately: the client hook starts at its default and updates after an async GET /flags, so anything gated on it paints Augmented and then repaints. ENG-8858 moved the PALETTE for that reason (a full-page colour flash); ENG-9227 moved the WORDMARK, which had been the last surface still swapping after hydration. A consequence worth knowing: /login and the marketing routes stay on the Augmented palette whatever an org sets, because fetchPublicFlags returns null without a verified session and a pre-auth page has neither a session nor an active org \u2014 a PER-ORG flag structurally cannot brand one. ENG-9830 CORRECTS what used to be written here ("those surfaces follow only when the stage-wide default flips"): they do not follow it at all. Two reasons. The value returned on a null fetch is the CALL SITE\u2019s passed argument, not this registry default; and six such pages (/login, /reset-password, /auth/confirm, the pre-redeem member-signin gate and the two public Slack-install terminal pages) do not mount <BrandStamp/> AT ALL \u2014 deliberately, enumerated with per-page reasons in eng-9266-brand-stamp-coverage.test.ts. They become branded when the flag is REMOVED at cutover step 2 and the palette moves into bare :root, with no read left to gate it. NO LONGER DARK: ENG-9830 cutover step 1 flipped the default to true, so an org with no override now sees Ninjafy. The key survives only until cutover step 2 deletes it.',
38446
38476
  flagType: "boolean",
38447
- // Declared safe value is `false`: the pre-rebrand brand. `false` is also the
38448
- // fail-closed direction if the flag DB is unreachable we must show the brand
38449
- // that is currently live and contractually correct, never leak an unannounced
38450
- // rebrand to every customer at once.
38451
- defaultValue: false,
38477
+ // ENG-9830 (cutover step 1): flipped `false` -> `true`. The comment this
38478
+ // replaces argued `false` was the fail-closed direction "never leak an
38479
+ // UNANNOUNCED rebrand to every customer at once". That was correct for as
38480
+ // long as the rebrand was unannounced. It is not any more: Ninjafy is the
38481
+ // live, announced brand (ENG-9613 reconciled the console onto the master
38482
+ // assets while the flag was already ON in production), so `false` now points
38483
+ // at the brand we no longer ship. A flags outage that reverted a customer to
38484
+ // Augmented would be the incident, not the safe harbour.
38485
+ //
38486
+ // The old rationale is recorded rather than deleted because it is a correct
38487
+ // argument whose PREMISE expired — reading the change without it looks like
38488
+ // someone overriding a deliberate fail-closed default.
38489
+ //
38490
+ // NOTE this value is only consulted by the API evaluator when building the
38491
+ // `GET /flags` map for an org with no override. It is NOT the fallback the
38492
+ // webapp uses on an outage: `getPublicBooleanFlagServer(key, defaultValue)`
38493
+ // returns its own PASSED argument when the fetch fails, so the call sites in
38494
+ // (dashboard)/layout.tsx and components/brand-stamp.tsx carry `true` too.
38495
+ // Flipping only one of the two leaves the cutover half-applied.
38496
+ defaultValue: true,
38452
38497
  // ENG-9227: there are NO client readers of this key left. (dashboard)/
38453
38498
  // layout.tsx resolves it ONCE server-side via getPublicBooleanFlagServer and
38454
38499
  // passes the boolean down to sidebar.tsx and top-nav.tsx as a required prop.
38500
+ // "ONCE" is about the chrome, not the key: components/brand-stamp.tsx is a
38501
+ // SECOND, independent server read of `ninjafy-brand` (CodeRabbit, #5385).
38502
+ // Both are listed in the note above because both carry an outage fallback
38503
+ // that has to move together — reading this paragraph alone would leave you
38504
+ // updating one of the two.
38455
38505
  // ENG-8858 did that for the THEME; ENG-9227 finished the job for the
38456
38506
  // WORDMARK, which had kept usePublicBooleanFlag and so kept swapping
38457
38507
  // "augmented.team" to "ninjafy" after hydration.
@@ -38473,24 +38523,38 @@ var FLAG_REGISTRY = [
38473
38523
  },
38474
38524
  {
38475
38525
  key: "ninjafy-logo",
38476
- description: "Which Ninjafy logo TREATMENT the console chrome renders (ENG-9365). This is a SUB-SELECTION under ninjafy-brand, not a second brand gate: it is consulted only once ninjafy-brand has already resolved ON, so with the brand off the value is inert and the half-branded state that flag's description calls unreachable stays unreachable. ninjafy-brand remains the single kill switch for the rebrand. It exists so candidate logo treatments can be put in front of a human and compared in the running console, rather than judged from a static export. lockup = mark and wordmark together, both in the brand blue \u2014 exactly what ENG-9298 shipped, so an unset flag is a no-op. two-tone = the mark in brand blue with the wordmark in the neutral text colour (the treatment of the blue-icon/black-wordmark artwork). wordmark = the word alone, no mark. Every treatment is composed from the ENG-9298 geometry \u2014 ENG-9312 pins that the lockup's blue path IS the mark subpath followed by the wordmark subpaths, byte for byte \u2014 so a new treatment is a composition, never a fresh trace, and the three drawings cannot drift apart. Surfaces are the dashboard sidebar and the top nav. The top nav shows the WORDMARK portion at every width whatever the treatment, because ENG-9342 decided that deliberately (a full lockup at the header's icon height crowds the team switcher on a phone) \u2014 so a treatment changes the word's colour there, never whether a mark appears. The admin sidebar (ENG-9323) is NOT wired to this key and always renders the mark; widening it is a separate decision. Resolved SERVER-SIDE in (dashboard)/layout.tsx via getPublicEnumFlagServer, beside ninjafy-brand and in the same single GET /flags round trip, then passed down as a required prop. That is not a style preference: the client hook starts at its default and updates after an async fetch, so a client read would paint one logo and swap it after hydration \u2014 the exact flash ENG-9227 removed from the wordmark and ENG-8858 removed from the palette. Org and team are the useful pilot grains, as for ninjafy-brand: the single consumer evaluates in the active-org cookie scope, so a host- or agent-scoped override row is accepted by the table but never reached by the console.",
38526
+ description: "Which Ninjafy logo TREATMENT the console chrome renders (ENG-9365). This is a SUB-SELECTION under ninjafy-brand, not a second brand gate: it is consulted only once ninjafy-brand has already resolved ON, so with the brand off the value is inert and the half-branded state that flag's description calls unreachable stays unreachable. ninjafy-brand remains the single kill switch for the rebrand. It existed so candidate logo treatments could be put in front of a human and compared in the running console, rather than judged from a static export. That comparison has happened: ENG-9830 cutover step 1 chose TWO-TONE, so that is now the default and an unset flag renders it. NOTE this reverses the property this description used to claim \u2014 an unset flag was a no-op while the default was lockup (what ENG-9298 shipped), and that is deliberately given up at cutover: the default MOVING is the change. The key survives only until cutover step 2 hardcodes the chosen treatment and deletes it. lockup = mark and wordmark together, both in the brand blue \u2014 what ENG-9298 shipped. two-tone = the mark in brand blue with the wordmark in the neutral text colour (the treatment of the blue-icon/black-wordmark artwork); the chosen one. wordmark = the word alone, no mark. Every treatment is composed from the ENG-9298 geometry \u2014 ENG-9312 pins that the lockup's blue path IS the mark subpath followed by the wordmark subpaths, byte for byte \u2014 so a new treatment is a composition, never a fresh trace, and the three drawings cannot drift apart. Surfaces are the dashboard sidebar and the top nav. The top nav shows the WORDMARK portion at every width whatever the treatment, because ENG-9342 decided that deliberately (a full lockup at the header's icon height crowds the team switcher on a phone) \u2014 so a treatment changes the word's colour there, never whether a mark appears. The admin sidebar (ENG-9323) is NOT wired to this key and always renders the mark; widening it is a separate decision. Resolved SERVER-SIDE in (dashboard)/layout.tsx via getPublicEnumFlagServer, beside ninjafy-brand and in the same single GET /flags round trip, then passed down as a required prop. That is not a style preference: the client hook starts at its default and updates after an async fetch, so a client read would paint one logo and swap it after hydration \u2014 the exact flash ENG-9227 removed from the wordmark and ENG-8858 removed from the palette. Org and team are the useful pilot grains, as for ninjafy-brand: the single consumer evaluates in the active-org cookie scope, so a host- or agent-scoped override row is accepted by the table but never reached by the console.",
38477
38527
  flagType: "enum",
38478
38528
  allowedValues: ["lockup", "two-tone", "wordmark"],
38479
- // Declared safe value is `lockup` what ENG-9298 shipped. This flag has no
38480
- // "off" direction: it selects among presentations that are all live-safe, so
38481
- // fail-safe here means "the treatment currently in production", not the
38529
+ // ENG-9830 (cutover step 1): `lockup` -> `two-tone`. The treatments existed
38530
+ // so they could be compared in the running console rather than judged from a
38531
+ // static export (ENG-9365); that comparison has now happened and `two-tone`
38532
+ // — the mark in brand blue with the wordmark in the neutral text colour — is
38533
+ // the chosen treatment. It becomes the hardcoded one when this key is
38534
+ // removed at cutover step 2.
38535
+ //
38536
+ // The rule this value obeys is unchanged: this flag has no "off" direction,
38537
+ // so fail-safe means "the treatment currently in production", not the
38482
38538
  // narrowest one. A flag-DB read error, an archived row, or a stored value
38483
38539
  // outside allowedValues all resolve here (evaluate.ts normalizeFlagValue),
38484
- // which is what makes an experimental value impossible to strand.
38485
- defaultValue: "lockup",
38540
+ // which is what makes an experimental value impossible to strand. Only which
38541
+ // treatment holds that position has moved.
38542
+ //
38543
+ // Same split as ninjafy-brand above: this governs the API evaluation path
38544
+ // only. The webapp's outage fallback is the argument passed at the
38545
+ // (dashboard)/layout.tsx call site, which carries 'two-tone' to match.
38546
+ defaultValue: "two-tone",
38486
38547
  // Same trap as ninjafy-brand, and it bites harder here because there are no
38487
38548
  // client readers of this key AT ALL — it is server-resolved by construction.
38488
38549
  // `public` does NOT mean "read by a browser"; it means "readable through the
38489
38550
  // public map". getPublicEnumFlagServer resolves against the same GET /flags
38490
38551
  // endpoint the browser uses, and that route filters to listPublicFlagKeys()
38491
38552
  // (routes/flags.ts). Drop `public` and the key is simply absent from the map,
38492
- // so the helper falls through to its default and returns `lockup` FOREVER
38493
- // the dropdown appearing to do nothing, with no error raised anywhere.
38553
+ // so the helper falls through to the fallback passed at that call site and
38554
+ // returns it FOREVER — the dropdown appearing to do nothing, with no error
38555
+ // raised anywhere. Named as the call site rather than as a literal on
38556
+ // purpose: this comment said `lockup` for exactly as long as `lockup` was
38557
+ // the answer, and ENG-9830 flipping the winner is what made it a lie.
38494
38558
  public: true
38495
38559
  },
38496
38560
  {
@@ -62,8 +62,8 @@ import {
62
62
  writeDirectChatSessionState,
63
63
  writeEgressAllowlist,
64
64
  writePersistentClaudeWrapper
65
- } from "./chunk-SXYTFXPO.js";
66
- import "./chunk-BH5RFBUM.js";
65
+ } from "./chunk-RAEBKUW2.js";
66
+ import "./chunk-5464FJVN.js";
67
67
  import "./chunk-XWVM4KPK.js";
68
68
  export {
69
69
  CLAUDE_HOST_WIDE,
@@ -130,4 +130,4 @@ export {
130
130
  writeEgressAllowlist,
131
131
  writePersistentClaudeWrapper
132
132
  };
133
- //# sourceMappingURL=persistent-session-ZDZSEODJ.js.map
133
+ //# sourceMappingURL=persistent-session-5HSYQBF7.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  paneLogPath
3
- } from "./chunk-SXYTFXPO.js";
4
- import "./chunk-BH5RFBUM.js";
3
+ } from "./chunk-RAEBKUW2.js";
4
+ import "./chunk-5464FJVN.js";
5
5
  import "./chunk-XWVM4KPK.js";
6
6
 
7
7
  // src/lib/responsiveness-probe.ts
@@ -764,4 +764,4 @@ export {
764
764
  readAndResetSlackReplyBindingClassifications,
765
765
  readAndResetSlackReplyTargetClassifications
766
766
  };
767
- //# sourceMappingURL=responsiveness-probe-7CY5VZMG.js.map
767
+ //# sourceMappingURL=responsiveness-probe-ZSB3DLLI.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sessionTranscriptDir
3
- } from "./chunk-BH5RFBUM.js";
3
+ } from "./chunk-5464FJVN.js";
4
4
 
5
5
  // src/lib/session-auth-dead.ts
6
6
  import { closeSync, openSync, readSync, readdirSync, statSync } from "fs";
@@ -203,4 +203,4 @@ export {
203
203
  decideSessionAuthState,
204
204
  probeSessionAuth
205
205
  };
206
- //# sourceMappingURL=session-auth-dead-65TG2DLW.js.map
206
+ //# sourceMappingURL=session-auth-dead-J7SQAYRR.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.891",
3
+ "version": "0.28.893",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {
@@ -24,7 +24,7 @@
24
24
  "scripts": {
25
25
  "build": "tsup && npm run build:mcp-assets && npm run build:cli-assets",
26
26
  "build:mcp-assets": "mkdir -p dist/mcp && cp ../../packages/mcp/dist/index.js dist/mcp/index.js && cp ../../packages/mcp/dist/slack-channel.js dist/mcp/slack-channel.js && cp ../../packages/mcp/dist/direct-chat-channel.js dist/mcp/direct-chat-channel.js && cp ../../packages/mcp/dist/telegram-channel.js dist/mcp/telegram-channel.js && cp ../../packages/mcp/dist/teams-channel.js dist/mcp/teams-channel.js && cp ../../packages/mcp/dist/whatsapp-channel.js dist/mcp/whatsapp-channel.js && cp ../../packages/mcp/dist/whatsapp-link.js dist/mcp/whatsapp-link.js && cp ../../packages/mcp/dist/remote-oauth-proxy.js dist/mcp/remote-oauth-proxy.js && cp ../../packages/mcp/dist/computer-use-proxy.js dist/mcp/computer-use-proxy.js && cp ../../packages/augmented-admin-mcp/dist/index.js dist/mcp/augmented-admin.js && cp ../../packages/augmented-support-mcp/dist/index.js dist/mcp/augmented-support.js && cp ../../packages/augmented-help-kb-mcp/dist/index.js dist/mcp/augmented-help-kb.js && cp ../../packages/origami-mcp-server/dist/index.js dist/mcp/origami.js && cp ../../packages/xero-mcp-server/dist/index.js dist/mcp/xero.js",
27
- "build:cli-assets": "mkdir -p dist/assets && cp assets/impersonate-statusline.sh dist/assets/impersonate-statusline.sh && chmod +x dist/assets/impersonate-statusline.sh && mkdir -p dist/assets/review && cp assets/review/post-review-findings.mjs dist/assets/review/post-review-findings.mjs && cp assets/review/obiwan-auth.mjs dist/assets/review/obiwan-auth.mjs && cp assets/review/SKILL.md dist/assets/review/SKILL.md && cp assets/review/SWEEP.md dist/assets/review/SWEEP.md && chmod +x dist/assets/review/post-review-findings.mjs",
27
+ "build:cli-assets": "mkdir -p dist/assets && cp assets/impersonate-statusline.sh dist/assets/impersonate-statusline.sh && chmod +x dist/assets/impersonate-statusline.sh && mkdir -p dist/assets/review && cp assets/review/post-review-findings.mjs dist/assets/review/post-review-findings.mjs && cp assets/review/obiwan-auth.mjs dist/assets/review/obiwan-auth.mjs && chmod +x dist/assets/review/post-review-findings.mjs",
28
28
  "dev": "tsx watch src/bin/agt.ts",
29
29
  "test": "vitest run",
30
30
  "typecheck": "bash ../../scripts/typecheck-guard.sh tsc --noEmit",