@reticlehq/init 2.14.0 → 3.2.0

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 (125) hide show
  1. package/dist/{detect.d.ts → detect/detect.d.ts} +1 -1
  2. package/dist/{detect.js → detect/detect.js} +6 -2
  3. package/dist/{dev-server-ports.js → detect/dev-server-ports.js} +8 -0
  4. package/dist/{existing-config.d.ts → detect/existing-config.d.ts} +2 -4
  5. package/dist/{existing-config.js → detect/existing-config.js} +2 -4
  6. package/dist/{lockfiles.d.ts → detect/lockfiles.d.ts} +1 -1
  7. package/dist/{lockfiles.js → detect/lockfiles.js} +1 -2
  8. package/dist/{workspace-apps.d.ts → detect/workspace-apps.d.ts} +3 -5
  9. package/dist/{workspace-apps.js → detect/workspace-apps.js} +2 -4
  10. package/dist/{workspace-redirect.d.ts → detect/workspace-redirect.d.ts} +3 -5
  11. package/dist/{workspace-redirect.js → detect/workspace-redirect.js} +8 -12
  12. package/dist/{closing-hint.d.ts → diagnose/closing-hint.d.ts} +3 -4
  13. package/dist/{closing-hint.js → diagnose/closing-hint.js} +14 -19
  14. package/dist/diagnose/containerised-dev-server.d.ts +32 -0
  15. package/dist/diagnose/containerised-dev-server.js +56 -0
  16. package/dist/{csp-check.d.ts → diagnose/csp-check.d.ts} +2 -2
  17. package/dist/{csp-check.js → diagnose/csp-check.js} +2 -2
  18. package/dist/{desktop-doctor.js → diagnose/desktop-doctor.js} +12 -6
  19. package/dist/{init-failure.d.ts → diagnose/init-failure.d.ts} +1 -2
  20. package/dist/{init-failure.js → diagnose/init-failure.js} +1 -2
  21. package/dist/diagnose/install-hint.d.ts +8 -0
  22. package/dist/{install-hint.js → diagnose/install-hint.js} +3 -4
  23. package/dist/{install-retries.d.ts → diagnose/install-retries.d.ts} +3 -4
  24. package/dist/{install-retries.js → diagnose/install-retries.js} +6 -8
  25. package/dist/host.d.ts +14 -1
  26. package/dist/host.js +3 -0
  27. package/dist/index.d.ts +32 -12
  28. package/dist/index.js +36 -12
  29. package/dist/node-io.d.ts +12 -1
  30. package/dist/node-io.js +53 -25
  31. package/dist/{astro-patch.d.ts → patch/astro-patch.d.ts} +1 -1
  32. package/dist/{astro-patch.js → patch/astro-patch.js} +1 -1
  33. package/dist/{cra.js → patch/cra.js} +1 -1
  34. package/dist/{electron-patch.js → patch/electron-patch.js} +1 -1
  35. package/dist/{next-patch.d.ts → patch/next-patch.d.ts} +2 -2
  36. package/dist/{next-patch.js → patch/next-patch.js} +2 -2
  37. package/dist/{nuxt-patch.js → patch/nuxt-patch.js} +1 -1
  38. package/dist/{snippets.d.ts → patch/snippets.d.ts} +11 -21
  39. package/dist/{snippets.js → patch/snippets.js} +20 -29
  40. package/dist/{tanstack-start.d.ts → patch/tanstack-start.d.ts} +2 -3
  41. package/dist/{tanstack-start.js → patch/tanstack-start.js} +3 -4
  42. package/dist/{vite-config.js → patch/vite-config.js} +15 -13
  43. package/dist/{connect-steps.d.ts → plan/connect-steps.d.ts} +3 -3
  44. package/dist/{connect-steps.js → plan/connect-steps.js} +4 -4
  45. package/dist/{framework-adapter.d.ts → plan/framework-adapter.d.ts} +11 -2
  46. package/dist/{framework-adapter.js → plan/framework-adapter.js} +12 -1
  47. package/dist/plan/notices.d.ts +23 -0
  48. package/dist/plan/notices.js +94 -0
  49. package/dist/{plan-electron-vite.d.ts → plan/plan-electron-vite.d.ts} +3 -4
  50. package/dist/{plan-electron-vite.js → plan/plan-electron-vite.js} +7 -8
  51. package/dist/{plan-framework.d.ts → plan/plan-framework.d.ts} +4 -13
  52. package/dist/{plan-framework.js → plan/plan-framework.js} +14 -34
  53. package/dist/{plan.d.ts → plan/plan-types.d.ts} +14 -17
  54. package/dist/plan/plan-types.js +24 -0
  55. package/dist/plan/plan.d.ts +20 -0
  56. package/dist/{plan.js → plan/plan.js} +27 -88
  57. package/dist/{agent-rules.d.ts → project/agent-rules.d.ts} +2 -2
  58. package/dist/{agent-rules.js → project/agent-rules.js} +17 -21
  59. package/dist/project/install-source-config.d.ts +14 -0
  60. package/dist/{install-source-config.js → project/install-source-config.js} +3 -7
  61. package/dist/project/remember-project.js +74 -0
  62. package/dist/register/detect-clients.d.ts +23 -0
  63. package/dist/register/detect-clients.js +28 -0
  64. package/dist/{mcp-clients.js → register/mcp-clients.js} +4 -8
  65. package/dist/{mcp-registered.d.ts → register/mcp-registered.d.ts} +1 -4
  66. package/dist/{mcp-registered.js → register/mcp-registered.js} +1 -4
  67. package/dist/{mcp.d.ts → register/mcp.d.ts} +5 -8
  68. package/dist/{mcp.js → register/mcp.js} +6 -9
  69. package/dist/register/slash-command.d.ts +27 -0
  70. package/dist/{slash-command.js → register/slash-command.js} +10 -10
  71. package/dist/register/windows-quote.d.ts +17 -0
  72. package/dist/register/windows-quote.js +49 -0
  73. package/dist/run-types.d.ts +131 -0
  74. package/dist/run-types.js +8 -0
  75. package/dist/run.d.ts +3 -120
  76. package/dist/run.js +111 -56
  77. package/package.json +5 -5
  78. package/dist/install-hint.d.ts +0 -9
  79. package/dist/install-source-config.d.ts +0 -18
  80. package/dist/remember-project.js +0 -40
  81. package/dist/slash-command.d.ts +0 -27
  82. package/dist/windows-quote.d.ts +0 -38
  83. package/dist/windows-quote.js +0 -70
  84. /package/dist/{capabilities.d.ts → detect/capabilities.d.ts} +0 -0
  85. /package/dist/{capabilities.js → detect/capabilities.js} +0 -0
  86. /package/dist/{app-choice.d.ts → detect/declared/app-choice.d.ts} +0 -0
  87. /package/dist/{app-choice.js → detect/declared/app-choice.js} +0 -0
  88. /package/dist/{init-opt-out.d.ts → detect/declared/init-opt-out.d.ts} +0 -0
  89. /package/dist/{init-opt-out.js → detect/declared/init-opt-out.js} +0 -0
  90. /package/dist/{dev-script.d.ts → detect/dev-script.d.ts} +0 -0
  91. /package/dist/{dev-script.js → detect/dev-script.js} +0 -0
  92. /package/dist/{dev-server-ports.d.ts → detect/dev-server-ports.d.ts} +0 -0
  93. /package/dist/{non-js-project.d.ts → detect/non-js-project.d.ts} +0 -0
  94. /package/dist/{non-js-project.js → detect/non-js-project.js} +0 -0
  95. /package/dist/{platform.d.ts → detect/platform.d.ts} +0 -0
  96. /package/dist/{platform.js → detect/platform.js} +0 -0
  97. /package/dist/{csp-doctor.d.ts → diagnose/csp-doctor.d.ts} +0 -0
  98. /package/dist/{csp-doctor.js → diagnose/csp-doctor.js} +0 -0
  99. /package/dist/{desktop-doctor.d.ts → diagnose/desktop-doctor.d.ts} +0 -0
  100. /package/dist/{astro-host.d.ts → patch/astro-host.d.ts} +0 -0
  101. /package/dist/{astro-host.js → patch/astro-host.js} +0 -0
  102. /package/dist/{brace-scan.d.ts → patch/brace-scan.d.ts} +0 -0
  103. /package/dist/{brace-scan.js → patch/brace-scan.js} +0 -0
  104. /package/dist/{cra.d.ts → patch/cra.d.ts} +0 -0
  105. /package/dist/{electron-patch.d.ts → patch/electron-patch.d.ts} +0 -0
  106. /package/dist/{electron-vite-patch.d.ts → patch/electron-vite-patch.d.ts} +0 -0
  107. /package/dist/{electron-vite-patch.js → patch/electron-vite-patch.js} +0 -0
  108. /package/dist/{format-generated.d.ts → patch/format-generated.d.ts} +0 -0
  109. /package/dist/{format-generated.js → patch/format-generated.js} +0 -0
  110. /package/dist/{nuxt-patch.d.ts → patch/nuxt-patch.d.ts} +0 -0
  111. /package/dist/{patch-kind.d.ts → patch/patch-kind.d.ts} +0 -0
  112. /package/dist/{patch-kind.js → patch/patch-kind.js} +0 -0
  113. /package/dist/{vite-config.d.ts → patch/vite-config.d.ts} +0 -0
  114. /package/dist/{vite-owning-config.d.ts → patch/vite-owning-config.d.ts} +0 -0
  115. /package/dist/{vite-owning-config.js → patch/vite-owning-config.js} +0 -0
  116. /package/dist/{preflight.d.ts → plan/preflight.d.ts} +0 -0
  117. /package/dist/{preflight.js → plan/preflight.js} +0 -0
  118. /package/dist/{project-id.d.ts → project/project-id.d.ts} +0 -0
  119. /package/dist/{project-id.js → project/project-id.js} +0 -0
  120. /package/dist/{refresh-rules.d.ts → project/refresh-rules.d.ts} +0 -0
  121. /package/dist/{refresh-rules.js → project/refresh-rules.js} +0 -0
  122. /package/dist/{remember-project.d.ts → project/remember-project.d.ts} +0 -0
  123. /package/dist/{codex-toml.d.ts → register/codex-toml.d.ts} +0 -0
  124. /package/dist/{codex-toml.js → register/codex-toml.js} +0 -0
  125. /package/dist/{mcp-clients.d.ts → register/mcp-clients.d.ts} +0 -0
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Steps that TELL the user something rather than change anything.
3
+ *
4
+ * `StepStatus.NOTICE` exists because reporting these as `manual` made "steps left to do" a
5
+ * number that could never reach zero. They are one category by that test: a dev server in a
6
+ * container, an MCP registration Windows will not take, a UI library no gate covers. Reticle is
7
+ * not going to fix any of them and the user is better off knowing.
8
+ *
9
+ * They live together because that shared test is a real seam.
10
+ */
11
+ import { CONTAINERISED_TITLE, containerisedDevServerNote } from '../diagnose/containerised-dev-server.js';
12
+ import { mcpWindowsNote } from '../register/mcp.js';
13
+ import { unverifiedUiLibraryNote, WEBGL_CANVAS_LIMIT_NOTE } from '../patch/snippets.js';
14
+ import { FRAMEWORK_ADAPTERS } from './framework-adapter.js';
15
+ import { NodePlatform } from '../detect/platform.js';
16
+ import { UiLibrary } from '../detect/detect.js';
17
+ // `Step` and `PlanInput` are TYPES, so importing them back from `plan.ts` is erased at build
18
+ // time and creates no cycle. `StepStatus` and `MCP_TARGET` are values, and both are read inside
19
+ // function bodies rather than at module scope, which is what keeps the pair safe to import in
20
+ // both directions. If a third value is ever needed here, move the vocabulary to its own module
21
+ // rather than widening this.
22
+ import { MCP_TARGET, StepStatus } from './plan-types.js';
23
+ const WINDOWS_MCP_TITLE = 'Windows MCP spawn';
24
+ /**
25
+ * The two things a containerised dev server does differently, said before they go wrong.
26
+ *
27
+ * Null for every project with no container marker near it, which is almost all of them — so this
28
+ * adds nothing to the ordinary plan and does not move the install baseline.
29
+ */
30
+ export function containerisedStep(input) {
31
+ const marker = input.containerMarker;
32
+ if (marker === undefined || 0 === marker.length)
33
+ return null;
34
+ return {
35
+ title: CONTAINERISED_TITLE,
36
+ target: marker,
37
+ status: StepStatus.NOTICE,
38
+ detail: containerisedDevServerNote(marker),
39
+ };
40
+ }
41
+ /** Windows only. The reported install never reached mcpManual because `claude mcp add` succeeded. */
42
+ export function windowsMcpNoteStep(input) {
43
+ if (input.platform !== NodePlatform.WINDOWS)
44
+ return null;
45
+ return {
46
+ title: WINDOWS_MCP_TITLE,
47
+ target: MCP_TARGET,
48
+ status: StepStatus.NOTICE,
49
+ detail: mcpWindowsNote(),
50
+ };
51
+ }
52
+ /**
53
+ * A step that says out loud when the app isn't React. SvelteKit already carries its own unverified
54
+ * note, so it isn't doubled up here.
55
+ */
56
+ export function uiLibraryStep(input) {
57
+ const lib = input.detection.uiLibrary;
58
+ // A framework whose own recipe already says it is unverified must not be argued with by a second,
59
+ // more generic notice. Asked of the registry rather than of a remembered `SVELTEKIT || NUXT` pair:
60
+ // the pair was the answer, not the question, and a third framework joining it was a silent edit.
61
+ if (lib === UiLibrary.REACT)
62
+ return [];
63
+ if (FRAMEWORK_ADAPTERS[input.detection.framework].carriesOwnUnverifiedNote)
64
+ return [];
65
+ if (lib === UiLibrary.UNKNOWN)
66
+ return [];
67
+ return [
68
+ {
69
+ title: `${lib} is UNVERIFIED`,
70
+ target: 'package.json',
71
+ status: StepStatus.NOTICE,
72
+ detail: unverifiedUiLibraryNote(lib),
73
+ },
74
+ ];
75
+ }
76
+ /**
77
+ * A WebGL subtree is pixels, and Reticle reads the DOM.
78
+ *
79
+ * react-three-fiber and its relatives render into a canvas, so the tools that find and drive
80
+ * elements have nothing to find. Disclosed rather than blocked: the rest of the app is still
81
+ * verifiable and a NOTICE says which part is not.
82
+ */
83
+ export function webGlCanvasStep(input) {
84
+ if (true !== input.detection.webGlSubtree)
85
+ return [];
86
+ return [
87
+ {
88
+ title: 'WebGL canvas is not observable',
89
+ target: 'package.json',
90
+ status: StepStatus.NOTICE,
91
+ detail: WEBGL_CANVAS_LIMIT_NOTE,
92
+ },
93
+ ];
94
+ }
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * The plan's electron-vite half: the renderer plugin, capabilities, and the two Electron steps.
3
3
  *
4
- * Its own module rather than more of `plan-framework.ts`, which was at the 1000-line backstop.
5
- * Cohesive on its own terms: this is the only framework whose wiring reaches outside the renderer,
6
- * into a preload and a main process that the web frameworks have no equivalent of.
4
+ * Its own module because this is the only framework whose wiring reaches outside the renderer, into
5
+ * a preload and a main process the web frameworks have no equivalent of.
7
6
  */
8
- import { type PlanInput, type Step } from './plan.js';
7
+ import { type PlanInput, type Step } from './plan-types.js';
9
8
  /**
10
9
  * electron-vite: the renderer plugin, then capabilities, then the two Electron halves.
11
10
  *
@@ -1,17 +1,16 @@
1
1
  /**
2
2
  * The plan's electron-vite half: the renderer plugin, capabilities, and the two Electron steps.
3
3
  *
4
- * Its own module rather than more of `plan-framework.ts`, which was at the 1000-line backstop.
5
- * Cohesive on its own terms: this is the only framework whose wiring reaches outside the renderer,
6
- * into a preload and a main process that the web frameworks have no equivalent of.
4
+ * Its own module because this is the only framework whose wiring reaches outside the renderer, into
5
+ * a preload and a main process the web frameworks have no equivalent of.
7
6
  */
8
- import { StepStatus } from './plan.js';
7
+ import { StepStatus } from './plan-types.js';
9
8
  import { StepTitle } from './connect-steps.js';
10
9
  import { capabilitiesStep, patchStep } from './plan-framework.js';
11
- import { patchElectronViteConfig } from './electron-vite-patch.js';
12
- import { patchElectronMain, patchElectronPreload } from './electron-patch.js';
13
- import { ELECTRON_CAPTURE_FIX, ELECTRON_PRELOAD_FIX } from './desktop-doctor.js';
14
- import { electronViteManual, ELECTRON_VITE_DEV_MODULE_PATH } from './snippets.js';
10
+ import { patchElectronViteConfig } from '../patch/electron-vite-patch.js';
11
+ import { patchElectronMain, patchElectronPreload } from '../patch/electron-patch.js';
12
+ import { ELECTRON_CAPTURE_FIX, ELECTRON_PRELOAD_FIX } from '../diagnose/desktop-doctor.js';
13
+ import { electronViteManual, ELECTRON_VITE_DEV_MODULE_PATH } from '../patch/snippets.js';
15
14
  /**
16
15
  * electron-vite: the renderer plugin, then capabilities, then the two Electron halves.
17
16
  *
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * How each framework gets wired: the Vite plugin, the three Next files, the SvelteKit client hook.
3
- * Split out of `plan.ts` — that file is the plan's SHAPE (statuses, ordering, the agent/MCP steps),
4
- * this one is the per-framework detail, and they grow for different reasons.
3
+ * `plan.ts` is the plan's SHAPE (statuses, ordering, the agent/MCP steps); this is the per-framework
4
+ * detail, and they grow for different reasons.
5
5
  */
6
- import { type SourcePatch } from './patch-kind.js';
7
- import { type PlanInput, type Step } from './plan.js';
6
+ import { type SourcePatch } from '../patch/patch-kind.js';
7
+ import { type PlanInput, type Step } from './plan-types.js';
8
8
  import { StepTitle } from './connect-steps.js';
9
9
  /** What adding `reticle()` to a Vite config buys, which differs by framework. */
10
10
  export declare const VITE_PLUGIN_DETAIL: {
@@ -111,12 +111,3 @@ export declare function cspStep(input: PlanInput): Step[];
111
111
  * where the if/else chain this replaced used to hand it these instructions silently.
112
112
  */
113
113
  export declare function htmlSteps(input: PlanInput): Step[];
114
- /**
115
- * The per-framework half of the plan, looked up rather than switched.
116
- *
117
- * `FRAMEWORK_ADAPTERS` is a `Record<Framework, FrameworkAdapter>`, so a member added to `Framework`
118
- * is a compile error in that one table instead of a framework the plan quietly does not serve. The
119
- * exhaustive switch this replaced gave the same guarantee for the steps alone; the record gives it
120
- * for the packages, the connect-step titles and the unverified-note flag in the same edit.
121
- */
122
- export declare function frameworkSteps(input: PlanInput): Step[];
@@ -1,24 +1,23 @@
1
1
  /**
2
2
  * How each framework gets wired: the Vite plugin, the three Next files, the SvelteKit client hook.
3
- * Split out of `plan.ts` — that file is the plan's SHAPE (statuses, ordering, the agent/MCP steps),
4
- * this one is the per-framework detail, and they grow for different reasons.
3
+ * `plan.ts` is the plan's SHAPE (statuses, ordering, the agent/MCP steps); this is the per-framework
4
+ * detail, and they grow for different reasons.
5
5
  */
6
6
  import { bridgeWsUrl } from '@reticlehq/core';
7
- import { patchViteConfig, VitePatchKind, VITE_IMPORT } from './vite-config.js';
8
- import { patchNextConfig, patchRootLayout, patchPagesApp } from './next-patch.js';
9
- import { ASTRO_ENV_DTS_PATH, patchAstroConfig, patchAstroEnvDts, patchAstroLayout, } from './astro-patch.js';
10
- import { CRA_DEV_MODULE_IMPORT, CRA_ENV_PATH, CRA_TOKEN_PER_MACHINE_NOTICE, TOKEN_VAR, craDevModuleFile, craDevModulePath, craEnvPatch, craImportPatch, } from './cra.js';
11
- import { PatchKind } from './patch-kind.js';
12
- import { viteManual, NEXT_LAYOUT_MANUAL, NEXT_LAYOUT_PATH, viteDevModuleFile, VITE_DEV_MODULE_PATH, nextReticleDevFile, NEXT_RETICLE_DEV_PATH, nextConfigManual, svelteKitHooksFile, SVELTEKIT_HOOKS_PATH, UNVERIFIED_FRAMEWORK_NOTE, astroManual, nuxtManual, nuxtPluginFile, nuxtPluginPath, NUXT_PLUGIN_NOTICE, webpack4TranspileNote, WEBPACK4_REACT_SCRIPTS_MAJOR, reactRouterEntryFile, reactRouterEntryPatch, REACT_ROUTER_ENTRY_PATH, UNVERIFIED_TANSTACK_START_NOTE, htmlManual, } from './snippets.js';
13
- import { hasOptOut, OPT_OUT_MARKER } from './init-opt-out.js';
14
- import { StepStatus } from './plan.js';
7
+ import { patchViteConfig, VitePatchKind, VITE_IMPORT } from '../patch/vite-config.js';
8
+ import { patchNextConfig, patchRootLayout, patchPagesApp } from '../patch/next-patch.js';
9
+ import { ASTRO_ENV_DTS_PATH, patchAstroConfig, patchAstroEnvDts, patchAstroLayout, } from '../patch/astro-patch.js';
10
+ import { CRA_DEV_MODULE_IMPORT, CRA_ENV_PATH, CRA_TOKEN_PER_MACHINE_NOTICE, TOKEN_VAR, craDevModuleFile, craDevModulePath, craEnvPatch, craImportPatch, } from '../patch/cra.js';
11
+ import { PatchKind } from '../patch/patch-kind.js';
12
+ import { viteManual, NEXT_LAYOUT_MANUAL, NEXT_LAYOUT_PATH, viteDevModuleFile, VITE_DEV_MODULE_PATH, nextReticleDevFile, NEXT_RETICLE_DEV_PATH, nextConfigManual, svelteKitHooksFile, SVELTEKIT_HOOKS_PATH, UNVERIFIED_FRAMEWORK_NOTE, astroManual, nuxtManual, nuxtPluginFile, nuxtPluginPath, NUXT_PLUGIN_NOTICE, webpack4TranspileNote, WEBPACK4_REACT_SCRIPTS_MAJOR, reactRouterEntryFile, reactRouterEntryPatch, REACT_ROUTER_ENTRY_PATH, UNVERIFIED_TANSTACK_START_NOTE, htmlManual, } from '../patch/snippets.js';
13
+ import { hasOptOut, OPT_OUT_MARKER } from '../detect/declared/init-opt-out.js';
14
+ import { StepStatus } from './plan-types.js';
15
15
  import { RETICLE_DEFAULT_PORT } from '@reticlehq/core';
16
- import { CSP_STEP_TITLE } from './csp-check.js';
16
+ import { CSP_STEP_TITLE } from '../diagnose/csp-check.js';
17
17
  import { StepTitle } from './connect-steps.js';
18
- import { tanstackStartManual, TANSTACK_START_ROOT_PATH } from './tanstack-start.js';
19
- import { FRAMEWORK_ADAPTERS } from './framework-adapter.js';
20
- import { diagnoseWebCsp } from './csp-doctor.js';
21
- import { patchNuxtConfig } from './nuxt-patch.js';
18
+ import { tanstackStartManual, TANSTACK_START_ROOT_PATH } from '../patch/tanstack-start.js';
19
+ import { diagnoseWebCsp } from '../diagnose/csp-doctor.js';
20
+ import { patchNuxtConfig } from '../patch/nuxt-patch.js';
22
21
  /** What adding `reticle()` to a Vite config buys, which differs by framework. */
23
22
  export const VITE_PLUGIN_DETAIL = {
24
23
  /** A plain Vite app gets both halves from the plugin. */
@@ -352,14 +351,6 @@ export function nextSteps(input) {
352
351
  patchStep(StepTitle.MOUNT_RETICLE_DEV, layout?.path ?? NEXT_LAYOUT_PATH, layoutPatch, 'mount <ReticleDev /> in the root layout (dev-only)', NEXT_LAYOUT_MANUAL),
353
352
  ];
354
353
  }
355
- /**
356
- * SvelteKit is WIRED but not SUPPORTED, and the plan says so out loud.
357
- *
358
- * There is no SvelteKit app in `apps/` and no CI gate for one, so nothing proves this hook still
359
- * registers a session — every other framework init offers (React, Next, Remix, Astro) has both. The
360
- * wiring is real and may well work; what is missing is anything that would tell us when it stops.
361
- * Silently emitting it reads as a support claim, which is the thing this project exists to not do.
362
- */
363
354
  /**
364
355
  * The one failure `init` cannot otherwise see: the bundler will not parse our SDK.
365
356
  *
@@ -760,14 +751,3 @@ export function htmlSteps(input) {
760
751
  },
761
752
  ];
762
753
  }
763
- /**
764
- * The per-framework half of the plan, looked up rather than switched.
765
- *
766
- * `FRAMEWORK_ADAPTERS` is a `Record<Framework, FrameworkAdapter>`, so a member added to `Framework`
767
- * is a compile error in that one table instead of a framework the plan quietly does not serve. The
768
- * exhaustive switch this replaced gave the same guarantee for the steps alone; the record gives it
769
- * for the packages, the connect-step titles and the unverified-note flag in the same edit.
770
- */
771
- export function frameworkSteps(input) {
772
- return FRAMEWORK_ADAPTERS[input.detection.framework].steps(input);
773
- }
@@ -1,22 +1,13 @@
1
1
  /**
2
- * Pure assembly of the `reticle init` action plan. Given the detection result and the relevant file
3
- * contents, produce an ordered list of steps — each marked apply / manual / already / skip. The
4
- * runner performs the `write` side-effects; this module decides *what* should happen.
5
- */
6
- import { Framework, UiLibrary, type Detection } from './detect.js';
7
- import type { FoundStore } from './capabilities.js';
8
- import { McpClient } from './mcp-clients.js';
9
- import { RETICLE_CONFIG_FILE } from './existing-config.js';
10
- export { RETICLE_CONFIG_FILE };
11
- /**
12
- * The dev-dependencies `reticle init` installs — kit (or sensor) first, build plugin next.
2
+ * The plan's vocabulary: what a step IS, what status it can be in, and what a plan is built from.
13
3
  *
14
- * `uiLibrary` matters because the framework does not always name the renderer. The rule below was
15
- * already written for Nuxt, correctly, and applied only there: a Vue app on plain Vite is
16
- * `Framework.VITE` and a SvelteKit app renders Svelte, and both were being handed the React kit
17
- * right after `init` had detected the real UI library and said so on screen.
4
+ * A leaf. Four modules that `plan.ts` calls — the framework adapters, the electron-vite steps, the
5
+ * per-framework steps and the notices — each named these to declare their own signatures, and all
6
+ * four had to import them back out of the module that calls them.
18
7
  */
19
- export declare function frameworkPackages(framework: Framework, uiLibrary?: UiLibrary): readonly string[];
8
+ import type { Detection, Framework, UiLibrary } from '../detect/detect.js';
9
+ import type { FoundStore } from '../detect/capabilities.js';
10
+ import type { McpClient } from '../register/mcp-clients.js';
20
11
  /** Exported so the init telemetry can tell an MCP-registration failure from a dependency install. */
21
12
  export declare const MCP_TARGET = "global (claude user scope)";
22
13
  /** The step that runs the package manager — the other thing that commonly fails on a user's machine. */
@@ -260,6 +251,13 @@ export interface PlanInput {
260
251
  pairingToken?: string;
261
252
  /** Whether .reticle.json already exists in the project root (idempotency). */
262
253
  reticleConfigExists?: boolean;
254
+ /**
255
+ * The container marker found near the app (`Dockerfile`, `docker-compose.yml`, …), or undefined.
256
+ *
257
+ * Not proof the dev server runs in one — see containerised-dev-server.ts for why over-eager is the
258
+ * right direction here, and for what goes wrong when it does.
259
+ */
260
+ containerMarker?: string | undefined;
263
261
  /**
264
262
  * Its CONTENT, so an existing config can be checked instead of trusted.
265
263
  *
@@ -309,4 +307,3 @@ export interface PlanInput {
309
307
  sdkVersion?: string;
310
308
  };
311
309
  }
312
- export declare function buildPlan(input: PlanInput): Plan;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The plan's vocabulary: what a step IS, what status it can be in, and what a plan is built from.
3
+ *
4
+ * A leaf. Four modules that `plan.ts` calls — the framework adapters, the electron-vite steps, the
5
+ * per-framework steps and the notices — each named these to declare their own signatures, and all
6
+ * four had to import them back out of the module that calls them.
7
+ */
8
+ /** Exported so the init telemetry can tell an MCP-registration failure from a dependency install. */
9
+ export const MCP_TARGET = 'global (claude user scope)';
10
+ /** The step that runs the package manager — the other thing that commonly fails on a user's machine. */
11
+ export const DEPS_TARGET = 'package.json';
12
+ export const StepStatus = {
13
+ APPLY: 'apply',
14
+ MANUAL: 'manual',
15
+ ALREADY: 'already',
16
+ SKIP: 'skip',
17
+ /**
18
+ * Something the user should KNOW, not something they must DO. The UNVERIFIED lines are the case:
19
+ * a Preact or SvelteKit app is wired and working, it just isn't covered by a gate. Reporting those
20
+ * as `manual` made "steps left to do" a number that could never reach zero, and made a release gate
21
+ * read two regressions that were not regressions.
22
+ */
23
+ NOTICE: 'notice',
24
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Pure assembly of the `reticle init` action plan. Given the detection result and the relevant file
3
+ * contents, produce an ordered list of steps — each marked apply / manual / already / skip. The
4
+ * runner performs the `write` side-effects; this module decides *what* should happen.
5
+ */
6
+ import { Framework, UiLibrary } from '../detect/detect.js';
7
+ import { type Plan, type PlanInput } from './plan-types.js';
8
+ export { DEPS_TARGET, MCP_TARGET, StepStatus, type Step, type Plan, type PlanInput, } from './plan-types.js';
9
+ import { RETICLE_CONFIG_FILE } from '../detect/existing-config.js';
10
+ export { RETICLE_CONFIG_FILE };
11
+ /**
12
+ * The dev-dependencies `reticle init` installs — kit (or sensor) first, build plugin next.
13
+ *
14
+ * `uiLibrary` matters because the framework does not always name the renderer. The rule below was
15
+ * already written for Nuxt, correctly, and applied only there: a Vue app on plain Vite is
16
+ * `Framework.VITE` and a SvelteKit app renders Svelte, and both were being handed the React kit
17
+ * right after `init` had detected the real UI library and said so on screen.
18
+ */
19
+ export declare function frameworkPackages(framework: Framework, uiLibrary?: UiLibrary): readonly string[];
20
+ export declare function buildPlan(input: PlanInput): Plan;
@@ -3,30 +3,33 @@
3
3
  * contents, produce an ordered list of steps — each marked apply / manual / already / skip. The
4
4
  * runner performs the `write` side-effects; this module decides *what* should happen.
5
5
  */
6
- import { Framework, UiLibrary, installCommand, installCommandParts, } from './detect.js';
7
- import { installFailureHint } from './install-hint.js';
8
- import { installRetries } from './install-retries.js';
9
- import { claudeAddCommand, mcpManual, mcpWindowsNote } from './mcp.js';
10
- import { NodePlatform } from './platform.js';
11
- import { mergeClientConfig, ClientMergeStatus, clientSnippet, clientSpec, McpClient, } from './mcp-clients.js';
12
- import { CLAUDE_COMMAND_PATH, CURSOR_COMMAND_PATH, SLASH_COMMAND_BODY, SLASH_COMMAND_SIGNATURE, } from './slash-command.js';
13
- import { mergeMarkedInstruction, reticleMdFile, cursorRuleFile, AgentRuleStatus, CLAUDE_MD_PATH, markedBlock, AGENTS_MD_PATH, RETICLE_MD_PATH, CURSOR_RULE_PATH, } from './agent-rules.js';
14
- import { cspStep, frameworkSteps } from './plan-framework.js';
6
+ import { Framework, UiLibrary, installCommand, installCommandParts, } from '../detect/detect.js';
7
+ import { installFailureHint } from '../diagnose/install-hint.js';
8
+ import { installRetries } from '../diagnose/install-retries.js';
9
+ import { claudeAddCommand, mcpManual } from '../register/mcp.js';
10
+ import { mergeClientConfig, ClientMergeStatus, clientSnippet, clientSpec, McpClient, } from '../register/mcp-clients.js';
11
+ import { CLAUDE_COMMAND_PATH, CURSOR_COMMAND_PATH, SLASH_COMMAND_BODY, SLASH_COMMAND_SIGNATURE, } from '../register/slash-command.js';
12
+ import { mergeMarkedInstruction, reticleMdFile, cursorRuleFile, AgentRuleStatus, CLAUDE_MD_PATH, markedBlock, AGENTS_MD_PATH, RETICLE_MD_PATH, CURSOR_RULE_PATH, } from '../project/agent-rules.js';
13
+ import { cspStep } from './plan-framework.js';
14
+ import { frameworkSteps } from './framework-adapter.js';
15
15
  import { FRAMEWORK_ADAPTERS, RETICLE_BROWSER_SDK, RETICLE_REACT_KIT } from './framework-adapter.js';
16
+ import { MCP_TARGET, StepStatus, } from './plan-types.js';
17
+ export { DEPS_TARGET, MCP_TARGET, StepStatus, } from './plan-types.js';
16
18
  import { join } from 'node:path';
17
- import { reticleConfigContent, unverifiedUiLibraryNote, WEBGL_CANVAS_LIMIT_NOTE, } from './snippets.js';
18
- import { configWithInstallSource } from './install-source-config.js';
19
- import { existingConfigProblem, projectIdOf, RETICLE_CONFIG_FILE } from './existing-config.js';
19
+ import { reticleConfigContent } from '../patch/snippets.js';
20
+ import { configWithInstallSource } from '../project/install-source-config.js';
21
+ import { containerisedStep, uiLibraryStep, webGlCanvasStep, windowsMcpNoteStep } from './notices.js';
22
+ import { existingConfigProblem, projectIdOf, RETICLE_CONFIG_FILE } from '../detect/existing-config.js';
20
23
  // Re-exported: it moved to the module that reads it, and every existing importer says `plan.js`.
21
24
  export { RETICLE_CONFIG_FILE };
22
25
  /**
23
26
  * Pin the SDK to the CLI's own version.
24
27
  *
25
- * `pnpm add -D @reticlehq/react` installed **2.2.1** in one project while npm and yarn took 2.3.0 in
26
- * the next — a stale registry metadata cache, invisible to the user and to us. A version-skewed SDK
27
- * talking to a newer daemon is the `-32000` failure path: the app connects, the protocol disagrees,
28
- * and nothing on either side names a version. Asking for the CLI's exact version makes the cache
29
- * irrelevant, and a skewed pair impossible to install by accident.
28
+ * `pnpm add -D @reticlehq/react` once installed an older release in one project while npm and yarn
29
+ * took the current one in the next — a stale registry metadata cache, invisible to everyone. A
30
+ * version-skewed SDK talking to a newer daemon is the `-32000` failure path: the app connects, the
31
+ * protocol disagrees, and nothing on either side names a version. Asking for the CLI's exact version
32
+ * makes the cache irrelevant, and a skewed pair impossible to install by accident.
30
33
  */
31
34
  function pinnedPackages(packages, version) {
32
35
  if (version === undefined || 0 === version.length)
@@ -59,23 +62,6 @@ export function frameworkPackages(framework, uiLibrary = UiLibrary.UNKNOWN) {
59
62
  const kit = wantsReactKit(uiLibrary) ? RETICLE_REACT_KIT : RETICLE_BROWSER_SDK;
60
63
  return FRAMEWORK_ADAPTERS[framework].packages(kit);
61
64
  }
62
- /** Exported so the init telemetry can tell an MCP-registration failure from a dependency install. */
63
- export const MCP_TARGET = 'global (claude user scope)';
64
- /** The step that runs the package manager — the other thing that commonly fails on a user's machine. */
65
- export const DEPS_TARGET = 'package.json';
66
- export const StepStatus = {
67
- APPLY: 'apply',
68
- MANUAL: 'manual',
69
- ALREADY: 'already',
70
- SKIP: 'skip',
71
- /**
72
- * Something the user should KNOW, not something they must DO. The UNVERIFIED lines are the case:
73
- * a Preact or SvelteKit app is wired and working, it just isn't covered by a gate. Reporting those
74
- * as `manual` made "steps left to do" a number that could never reach zero, and made a release gate
75
- * read two regressions that were not regressions.
76
- */
77
- NOTICE: 'notice',
78
- };
79
65
  /**
80
66
  * Where the agent-facing files go, which is not always where the app is.
81
67
  *
@@ -188,18 +174,6 @@ function mcpSteps(input) {
188
174
  steps.push(windowsNote);
189
175
  return steps;
190
176
  }
191
- const WINDOWS_MCP_TITLE = 'Windows MCP spawn';
192
- /** Windows only. The reported install never reached mcpManual because `claude mcp add` succeeded. */
193
- function windowsMcpNoteStep(input) {
194
- if (input.platform !== NodePlatform.WINDOWS)
195
- return null;
196
- return {
197
- title: WINDOWS_MCP_TITLE,
198
- target: MCP_TARGET,
199
- status: StepStatus.NOTICE,
200
- detail: mcpWindowsNote(),
201
- };
202
- }
203
177
  const SLASH_COMMAND_TITLE = 'The /reticle command';
204
178
  /**
205
179
  * Nothing to do for this command file: it already holds the CURRENT body, or it is not ours at all.
@@ -436,8 +410,8 @@ function agentRuleSteps(input) {
436
410
  *
437
411
  * pnpm's `minimumReleaseAge` refuses any release younger than the configured window — a deliberate
438
412
  * supply-chain policy, not a bug — with `ERR_PNPM_NO_MATURE_MATCHING_VERSION`. Unpinned it silently
439
- * resolves to an OLDER version instead, which is how an app ends up running a 2.2.1 SDK against a
440
- * 2.3.0 daemon: the connection succeeds, the protocol disagrees, and the failure surfaces as -32000
413
+ * resolves to an OLDER version instead, which is how an app ends up running a stale SDK against a
414
+ * newer daemon: the connection succeeds, the protocol disagrees, and the failure surfaces as -32000
441
415
  * with nothing naming a version. Pinning turns that into this loud failure, which is the better
442
416
  * trade — but only if the message says what to do about it.
443
417
  */
@@ -594,46 +568,6 @@ function reticleConfigSteps(input) {
594
568
  input.installSource);
595
569
  return [reticleConfigStep(input, content), ...agentRootConfigStep(input, content)];
596
570
  }
597
- /**
598
- * A step that says out loud when the app isn't React. SvelteKit already carries its own unverified
599
- * note, so it isn't doubled up here.
600
- */
601
- function uiLibraryStep(input) {
602
- const lib = input.detection.uiLibrary;
603
- // A framework whose own recipe already says it is unverified must not be argued with by a second,
604
- // more generic notice. Asked of the registry rather than of a remembered `SVELTEKIT || NUXT` pair:
605
- // the pair was the answer, not the question, and a third framework joining it was a silent edit.
606
- if (lib === UiLibrary.REACT)
607
- return [];
608
- if (FRAMEWORK_ADAPTERS[input.detection.framework].carriesOwnUnverifiedNote)
609
- return [];
610
- if (lib === UiLibrary.UNKNOWN)
611
- return [];
612
- return [
613
- {
614
- title: `${lib} is UNVERIFIED`,
615
- target: 'package.json',
616
- status: StepStatus.NOTICE,
617
- detail: unverifiedUiLibraryNote(lib),
618
- },
619
- ];
620
- }
621
- /**
622
- * Say the WebGL gap out loud at install time. Without it, init looks fully green on an R3F app
623
- * while the canvas — often the product — stays a blank rectangle to every look and act tool (#880).
624
- */
625
- function webGlCanvasStep(input) {
626
- if (true !== input.detection.webGlSubtree)
627
- return [];
628
- return [
629
- {
630
- title: 'WebGL canvas is not observable',
631
- target: 'package.json',
632
- status: StepStatus.NOTICE,
633
- detail: WEBGL_CANVAS_LIMIT_NOTE,
634
- },
635
- ];
636
- }
637
571
  export function buildPlan(input) {
638
572
  const steps = [
639
573
  ...cspStep(input),
@@ -646,5 +580,10 @@ export function buildPlan(input) {
646
580
  ...reticleConfigSteps(input),
647
581
  ];
648
582
  steps.push(...frameworkSteps(input));
583
+ // LAST, and a notice rather than an action: it is a statement about this machine's shape, and it
584
+ // only matters once every file above has been written. See containerised-dev-server.ts.
585
+ const container = containerisedStep(input);
586
+ if (container !== null)
587
+ steps.push(container);
649
588
  return { framework: input.detection.framework, uiLibrary: input.detection.uiLibrary, steps };
650
589
  }
@@ -82,7 +82,7 @@ export declare const CLI = "npx @reticlehq/server";
82
82
  *
83
83
  * Exported because slash-command.ts renders the same rule; there must not be two versions of it.
84
84
  */
85
- export declare const DEV_SERVER_POLICY = "**A dev server already running when `reticle init` ran does not have Reticle in its bundle.** It read the build config at boot; `init` edited it afterwards. It serves the old bundle and no session appears. In order:\n\n1. **A dev server was already running?** Restart it, then hard-reload the tab. \"Something is listening\" does not mean the right bundle is served.\n2. **Nothing was running?** Start it in the BACKGROUND and say so in one line. `reticle_sessions` gives you this project's own dev command in `next_action`; use that, never compose one. Started after `init`, it needs no restart.\n\nStopping to ask is how a verification turn ends with nothing verified.\n\nFour guards, none optional:\n\n1. **Never run two at once.** One dev server on the app's port. Restarting a stale one means stopping it first, not starting a second alongside it.\n2. **Never guess the command.** It comes from `package.json` scripts. No recognisable dev script means say so and stop, not invent one.\n3. **Never kill anything you did not start**, and never a daemon or a port holder. The one exception is the restart above, and say in one line that you did it.\n4. **The permission prompt belongs to your host.** Never bypass, suppress or auto-approve it, and take a refusal as the answer.";
85
+ export declare const DEV_SERVER_POLICY = "**A dev server already running when `reticle init` ran does not have Reticle in its bundle.** It read the build config at boot; `init` edited it afterwards. It serves the old bundle and no session appears. In order:\n\n1. **A dev server was already running?** Restart it, then hard-reload the tab. \"Something is listening\" does not mean the right bundle is served.\n2. **Nothing was running?** Start it in the BACKGROUND and say so in one line. `reticle_session { action: \"list\" }` gives you this project's own dev command in `next_action`; use that, never compose one. Started after `init`, it needs no restart.\n\nStopping to ask is how a verification turn ends with nothing verified.\n\nFour guards, none optional:\n\n1. **Never run two at once.** One dev server on the app's port. Restarting a stale one means stopping it first, not starting a second alongside it.\n2. **Never guess the command.** It comes from `package.json` scripts. No recognisable dev script means say so and stop, not invent one.\n3. **Never kill anything you did not start**, and never a daemon or a port holder. The one exception is the restart above, and say in one line that you did it.\n4. **The permission prompt belongs to your host.** Never bypass, suppress or auto-approve it, and take a refusal as the answer.";
86
86
  /**
87
87
  * The operative rules, carried by every file that loads on every turn.
88
88
  *
@@ -90,7 +90,7 @@ export declare const DEV_SERVER_POLICY = "**A dev server already running when `r
90
90
  * NOT to, how, and the guards against calling something proven when it is not. Everything an agent
91
91
  * needs only at the moment it hits a specific situation lives in RETICLE.md, named at the end.
92
92
  */
93
- export declare const RULE_BODY = "## Verifying with Reticle\n\nThis app is instrumented by **Reticle**, an in-app verification layer exposed as `reticle_*` MCP tools and the `npx @reticlehq/server` CLI (always through npx: Reticle's server is not installed into this project). Verifying is part of \"done\", not an optional extra.\n\n**Verify when you have changed something a user can see or do.** A component, a form, a route, a request, a piece of state that reaches the screen. Do it BEFORE telling the user it is complete. Reading the diff proves nothing and unit tests do not run the app.\n\n**Do not reach for Reticle when the change cannot show up in the running app.** It costs tool calls and the user's patience, and a verdict over an unrelated flow proves nothing about what you changed. Skip it for: documentation, comments, tests, build config, CI, dependency bumps with no user-facing effect, backend or CLI work with no UI surface, and any change to a project that is not a running web app. Say in one line that you skipped verification and why, rather than silently not doing it.\n\n**How to verify:**\n\n- Drive the flow with `reticle_act_and_wait({ ref, action, until })`. It names the consequence you expect BEFORE the action, which is the difference between a check and a rationalisation.\n- Batch a multi-step journey (a login, a form) into one `reticle_act_sequence` rather than one round trip per field.\n- Read the surrounding evidence with `reticle_snapshot`, `reticle_state`, `reticle_network`, `reticle_console`.\n- **Only `reticle_act_and_wait` and `reticle_assert` produce a verdict.** `reticle_act` and everything else move or read the app and prove nothing, so a session ending without one of those two has no result however many tools it used.\n- Covered flows: `npx @reticlehq/server gate` reports which recorded flows the changed files affect and whether they still pass.\n\n**Setting Reticle up, or just restarted? You are mid-sequence \u2014 do not stop until a verdict exists.**\nThe whole of it is: instrument the app \u2192 get a dev server running \u2192 open the app in a browser \u2192\ndrive one flow \u2192 report the verdict. Every step is yours to do, and none of them needs the user.\nThe ONE legitimate pause is a client restart, because a client reads its server list at startup;\nwhen you come back, you are not finished, you are on the next step \u2014 resume it without being asked.\nStopping anywhere else leaves an app that looks installed and can verify nothing, which is the\nsingle commonest way this goes wrong. `/reticle` carries the full recovery ladder when a step\ndoes not work; use it rather than guessing, and never report the install as finished without a\nverdict to point at.\n\n**Nothing connected? Get the app running.**\n\n**A dev server already running when `reticle init` ran does not have Reticle in its bundle.** It read the build config at boot; `init` edited it afterwards. It serves the old bundle and no session appears. In order:\n\n1. **A dev server was already running?** Restart it, then hard-reload the tab. \"Something is listening\" does not mean the right bundle is served.\n2. **Nothing was running?** Start it in the BACKGROUND and say so in one line. `reticle_sessions` gives you this project's own dev command in `next_action`; use that, never compose one. Started after `init`, it needs no restart.\n\nStopping to ask is how a verification turn ends with nothing verified.\n\nFour guards, none optional:\n\n1. **Never run two at once.** One dev server on the app's port. Restarting a stale one means stopping it first, not starting a second alongside it.\n2. **Never guess the command.** It comes from `package.json` scripts. No recognisable dev script means say so and stop, not invent one.\n3. **Never kill anything you did not start**, and never a daemon or a port holder. The one exception is the restart above, and say in one line that you did it.\n4. **The permission prompt belongs to your host.** Never bypass, suppress or auto-approve it, and take a refusal as the answer.\n\nA dev server that is already running does not pick up an edited build config or a newly created plugin file \u2014 restart it and hard-reload the tab. And if a server IS listening and still nothing connects, the cause is the SDK not loading in the page, not a missing dev server; do not tell the user to start one they are already running.\n\n**Finish `src/reticle-dev.ts` before you claim setup is done.** `init` writes it and cannot always fill it in: a store that needs an argument only reading the code supplies (Jotai atoms, an XState actor, a TanStack `queryClient`) is left as a commented `registerStore` line. A file that registers nothing looks exactly like a finished one, and `reticle_state` then returns empty forever \u2014 which is indistinguishable from an app that has nothing to report, so it reads as success. Uncomment the line, complete it, and prove it by driving one flow and seeing your keys come back. If `init` told you to restart your client, this is the job waiting for you on the other side of that restart.\n\n**Verify each feature as you finish it, not all of them at the end.** Asked for four, build one, drive it, get a verdict, then start the second. A red verdict after four builds has four suspects; after one it has none.\n\n**Capture what a change is FOR while you are building it, not afterwards.** `reticle_intent` records the business outcome a change is meant to produce, and the only moment anybody knows it is while the change is being made. Pass `intent` when you save a flow, so the saved flow carries the reason it exists. A flow without one replays for months and then reports \"step 3 failed\" instead of what stopped being true for a user.\n\n**Honesty, which is the whole point:**\n\n- **`verified: \"unknown\"` is not a pass.** It means Reticle drove the app and could not tell what happened; `verifiedReason` says which clause decided that. Report it as unknown, never as working.\n- **`verified: \"no-fault\"` is not a pass either.** It means nothing was DECLARED to prove: the page settled and no channel complained, but you asserted nothing, so there is no verification. You get it whenever `until` is omitted. Name a consequence the action changes \u2014 a signal, a request, a route, or store state \u2014 and call again.\n- **Never weaken a check to make it green.** Downgrading, skipping or deleting an assertion is a finding, not a fix.\n- **If Reticle cannot run** (no daemon, or this is not a running web app), say so. Do not skip verification silently.\n- **Setup is not finished until one real flow has been driven and produced a verdict.** `init` exiting 0, the tools appearing, and a session being listed are all things that happen before anything has been verified.\n\n**The `/reticle` skill runs this whole loop for you** \u2014 detect, connect, drive one flow, report. If your client does not have it, install it once: `/plugin marketplace add reticlehq/reticle` then `/plugin install reticle@reticlehq` in Claude Code, or `npx skills add reticlehq/reticle` anywhere the skills CLI works.\n\n**A tool you need is missing? It exists.** The default surface advertises a subset; reach any other by name with `reticle_run { tool, args }`, and list them with `reticle_tools`. Two worth knowing: `reticle_context` returns this run's own memory \u2014 what is established, what is proven, what is still unverified \u2014 which is what you want after a compaction or when picking up work you did not start; `reticle_intent` records what a change was MEANT to do, while somebody still knows.\n\n**Report Reticle's own defects with `reticle_feedback` the moment you notice**, then carry on with your task. You are the user Reticle is built for and the only one who can say what it cost you, and that knowledge is gone when your context is.\n\n\uD83D\uDCC4 **The rest is in [RETICLE.md](./RETICLE.md): what to do when the tools are missing, when a result carries `version_skew` or `update_available`, when `reticle_state` comes back empty, and how to write a feedback report that can be acted on. Read it when you hit one of those, not before.**";
93
+ export declare const RULE_BODY = "## Verifying with Reticle\n\nThis app is instrumented by **Reticle**, an in-app verification layer exposed as `reticle_*` MCP tools and the `npx @reticlehq/server` CLI (always through npx: Reticle's server is not installed into this project). Verifying is part of \"done\", not an optional extra.\n\n**Verify when you have changed something a user can see or do.** A component, a form, a route, a request, a piece of state that reaches the screen. Do it BEFORE telling the user it is complete. Reading the diff proves nothing and unit tests do not run the app.\n\n**Do not reach for Reticle when the change cannot show up in the running app.** It costs tool calls and the user's patience, and a verdict over an unrelated flow proves nothing about what you changed. Skip it for: documentation, comments, tests, build config, CI, dependency bumps with no user-facing effect, backend or CLI work with no UI surface, and any change to a project that is not a running web app. Say in one line that you skipped verification and why, rather than silently not doing it.\n\n**How to verify:**\n\n- Drive the flow with `reticle_act_and_wait({ ref, action, until })`. It names the consequence you expect BEFORE the action, which is the difference between a check and a rationalisation.\n- Batch a multi-step journey (a login, a form) into one `reticle_act { steps: [...] }` rather than one round trip per field.\n- Read the surrounding evidence with `reticle_look { action: \"page\" | \"state\" }` and `reticle_observe { action: \"network\" | \"console\" }`.\n- **Only `reticle_act_and_wait` and `reticle_assert` produce a verdict.** `reticle_act` and everything else move or read the app and prove nothing, so a session ending without one of those two has no result however many tools it used.\n- Covered flows: `npx @reticlehq/server gate` reports which recorded flows the changed files affect and whether they still pass.\n\n**Setting Reticle up? You are mid-sequence \u2014 do not stop until a verdict exists.** The whole of it\nis: instrument the app \u2192 get a dev server running \u2192 open the app in a browser \u2192 drive one flow \u2192\nreport the verdict. Every step is yours to do, and none of them needs the user. Stopping short leaves an app that\nlooks installed and can verify nothing, which is the commonest way this goes wrong. `/reticle`\ncarries the recovery ladder; never report the install as finished without a verdict to point at.\n\n**Nothing connected? Get the app running.**\n\n**A dev server already running when `reticle init` ran does not have Reticle in its bundle.** It read the build config at boot; `init` edited it afterwards. It serves the old bundle and no session appears. In order:\n\n1. **A dev server was already running?** Restart it, then hard-reload the tab. \"Something is listening\" does not mean the right bundle is served.\n2. **Nothing was running?** Start it in the BACKGROUND and say so in one line. `reticle_session { action: \"list\" }` gives you this project's own dev command in `next_action`; use that, never compose one. Started after `init`, it needs no restart.\n\nStopping to ask is how a verification turn ends with nothing verified.\n\nFour guards, none optional:\n\n1. **Never run two at once.** One dev server on the app's port. Restarting a stale one means stopping it first, not starting a second alongside it.\n2. **Never guess the command.** It comes from `package.json` scripts. No recognisable dev script means say so and stop, not invent one.\n3. **Never kill anything you did not start**, and never a daemon or a port holder. The one exception is the restart above, and say in one line that you did it.\n4. **The permission prompt belongs to your host.** Never bypass, suppress or auto-approve it, and take a refusal as the answer.\n\nA dev server that is already running does not pick up an edited build config or a newly created plugin file \u2014 restart it and hard-reload the tab. And if a server IS listening and still nothing connects, the cause is the SDK not loading in the page, not a missing dev server; do not tell the user to start one they are already running.\n\n**Finish `src/reticle-dev.ts` before you claim setup is done.** `init` writes it and cannot always fill it in: a store that needs an argument only reading the code supplies (Jotai atoms, an XState actor, a TanStack `queryClient`) is left as a commented `registerStore` line. A file that registers nothing looks exactly like a finished one, and `reticle_look { action: \"state\" }` then returns empty forever \u2014 which is indistinguishable from an app that has nothing to report, so it reads as success. Uncomment the line, complete it, and prove it by driving one flow and seeing your keys come back. If `init` told you to restart your client, this is the job waiting for you on the other side of that restart.\n\n**Verify each feature as you finish it, not all of them at the end.** Asked for four, build one, drive it, get a verdict, then start the second. A red verdict after four builds has four suspects; after one it has none.\n\n**Capture what a change is FOR while you are building it, not afterwards.** The business outcome a change is meant to produce is known only while the change is being made. Pass `intent` when a flow is saved, so the saved flow carries the reason it exists. A flow without one replays for months and then reports \"step 3 failed\" instead of what stopped being true for a user.\n\n**Honesty, which is the whole point:**\n\n- **`verified: \"unknown\"` is not a pass.** It means Reticle drove the app and could not tell what happened; `verifiedReason` says which clause decided that. Report it as unknown, never as working.\n- **`verified: \"no-fault\"` is not a pass either.** It means nothing was DECLARED to prove: the page settled and no channel complained, but you asserted nothing, so there is no verification. You get it whenever `until` is omitted. Name a consequence the action changes \u2014 a signal, a request, a route, or store state \u2014 and call again.\n- **Never weaken a check to make it green.** Downgrading, skipping or deleting an assertion is a finding, not a fix.\n- **If Reticle cannot run** (no daemon, or this is not a running web app), say so. Do not skip verification silently.\n- **Setup is not finished until one real flow has been driven and produced a verdict.** `init` exiting 0, the tools appearing, and a session being listed are all things that happen before anything has been verified.\n\n**The `/reticle` skill runs this whole loop for you** \u2014 detect, connect, drive one flow, report. If your client does not have it, install it once: `/plugin marketplace add reticlehq/reticle` then `/plugin install reticle@reticlehq` in Claude Code, or `npx skills add reticlehq/reticle` anywhere the skills CLI works.\n\n**A tool you need is missing?** Call `reticle_tools` before assuming it: this surface merges several families behind an `action`, so what looks absent is usually one argument away. It is the verify loop and nothing else on purpose, and a daemon started with `RETICLE_ADVERTISE_ALL_TOOLS=1` advertises the wider set \u2014 it reads that at startup, so it takes effect on the next one.\n\n**Report Reticle's own defects with `reticle_session { action: \"feedback\" }` the moment you notice**, then carry on with your task. You are the user Reticle is built for and the only one who can say what it cost you, and that knowledge is gone when your context is.\n\n\uD83D\uDCC4 **The rest is in [RETICLE.md](./RETICLE.md): what to do when the tools are missing, when a result carries `version_skew` or `update_available`, when `reticle_look { action: \"state\" }` comes back empty, and how to write a feedback report that can be acted on. Read it when you hit one of those, not before.**";
94
94
  /** The full-rules file, written verbatim (no markers: `init` owns this file entirely). */
95
95
  export declare function reticleMdFile(): string;
96
96
  export declare const AgentRuleStatus: {