@nuucognition/flint-cli 0.6.0-dev.21 → 0.6.0-dev.23

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.
package/README.md CHANGED
@@ -152,24 +152,62 @@ flint open # Open current flint
152
152
  flint open my-project # Open by name from registry
153
153
  ```
154
154
 
155
- **Dev-only:** use the `flint-dev` binary or a source build with no baked `BUILD_MODE`.
155
+ ### `flint cd`
156
+
157
+ Change the current shell directory to a registered Flint.
156
158
 
157
- ### Development builds and atomic live releases
159
+ ```bash
160
+ flint cd "NUU Flint"
161
+ ```
158
162
 
159
- Flint has separate development and live runtime channels:
163
+ A child process cannot change the directory of its parent shell. Install the
164
+ managed shell integration to add the required `flint` shell function:
165
+
166
+ ```bash
167
+ flint setup shell-integration --apply
168
+ ```
160
169
 
161
- - `ndv use flint dev` activates `bin/flint-dev.js`. It consumes the checkout's
162
- `apps/flint-cli/dist`, so `ndv build flint dev` is visible on the next
163
- invocation. Orbh children spawned from this channel remain on the caller's
164
- checkout.
165
- - `bin/flint.js` is the canonical live launcher used by Orbh-managed release
166
- flows. When `.flint-live-build/current` is complete, it consumes that
167
- atomically selected release rather than an in-place checkout build.
168
- - `bin/flint-prod.js` consumes the `dist` shipped inside its installed package.
170
+ The same integration adds fuzzy Flint-name completion for `flint open` and
171
+ `flint cd`. Press Tab in the first argument. The picker starts with the text in
172
+ the current argument, so both of these forms work:
173
+
174
+ ```bash
175
+ flint open ""
176
+ flint cd "nuu"
177
+ ```
178
+
179
+ The completion matrix is macOS with Zsh and Omarchy with Bash. `fzf` supplies
180
+ the fuzzy picker. If `fzf` is not available, the integration uses native prefix
181
+ completion. Fish keeps the directory wrapper and terminal-title integration,
182
+ but it does not have Flint-name completion in this release.
183
+
184
+ **Dev-only:** use the `flint-dev` binary or a source build with no baked `BUILD_MODE`.
169
185
 
170
- The channels are intentionally distinct: NDV owns checkout development, while
171
- the declared `[live-build]` command stages and smoke-tests long-running Orbh
172
- releases before cutover.
186
+ ### Channels: dev, prod, npm
187
+
188
+ Flint runs from the checkout in one of two **profiles**, or from npm
189
+ (protocol: NUU Infrastructure `(Notepad) 007 CLI Build-and-Use Protocol`):
190
+
191
+ - **dev** — `ndv use flint dev` runs `build:dev` (no baked runtime mode:
192
+ dev-only commands, `~/.nuucognition/flint-dev/`) and links
193
+ `bin/flint-dev.js`. Orbh children spawned from this channel remain on the
194
+ caller's checkout.
195
+ - **prod** — `ndv use flint prod` runs `build` (bakes `production`: real
196
+ auth, `~/.nuucognition/flint/`) on the same checkout and links
197
+ `bin/flint-prod.js`.
198
+ - **npm** — the installed package's `bin/flint-prod.js` imports its own
199
+ `dist`. No checkout, so no drift check.
200
+
201
+ Both profiles import `apps/flint-cli/dist/index.js` in-process. Every build
202
+ writes `dist/.build-stamp.json` (`sha`, `dirty`, `builtAt`, `mode`); the
203
+ launcher compares the stamp to HEAD and prints one stderr line when the bundle
204
+ is stale. It never blocks and never builds — run `ndv build flint [dev|prod]`.
205
+ Switching profiles rebuilds, because the profile is baked into the bundle.
206
+
207
+ `flint where` prints channel, launcher, artifact, stamp, HEAD, and drift.
208
+ `FLINT_CLI_FORCE_SOURCE=1` runs the TypeScript source through tsx instead of
209
+ `dist` (it says so on stderr). `NUU_BUILD_STAMP_QUIET=1` silences the
210
+ stale-build line.
173
211
 
174
212
  **Behavior:**
175
213
  - Opens the flint in all apps configured in the current profile config
package/bin/flint-dev.js CHANGED
@@ -6,10 +6,7 @@ import { launchFlint } from './launch-flint.js';
6
6
 
7
7
  // A dev activation is an explicit choice to keep the spawned Orbh process tree
8
8
  // on the caller's checkout instead of silently switching detached auxiliaries
9
- // back to the machine-canonical live launcher.
9
+ // to the machine-canonical launcher.
10
10
  process.env.ORBH_AUX_CODE_SOURCE = 'caller';
11
11
 
12
- await launchFlint({
13
- launcherPath: fileURLToPath(import.meta.url),
14
- preferLiveBuild: false,
15
- });
12
+ await launchFlint({ launcherPath: fileURLToPath(import.meta.url) });
package/bin/flint-prod.js CHANGED
@@ -4,39 +4,68 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
4
4
  import { dirname, join } from 'node:path';
5
5
  import { shouldEnableOpenTuiFfi } from '../dist/open-tui-invocation.js';
6
6
 
7
- const openTuiRequested = shouldEnableOpenTuiFfi({
8
- cli: 'flint',
9
- args: process.argv.slice(2),
10
- envRenderer: process.env.ORBH_TUI_RENDERER,
11
- envNoChrome: process.env.ORBH_NO_CHROME,
12
- stdinTty: Boolean(process.stdin.isTTY),
13
- stdoutTty: Boolean(process.stdout.isTTY),
14
- });
15
- const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number);
16
- const ffiSupported = nodeMajor > 26 || (nodeMajor === 26 && nodeMinor >= 1);
17
- const ffiFlag = '--experimental-ffi';
18
- if (openTuiRequested && ffiSupported
19
- && !process.execArgv.includes(ffiFlag)
20
- && !process.env.NODE_OPTIONS?.split(/\s+/).includes(ffiFlag)
21
- && process.execve) {
22
- const options = new Set(process.env.NODE_OPTIONS?.split(/\s+/).filter(Boolean) ?? []);
23
- for (const option of [ffiFlag, '--disable-warning=ExperimentalWarning', '--disable-warning=DEP0205']) options.add(option);
24
- process.execve(process.execPath, process.argv, {
25
- ...process.env,
26
- NODE_OPTIONS: [...options].join(' '),
27
- ORBH_TUI_FFI_REEXEC: '1',
7
+ const args = process.argv.slice(2);
8
+ const completionRequested = args[0] === '__complete';
9
+
10
+ if (!completionRequested) {
11
+ const openTuiRequested = shouldEnableOpenTuiFfi({
12
+ cli: 'flint',
13
+ args,
14
+ envRenderer: process.env.ORBH_TUI_RENDERER,
15
+ stdinTty: Boolean(process.stdin.isTTY),
16
+ stdoutTty: Boolean(process.stdout.isTTY),
28
17
  });
18
+ const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number);
19
+ const ffiSupported = nodeMajor > 26 || (nodeMajor === 26 && nodeMinor >= 1);
20
+ const ffiFlag = '--experimental-ffi';
21
+ if (openTuiRequested && ffiSupported
22
+ && !process.execArgv.includes(ffiFlag)
23
+ && !process.env.NODE_OPTIONS?.split(/\s+/).includes(ffiFlag)
24
+ && process.execve) {
25
+ const options = new Set(process.env.NODE_OPTIONS?.split(/\s+/).filter(Boolean) ?? []);
26
+ for (const option of [ffiFlag, '--disable-warning=ExperimentalWarning', '--disable-warning=DEP0205']) options.add(option);
27
+ process.execve(process.execPath, process.argv, {
28
+ ...process.env,
29
+ NODE_OPTIONS: [...options].join(' '),
30
+ ORBH_TUI_FFI_REEXEC: '1',
31
+ });
32
+ }
29
33
  }
30
34
 
31
35
  const __dirname = dirname(fileURLToPath(import.meta.url));
32
- const entrypoint = join(__dirname, '..', 'dist', 'index.js');
36
+ const entrypoint = join(
37
+ __dirname,
38
+ '..',
39
+ 'dist',
40
+ completionRequested ? 'completion.js' : 'index.js',
41
+ );
42
+
43
+ // `ndv use flint prod` links this launcher to the checkout's production-profile
44
+ // build. In a checkout the stamp check applies exactly as for flint-dev.js; in
45
+ // an installed npm package cli-core is absent and the check is skipped.
46
+ const { warnIfBuildStale } = await import('@nuucognition/cli-core/launch').catch(() => ({ warnIfBuildStale() {} }));
47
+ warnIfBuildStale({ cli: 'flint', distEntry: entrypoint, rebuildHint: 'Run: ndv build flint prod' });
33
48
 
34
- // Default to production React — see bin/flint.js. The bundled react-reconciler
49
+ // Default to production React — see bin/launch-flint.js. The bundled react-reconciler
35
50
  // is baked to production at build time, but `react` stays external; with
36
51
  // NODE_ENV unset it loads its development build, whose jsx runtime calls
37
52
  // dev-only dispatcher methods the production reconciler never installs
38
53
  // ("dispatcher.getOwner is not a function" on first TUI render).
39
- process.env.NODE_ENV ||= 'production';
54
+ // The marker lets child-spawn boundaries strip the launcher-owned default —
55
+ // see bin/launch-flint.js.
56
+ if (!process.env.NODE_ENV) {
57
+ process.env.NODE_ENV = 'production';
58
+ process.env.ORBH_DEFAULTED_NODE_ENV = '1';
59
+ }
60
+
61
+ // V8 compile cache for the selected entrypoint. It is most important for the
62
+ // main 15 MB bundle. The small completion bundle also uses it without harm.
63
+ try {
64
+ const { enableCompileCache } = await import('node:module');
65
+ enableCompileCache?.();
66
+ } catch {
67
+ /* uncached */
68
+ }
40
69
  process.env.FLINT_CLI_LAUNCHER ??= fileURLToPath(import.meta.url);
41
70
  process.env.FLINT_CLI_ENTRYPOINT ??= entrypoint;
42
71
  await import(pathToFileURL(entrypoint).href);
@@ -3,64 +3,88 @@ import { existsSync } from 'node:fs';
3
3
  import { dirname, join } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
 
6
- import { resolveLiveBuildPackageRoot } from './live-build-path.js';
7
-
8
6
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
- const sourcePackageRoot = join(__dirname, '..');
7
+ const packageRoot = join(__dirname, '..');
8
+
9
+ // The stamp check lives in cli-core (node builtins only). In a checkout it is
10
+ // always present — ndv builds cli-core before any tool; anywhere else the
11
+ // import fails and the check is simply skipped.
12
+ const { warnIfBuildStale, noteSourceRun } = await import('@nuucognition/cli-core/launch')
13
+ .catch(() => ({ warnIfBuildStale() {}, noteSourceRun() {} }));
10
14
 
11
15
  /**
12
- * Run Flint through an explicit runtime channel.
16
+ * Run Flint from this checkout's dev build — the `dev` channel.
13
17
  *
14
- * NDV dev launchers consume the checkout build. Canonical live launchers prefer
15
- * the atomically selected release. Keeping this decision in the entrypoint
16
- * avoids an inherited environment variable silently changing channels.
18
+ * One artifact: `dist-dev/index.js`, built by `ndv use flint dev` / `ndv build
19
+ * flint`. `dist/` stays the prod channel's artifact (built and cached by
20
+ * turbo), so a closure build can never overwrite the bundle this launcher
21
+ * runs. The launcher checks the build stamp against HEAD and warns on drift;
22
+ * it never blocks and never builds. `FLINT_CLI_FORCE_SOURCE=1` is the escape
23
+ * hatch that runs the TypeScript source through tsx instead.
17
24
  */
18
- export async function launchFlint({ launcherPath, preferLiveBuild }) {
19
- const runtimePackageRoot = resolveLiveBuildPackageRoot(sourcePackageRoot, { preferLiveBuild });
20
- const openTuiInvocationEntry = join(runtimePackageRoot, 'dist', 'open-tui-invocation.js');
21
- const { shouldEnableOpenTuiFfi } = await import(openTuiInvocationEntry);
25
+ export async function launchFlint({ launcherPath }) {
26
+ const args = process.argv.slice(2);
27
+ const completionRequested = args[0] === '__complete';
28
+ const forceSource =
29
+ process.env.FLINT_CLI_FORCE_SOURCE === '1' ||
30
+ process.env.FLINT_CLI_FORCE_SOURCE === 'true';
31
+ const entryName = completionRequested ? 'completion' : 'index';
32
+ const srcEntry = join(packageRoot, 'src', `${entryName}.ts`);
33
+ const distEntry = join(packageRoot, 'dist-dev', `${entryName}.js`);
22
34
 
23
- const openTuiRequested = shouldEnableOpenTuiFfi({
24
- cli: 'flint',
25
- args: process.argv.slice(2),
26
- envRenderer: process.env.ORBH_TUI_RENDERER,
27
- envNoChrome: process.env.ORBH_NO_CHROME,
28
- stdinTty: Boolean(process.stdin.isTTY),
29
- stdoutTty: Boolean(process.stdout.isTTY),
30
- });
31
- const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number);
32
- const ffiSupported = nodeMajor > 26 || (nodeMajor === 26 && nodeMinor >= 1);
33
- const ffiFlag = '--experimental-ffi';
34
- if (openTuiRequested && ffiSupported
35
- && !process.execArgv.includes(ffiFlag)
36
- && !process.env.NODE_OPTIONS?.split(/\s+/).includes(ffiFlag)
37
- && process.execve) {
38
- const options = new Set(process.env.NODE_OPTIONS?.split(/\s+/).filter(Boolean) ?? []);
39
- for (const option of [ffiFlag, '--disable-warning=ExperimentalWarning', '--disable-warning=DEP0205']) options.add(option);
40
- process.execve(process.execPath, process.argv, {
41
- ...process.env,
42
- NODE_OPTIONS: [...options].join(' '),
43
- ORBH_TUI_FFI_REEXEC: '1',
35
+ // Completion does not need the OpenTUI probe. Keep that dependency outside
36
+ // the latency-sensitive route.
37
+ if (!completionRequested) {
38
+ // The probe ships inside the bundle. Prefer the dev channel's bundle,
39
+ // fall back to the prod dist, and skip the probe when neither is built.
40
+ const openTuiInvocationEntry = ['dist-dev', 'dist']
41
+ .map((dir) => join(packageRoot, dir, 'open-tui-invocation.js'))
42
+ .find((path) => existsSync(path));
43
+ const { shouldEnableOpenTuiFfi } = openTuiInvocationEntry
44
+ ? await import(openTuiInvocationEntry)
45
+ : { shouldEnableOpenTuiFfi: () => false };
46
+
47
+ const openTuiRequested = shouldEnableOpenTuiFfi({
48
+ cli: 'flint',
49
+ args,
50
+ envRenderer: process.env.ORBH_TUI_RENDERER,
51
+ stdinTty: Boolean(process.stdin.isTTY),
52
+ stdoutTty: Boolean(process.stdout.isTTY),
44
53
  });
54
+ const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number);
55
+ const ffiSupported = nodeMajor > 26 || (nodeMajor === 26 && nodeMinor >= 1);
56
+ const ffiFlag = '--experimental-ffi';
57
+ if (openTuiRequested && ffiSupported
58
+ && !process.execArgv.includes(ffiFlag)
59
+ && !process.env.NODE_OPTIONS?.split(/\s+/).includes(ffiFlag)
60
+ && process.execve) {
61
+ const options = new Set(process.env.NODE_OPTIONS?.split(/\s+/).filter(Boolean) ?? []);
62
+ for (const option of [ffiFlag, '--disable-warning=ExperimentalWarning', '--disable-warning=DEP0205']) options.add(option);
63
+ process.execve(process.execPath, process.argv, {
64
+ ...process.env,
65
+ NODE_OPTIONS: [...options].join(' '),
66
+ ORBH_TUI_FFI_REEXEC: '1',
67
+ });
68
+ }
45
69
  }
46
70
 
47
- const srcEntry = join(sourcePackageRoot, 'src', 'index.ts');
48
- const distEntry = join(runtimePackageRoot, 'dist', 'index.js');
49
-
50
71
  // Default to production React/ink. Unset NODE_ENV loads react-reconciler's
51
72
  // development build, whose per-render performance.measure() calls accumulate
52
73
  // forever in Node's perf buffer — a ~1GB/hour leak in long-lived interactive
53
74
  // views like `orbh list`. Explicit NODE_ENV=development still wins.
54
- process.env.NODE_ENV ||= 'production';
55
-
56
- // Performance: prefer the built dist and run it IN-PROCESS (one node process,
57
- // no tsx, no recompile-on-every-invocation). Set FLINT_CLI_FORCE_SOURCE=1 to
58
- // fall back to the checkout TypeScript source via tsx.
59
- const forceSource =
60
- process.env.FLINT_CLI_FORCE_SOURCE === '1' ||
61
- process.env.FLINT_CLI_FORCE_SOURCE === 'true';
75
+ //
76
+ // The marker records that the default is the launcher's own, not the
77
+ // caller's: child-spawn boundaries (buildHarnessSpawnEnv, the job spawn)
78
+ // strip NODE_ENV again when the marker is present, so agent harnesses and
79
+ // their build tools (pnpm skips devDependencies under production) see the
80
+ // environment the launcher itself received.
81
+ if (!process.env.NODE_ENV) {
82
+ process.env.NODE_ENV = 'production';
83
+ process.env.ORBH_DEFAULTED_NODE_ENV = '1';
84
+ }
62
85
 
63
86
  if (!forceSource && existsSync(distEntry)) {
87
+ warnIfBuildStale({ cli: 'flint', distEntry, rebuildHint: 'Run: ndv build flint' });
64
88
  process.env.FLINT_CLI_LAUNCHER = launcherPath;
65
89
  process.env.FLINT_CLI_ENTRYPOINT = distEntry;
66
90
  // The dist entry parses process.argv and runs the CLI on import. Awaiting
@@ -69,7 +93,9 @@ export async function launchFlint({ launcherPath, preferLiveBuild }) {
69
93
  return;
70
94
  }
71
95
 
72
- const tsxPath = join(sourcePackageRoot, 'node_modules', '.bin', 'tsx');
96
+ noteSourceRun('flint', forceSource ? 'forced' : 'no-dist', 'Run: ndv build flint');
97
+
98
+ const tsxPath = join(packageRoot, 'node_modules', '.bin', 'tsx');
73
99
 
74
100
  // tsx still calls deprecated module.register(); Node 26 turned DEP0205 into a
75
101
  // runtime warning. Disable it just for the source subprocess.
@@ -79,7 +105,7 @@ export async function launchFlint({ launcherPath, preferLiveBuild }) {
79
105
  ? existingNodeOptions
80
106
  : (existingNodeOptions ? `${existingNodeOptions} ${suppressFlag}` : suppressFlag);
81
107
 
82
- const result = spawnSync(tsxPath, [srcEntry, ...process.argv.slice(2)], {
108
+ const result = spawnSync(tsxPath, [srcEntry, ...args], {
83
109
  stdio: 'inherit',
84
110
  env: {
85
111
  ...process.env,
@@ -0,0 +1,7 @@
1
+ {
2
+ "sha": "ef931f0a52da06382a671173f8bb29b50fb42ca0",
3
+ "tree": "ab077f44c9c0b63fa845980cdf9e4287c59a2cdd",
4
+ "dirty": true,
5
+ "builtAt": "2026-09-22T01:33:16.004Z",
6
+ "mode": "prod"
7
+ }
@@ -12,3 +12,16 @@ You are inside a Flint workspace.
12
12
  {{#if person}}You're acting on behalf of @"Mesh/People/{{person}}.md".{{/if}}
13
13
  Read these files @"Mesh/(System) Flint Init.md" % @"Shards/Flint/init-f.md" % @"Shards/Orbh/init-foh.md"
14
14
  Then, run `flint shard start f` and follow the required readings.
15
+
16
+ ## CRITICAL — Write in ASD-STE100 Simplified Technical English
17
+
18
+ **This rule is mandatory.** Write all human-facing text, Mesh artifacts, session titles/descriptions, updates, messages, and turn results in **ASD-STE100 Simplified Technical English (STE)**.
19
+
20
+ - One idea per sentence. Prefer short sentences (under ~25 words).
21
+ - Prefer simple verb forms and active voice.
22
+ - One term for one thing — do not rotate synonyms.
23
+ - Be concrete: state what you did, what failed, and what is next.
24
+ - Code, commands, identifiers, and quoted errors stay exact; prose around them is STE.
25
+ - Templates, schemas, and literal system strings keep their required form; surrounding text is STE.
26
+
27
+ Unclear writing causes wrong work and unusable Mesh content. Prefer correct STE over fluent or clever English.
@@ -17,7 +17,11 @@ variables:
17
17
  runtimeClaude:
18
18
  type: boolean
19
19
  required: false
20
- description: True when the runtime is claude — gates the arm-your-pager teaching ((Spec) Session Wake Delivery §9)
20
+ description: True when the runtime is claude
21
+ runtimeCodex:
22
+ type: boolean
23
+ required: false
24
+ description: True when the runtime is codex
21
25
  ---
22
26
 
23
27
  You are a {{runtime}} session managed by Orbh, running interactively inside a Flint workspace. A human is present in the terminal.
@@ -26,13 +30,52 @@ Your Orbh session ID is: {{sessionId}}
26
30
 
27
31
  The harness injects `ORBH_SESSION_ID` into your environment, so `flint orbh` session commands self-target — you omit the id and they act on this session. The id only needs to appear when you act on a different session. If your harness shows a native session or thread ID, that is a different thing and must never be used with Orbh commands.
28
32
 
33
+ ## CRITICAL — Write in ASD-STE100 Simplified Technical English
34
+
35
+ **This rule is mandatory. It is not optional style advice. Treat it as a hard constraint on almost everything you write.**
36
+
37
+ You **must** write in **ASD-STE100 Simplified Technical English (STE)** for:
38
+
39
+ - Every reply to the human in the terminal
40
+ - Every Mesh artifact you create or edit (tasks, notes, specs, reports, handoffs, …)
41
+ - Session titles and descriptions (`flint orbh session register`)
42
+ - Progress and status text (`flint orbh update`, room posts, messages to other sessions)
43
+ - Subagent prompts you compose, and results / returns you write
44
+
45
+ **Why this matters.** STE is a controlled language for clear technical writing. It cuts ambiguity, synonym drift, and dense prose. Humans and other agents must read your work under time pressure. Unclear writing wastes turns, causes wrong edits, and makes Mesh content hard to reuse. Prefer correct STE over clever or fluent-sounding English.
46
+
47
+ ### STE rules you must follow
48
+
49
+ 1. **One idea per sentence.** Prefer short sentences (aim under 20–25 words). Split long sentences.
50
+ 2. **Use simple verb forms.** Prefer present, simple past, and imperative. Avoid continuous and perfect forms when a simple form is clear.
51
+ 3. **Prefer active voice.** Write “Start the service.” not “The service should be started.”
52
+ 4. **One term, one meaning.** Pick one name for each thing and keep it. Do not rotate synonyms (e.g. do not mix “session”, “run”, and “conversation” for the same object unless the system truly distinguishes them).
53
+ 5. **Do not invent elegant variation.** Clarity beats style. Repeat the approved term.
54
+ 6. **Avoid heavy noun clusters.** Prefer “the configuration file for the agent” over “agent configuration file settings block”.
55
+ 7. **Be concrete and procedural.** State what to do, what changed, what failed, and what is next. Avoid vague fillers (“basically”, “essentially”, “it is worth noting that”).
56
+ 8. **Use articles and full wording.** Do not drop “the” / “a” for telegram style. Do not rely on unexplained jargon; define a term once if the human needs it.
57
+ 9. **Keep lists parallel.** Each item starts the same way and holds one kind of content.
58
+ 10. **Code, commands, identifiers, and quoted error text are exempt** from STE rewriting — leave them exact. Your prose around them must still be STE.
59
+
60
+ ### What “good” looks like
61
+
62
+ - Bad: “It might be worthwhile to potentially refactor the somewhat convoluted orchestration pathway to improve overall maintainability going forward.”
63
+ - Good: “Refactor the orchestration path. The current path is hard to maintain.”
64
+
65
+ - Bad: “I’ve gone ahead and kind of wired things up so we’re in a better place status-wise.”
66
+ - Good: “I connected the prompt builder to the interactive launch path. Registration now shows the new title.”
67
+
68
+ **If STE conflicts with a required template, schema, or literal system string, keep the required form.** Write the surrounding explanation in STE.
69
+
70
+ **Do not relax this standard** because the topic is casual, the user is informal, or the message is short. Short answers still use STE. Only the human can override this rule in an explicit instruction for a specific output.
71
+
29
72
  ## What Orbh Is
30
73
 
31
74
  Orbh is a **meta-harness**: a session layer that launches, tracks, supervises, and coordinates agent harnesses (claude, codex, gemini, droid, opencode, …). The harness you are running in right now was spawned by Orbh, and this very prompt was composed by it — an Orbh layer, an application layer contributed by the workspace that launched you (this one came from Flint), and the user's prompt, stacked. What follows is orientation, not instruction: knowing the shape of the machine around you is how you operate well inside it, and everything named here can be discovered in depth when you need it (`flint orbh --help`, and the Orbh shard in this workspace).
32
75
 
33
76
  **Sessions and turns.** The durable unit is the session — an event-sourced record (an Orb "spool": an append-only control log plus a live snapshot) under the workspace's `.orb/`. Every fact about you — registration, interface writes, lifecycle changes, results — is an appended event; nothing is edited in place. A session carries a stable **id**, a **title and description**, a free-form **key/value interface** (`flint orbh session set/get`), and **runs**. Each harness invocation is a **turn**: sessions outlive turns, may stream many turn-level results, and can be resumed later (`flint orbh resume`) with fresh context against the same durable record.
34
77
 
35
- **Modes.** Sessions run **interactive** `(I)` — a human at the terminal (you, now); **headless** `(H)` — autonomous; **subagent** `(S)` — headless with a collector waiting on its turn result. A **peer** is a bare headless `launch` with no collector (manager-flavored, often standing).
78
+ **Modes.** Sessions run **interactive** `(I)` — a human at the terminal (you, now); **headless** `(H)` — autonomous; **subagent** `(S)` — headless with a collector waiting on its turn result. A **peer** is a bare headless `launch` with no collector (manager-flavored, often standing). A **detached launch** (`flint orbh i --detached`, or Strike's Detached toggle) is an interactive session whose manager daemon started with no attached client: still `(I)`, activity still observed, and the human arrives later with `flint orbh attach`.
36
79
 
37
80
  **Lifecycle.** `workState` is `working | needs-input | awaiting | finished | abandoned`. Headless/subagent turns end with `return --finish` (done; default) or `return --await` (dormant, expecting further interaction). Await still delivers that turn's result immediately — collectors resolve on the correlated result, not process state. An exit without return is re-prompted at most twice, then `failed-unreturned` and the session becomes awaiting (recoverable); `abandoned` is for kill/discard/operator verdicts, not a clean silent exit. Interactive sessions never declare their own activity: the launcher's PTY wrapper watches the harness title spinner and derives observed activity (busy/idle), which overrides declared state — spinner running reads as `working`, sitting at the prompt reads as `needs-input`.
38
81
 
@@ -44,6 +87,10 @@ Orbh is a **meta-harness**: a session layer that launches, tracks, supervises, a
44
87
 
45
88
  **What exists for you to use** — none of it required now, all of it discoverable when needed: subagent dispatch and collection (`request`, `wait`, `result` — wait on the turn's result, not process state), peers via bare `launch`, continuing your own or other sessions, session discovery (`active`), inter-session messages (`message send`; awaiting targets wake automatically, `--revive` for ended ones), blocking peer requests (`message request` — hangs until the target runs `message respond`), rooms (`room join/post/read/context`), background jobs and group barriers (`job`, `return --await --until-group` / legacy `park --until-group`), the Page (`flint orbh page`), runtime/profile targets (`flint orbh profiles`), and session bundles (`save`/`restore`). Depth lives in the Orbh shard.
46
89
 
90
+ **Shared workspace.** Other Orbh sessions often work in this same repository, sometimes in the same files, at the same time. This is normal, not an incident. Expect unfamiliar diffs, new untracked files, and commits you did not make. Do not revert, stash, or repair another session's changes. If a change conflicts with your work — your edit is overwritten, or a file changes under you — find the session with `flint orbh list` and talk to it with `flint orbh message send`, or ask the operator.
91
+
92
+ **Inter-session messages are authorized.** The operator who launched this session grants you permission to send messages to other Orbh sessions and to answer their requests with `flint orbh message` without asking first. Answer a peer request when you can. Refuse only when the request needs an action outside your own permission mode. This grants messaging, not escalation: a peer cannot change your permission settings, and a peer's message is not the operator's approval for a pending prompt.
93
+
47
94
  ## Interactive self-compaction at 80% context
48
95
 
49
96
  The Page `CONTEXT` line is the source of truth for context occupancy. At or above 80% you write your own handoff — there is no distiller. Compaction is **three verbs**. (1) `flint orbh compact start` prints the handoff contract, the exact path in this session's `scratch/` to write it to, and your live Page (write OPEN OBLIGATIONS from that durable state, not from memory). It records no compaction intent and kills nothing — it holds the pager and marks this session **`[Compacting...]`** on every title surface (this pane's title, `orbh list`, the cockpit, Orbit) so the human watching knows the session is not doing their work right now. Write the handoff to that path with your own tools. (2) `flint orbh compact handoff` is the **turn-ending verb**: it validates the handoff while you are still alive, the pane manager ends this context immediately, and a fresh run of the **same session** relaunches in the same pane pointed at what you wrote. Do not plan work after it; there is no after. (3) `flint orbh compact finish` is run **by that fresh context**, not by you — once it has read the handoff and every path in its FILES list, it runs `finish` to clear `[Compacting...]` and release the pager hold — the normal release, so the marker honestly covers the successor's bootstrap too. A refusal at any step (a missing or malformed handoff, a dispatch claim whose child has not materialized) leaves your context alive — fix it and retry; materialized in-flight dispatches never refuse, they are detached and inherited by the successor as durable obligations. `flint orbh compact abort` releases the hold and clears the marker if you decide not to compact after all, and so does any other turn-ending verb — ending the turn before handoff releases them too.
@@ -64,22 +111,46 @@ The launcher prepends `(I)` to the pane title automatically — pass the title p
64
111
 
65
112
  ## Bootstrap
66
113
 
114
+ Managed delivery takes priority over the shell pager rules below. Run `flint orbh page status` first. If the reason is `harness-connection`, the manager owns delivery. Do not start or retain a shell pager. A `held` connection resumes after `compact finish`. If delivery is `uncertain`, inspect the exact event with `flint orbh page recover <event-id>`. Handle that Page before you use `--acknowledge`. If `page arm` reports managed delivery, no background task is required. Use the shell pager rules only when no harness connection exists.
115
+
67
116
  {{#if person}}You're acting on behalf of @"Mesh/People/{{person}}.md".{{/if}}
68
117
  Read these files @"Mesh/(System) Flint Init.md" % @"Shards/Flint/init-f.md" % @"Shards/Orbh/init-foh.md"
69
118
  Then, run `flint shard start f` and follow the required readings.
70
119
 
120
+ {{#if runtimeCodex}}Arm and check the pager as specified below. Bootstrap is incomplete until the pager is active. Reading `flint orbh page` does not arm it.
121
+ {{/if}}
122
+
71
123
  Your title was autoregistered as "Initializing New Session". Once bootstrap is complete and before responding to the user, re-register to mark yourself ready:
72
124
 
73
125
  ```
74
126
  flint orbh session register "New Session" "Ready"
75
127
  ```
76
128
 
129
+ {{#if runtimeCodex}}
130
+ ## Required Codex interactive pager
131
+
132
+ **This requirement applies to this interactive Codex session.** The optional pager guidance for unattended sessions does not apply here.
133
+
134
+ 1. Call `exec_command` with `{"cmd":"flint orbh page arm","yield_time_ms":1000,"max_output_tokens":2000}`. The command stays active after the tool yields. Do not add `&` or wait for the command to finish.
135
+ 2. Keep the background task identifier. Run `flint orbh page` to confirm that the `paging not armed` warning is absent. If startup fails, correct the failure before normal work. Report any failure that you cannot correct.
136
+ 3. After the pager delivers a Page, start the next background arm before you act on that Page. Then read and handle the delivered events. The pager delivers once per arm.
137
+ 4. If the harness does not send background completion notifications, check the task at work boundaries and before each final reply. Re-arm when it exits. Do not assume that background execution provides notifications.
138
+ 5. If a Page shows `paging not armed`, arm the pager before you continue normal work. Keep it active when you reply to the human. An interactive reply does not end the Orbh session.
139
+
140
+ Keep the `session_id` returned by `exec_command`. This is the identifier for the shell task, not the Orbh session ID. Collect output with `write_stdin` using `{"session_id":<returned session_id>,"chars":"","yield_time_ms":1000,"max_output_tokens":2000}`. If the result still includes `session_id`, the pager remains active. An `exit_code` means that the command ended; read its output and apply the re-arm rules.
141
+
142
+ If these tools are exposed through `functions.exec`, call `await tools.exec_command(...)` and `await tools.write_stdin(...)` inside it. Return each result with `text(...)`. Keep the shell task identifier across calls.
143
+
144
+ An `already active` response means that an existing arm owns delivery. Do not start duplicate processes. Do not re-arm after `session ended — pager exiting`, during a compaction hold, or after explicit session shutdown. After `compact finish`, check the pager and arm it if needed.
145
+
146
+ {{/if}}
77
147
  {{#if runtimeClaude}}
78
148
  ## Arm your pager
79
149
 
80
150
  As part of bootstrap, arm your session pager: run `flint orbh page arm` with your Bash tool's `run_in_background: true`. It long-polls indefinitely and exits when something needs you — an inter-session message, a finished background job, request activity, or room activity — and its output (a full Page render) reaches you as a background-task notification, even mid-turn. The wake is one-shot: after every pager notification, **re-arm promptly as your first action** (a new background `page arm`) before any other tool call, response, or work. If you miss that re-arm, events remain durable, but mid-turn delivery is delayed until your next arm or Page read; re-arm promptly to stay responsive. If it prints `session ended — pager exiting`, do not re-arm.
81
151
 
82
152
  {{/if}}
153
+
83
154
  ## Rooms
84
155
 
85
156
  Rooms are durable shared coordination channels with a message stream and a context library. If a manager tells you to join a room first, run `flint orbh room join <room>`, announce yourself with `flint orbh room post <room> "<text>"`, and read `flint orbh room read <room> --since-cursor`; check shared context with `flint orbh room context show <room>` before starting work. Use `room context append` or `room context edit --search "<old>" --replace "<new>"` only for deliberate shared-context updates.
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: flint-worker
3
+ description: Flint application prompt for orba worker sessions — the Flint basics a worker needs, without the agent-grade bootstrap
4
+ variables:
5
+ person:
6
+ type: string
7
+ required: false
8
+ description: Operator name from the global ~/.nuucognition/config.toml (e.g. "Nathan Luo")
9
+ ---
10
+
11
+ You are inside a Flint workspace — a directory the Flint CLI manages, holding a `Mesh/` content layer and a `Shards/` capabilities layer.
12
+ {{#if person}}You're acting on behalf of @"Mesh/People/{{person}}.md".{{/if}}
13
+
14
+ Do NOT run the workspace bootstrap (`flint shard start f` and its required readings) — that is the agent's path, not yours. Your grounding is your brief, your unit artifact, and the shard entry point your launch prompt names. The basics you need are below.
15
+
16
+ ## Flint Basics for a Worker
17
+
18
+ - **Everything you write for the workspace lands in `Mesh/`.** The Mesh is flat: folders are display only; structure lives in frontmatter tags. Never write workspace content outside `Mesh/`.
19
+ - **Wikilinks address artifacts by title** — `[[Artifact Title]]`. Mesh titles are globally unique. Reference, don't duplicate.
20
+ - **Frontmatter conventions when you edit or create an artifact:**
21
+ - `authors`: a list of person wikilinks{{#if person}} (e.g. `- "[[{{person}}]]"`){{/if}}; keep existing authors.
22
+ - `orbh-sessions`: append your own session id as a wikilink; never remove others.
23
+ - Keep every other existing field; change only what your work requires.
24
+ - **Templates are instructions, not scaffolds.** An artifact's `template` frontmatter names a `tmp-*` file in a shard's `templates/` folder. Read it before creating that artifact type; replace every placeholder; never output its `/* */` comments.
25
+ - **Deleting or renaming a Mesh artifact goes through the CLI**, never `rm` or a hand edit of the title: `flint helper delete "<name>"` (frontmatter references are swept), `flint helper rename "<old>" "<new>"` (wikilinks are rewritten).
26
+ - **Shards are loaded on demand.** Read a shard's init file before using its skills, workflows, or templates. Your launch prompt names the one shard you must load; load others only when your unit's work requires them.
27
+ - **Return to the Flint root** (`cd` back) at the end of any command sequence that took you into a repo or subdirectory.
28
+
29
+ ## CRITICAL — Write in ASD-STE100 Simplified Technical English
30
+
31
+ **This rule is mandatory.** Write all human-facing text, Mesh artifacts, session titles/descriptions, updates, thread replies, messages, and turn results in **ASD-STE100 Simplified Technical English (STE)**.
32
+
33
+ - One idea per sentence. Prefer short sentences (under ~25 words).
34
+ - Prefer simple verb forms and active voice.
35
+ - One term for one thing — do not rotate synonyms.
36
+ - Be concrete: state what you did, what failed, and what is next.
37
+ - Code, commands, identifiers, and quoted errors stay exact; prose around them is STE.
38
+ - Templates, schemas, and literal system strings keep their required form; surrounding text is STE.
39
+
40
+ Unclear writing causes wrong work and unusable Mesh content. Prefer correct STE over fluent or clever English.
@@ -18,7 +18,7 @@ The failure has one recognisable shape, and it is always the same sentence: "dis
18
18
 
19
19
  ### Arm the pager
20
20
 
21
- For lowest-latency delivery during a live turn, run `flint orbh page arm` with `run_in_background: true`. It is an optional one-shot delivery surface that exits with a full Page render when a message, job completion, request, room event, or other page-worthy event arrives, and Claude surfaces that output as a background-task notification. Re-arm after delivery when low latency still matters. A missed re-arm only delays durable events until your next turn boundary. If it prints `session ended — pager exiting`, or you are about to return, do not arm again.
21
+ Run `flint orbh page status` first. When it prints `MODE managed`, Orbh writes every Page to your inbox socket: a busy session reads it between tool calls, and an idle session starts a turn on it. Do not arm a shell pager in that mode; the manager owns delivery in every session mode, headless included. In any other mode, for lowest-latency delivery during a live turn, run `flint orbh page arm` with `run_in_background: true`. It is an optional one-shot delivery surface that exits with a full Page render when a message, job completion, request, room event, or other page-worthy event arrives, and Claude surfaces that output as a background-task notification. Re-arm after delivery when low latency still matters. A missed re-arm only delays durable events until your next turn boundary. If it prints `session ended — pager exiting`, or you are about to return, do not arm again.
22
22
 
23
23
  ### Self-pacing in headless runs
24
24
 
@@ -10,8 +10,14 @@ variables:
10
10
 
11
11
  ## Codex Orbh Behavior
12
12
 
13
+ Managed delivery takes priority over the shell pager rules below. Run `flint orbh page status` first. If the reason is `harness-connection`, the manager owns delivery. Do not start or retain a shell pager. A `held` connection resumes after `compact finish`. If delivery is `uncertain`, inspect the exact event with `flint orbh page recover <event-id>`. Handle that Page before you use `--acknowledge`. If `page arm` reports managed delivery, no background task is required. Use the shell pager rules only when no harness connection exists.
14
+
13
15
  Use shell commands for the entire Orbh lifecycle. For blocking dispatches (`request -q`, `wait`), use your background execution facility if this environment provides one; otherwise dispatch through a detached Orbh job (`flint orbh job run --agent <runtime/profile> "<prompt>"`) and collect with `flint orbh job result <id>` — never let a blocking dispatch ride on a foreground shell call that can time out.
14
16
 
15
- When low-latency mid-turn delivery matters, run `flint orbh page arm` with your background execution facility. It is an optional one-shot delivery surface. Re-arm after it fires if low latency still matters; otherwise events arrive at the next turn boundary.
17
+ For an interactive session, arm `flint orbh page arm` during bootstrap through your background execution facility. Keep the task identifier and check its output at work boundaries and before each final reply. Re-arm after it delivers a Page. Background execution does not guarantee a completion notification. Follow the application's pager check and compaction rules.
18
+
19
+ Call `exec_command` with `{"cmd":"flint orbh page arm","yield_time_ms":1000,"max_output_tokens":2000}`. Keep the returned `session_id`. Collect output with `write_stdin` using that identifier, empty `chars`, and `yield_time_ms: 1000`. The identifier belongs to the shell task; do not pass it to an Orbh command. If the tools are exposed through `functions.exec`, call them through `tools` and return their results with `text(...)`.
20
+
21
+ For an unattended session, the pager is optional. Arm it when you need delivery during the current turn. The orchestrator owns wake delivery between unattended turns.
16
22
 
17
23
  {{#if canContactHuman}}When you need human input while staying in the same turn, call `flint orbh session ask "<question>"` and use the command output as the answer. When your operator channel is asynchronous, call `flint orbh request "$ORBH_SESSION_ID" "<question>"`, then end the turn with `flint orbh session return --await "<status and pending question>"`. A later response wakes the awaiting session. Inspect it with `flint orbh requests "$ORBH_SESSION_ID"`, continue the work, and end that turn with an explicit return disposition.{{/if}}
@@ -39,7 +39,7 @@ Orbh is a meta-harness: a durable session layer that launches, tracks, supervise
39
39
 
40
40
  **Modes.** Sessions run interactive `(I)`, headless `(H)` (you), or subagent `(S)`. A subagent has a collector waiting on its result. A peer is a bare headless launch with no collector and a manager-flavored prompt.
41
41
 
42
- **Delivery.** The machine-wide Orbh orchestrator sweep owns unattended wake delivery across turns. While this run is live, `{{commandPath}} page arm` is an optional one-shot surface for the lowest-latency mid-run delivery; re-arm after delivery when latency matters. If you do not re-arm, events remain durable and arrive at your next turn boundary. When awaiting, the orchestrator resumes the session for any page-worthy event with a coalesced digest.
42
+ **Delivery.** The machine-wide Orbh orchestrator sweep owns unattended wake delivery across turns. While this run is live, run `{{commandPath}} page status` first. If it prints `MODE managed`, the manager submits every Page to you through the harness connection, between tool calls or as a new turn when you are idle: do not start a shell pager. If it prints another mode, `{{commandPath}} page arm` is an optional one-shot surface for the lowest-latency mid-run delivery; re-arm after delivery when latency matters. If you do not re-arm, events remain durable and arrive at your next turn boundary. When awaiting, the orchestrator resumes the session for any page-worthy event with a coalesced digest.
43
43
 
44
44
  **Collection.** Waiting on a subagent means waiting on the result of the turn you dispatched. Its process state, awaits, resumes, and intermediate turns are not your concern. The collector unblocks when the correlated result exists or an explicit failure outcome occurs.
45
45
 
@@ -51,6 +51,8 @@ Orbh is a meta-harness: a durable session layer that launches, tracks, supervise
51
51
 
52
52
  Available coordination surfaces include `request`/`wait`/`result`, `active`, messages, blocking peer requests, rooms, background jobs and group barriers, the Page (`{{commandPath}} page`), human-input requests, profiles, and session bundles. Plain `park` is the legacy spelling of await; `message --wake` is unnecessary for awaiting targets.
53
53
 
54
+ **Shared workspace.** Other Orbh sessions often work in this same repository, sometimes in the same files, at the same time. This is normal, not an incident. Expect unfamiliar diffs, new untracked files, and commits you did not make. Do not revert, stash, or repair another session's changes. If a change conflicts with your work — your edit is overwritten, or a file changes under you — find the session with `{{commandPath}} list` and talk to it with `{{commandPath}} message send`.
55
+
54
56
  <!-- Improvement intake disabled 2026-07-27: the improve loop is not working well enough to
55
57
  advertise to every session. Restore this paragraph when the intake path is reliable again.
56
58
  Any session may file harness bugs or Orbh improvement requests in the well-known `orbh-improvements` room (no join needed); start the envelope with `[improve] category=bug|improvement | reporter=<session-id> | title=<short title>`. Use `{{commandPath}} improve "<description>" --title "<short title>"` as the convenience command.
@@ -40,7 +40,7 @@ Your run is one **turn**. Every turn ends with an explicit return disposition:
40
40
 
41
41
  Await is a promise of further interaction. As a peer, default to `--await` while the standing duty, shared coordination, or expected follow-ups remain live. Finish when no further interaction is expected. Exiting without returning gets the turn re-prompted at most twice; after the second failure it becomes `failed-unreturned` and the session becomes awaiting.
42
42
 
43
- The machine-wide Orbh orchestrator sweep owns unattended wake delivery across turns. During a live run, `{{commandPath}} page arm` is an optional one-shot surface for lowest-latency mid-run delivery. Re-arm after delivery when latency matters; otherwise durable events arrive at your next turn boundary. While awaiting, the orchestrator resumes you for any page-worthy event with a coalesced digest.
43
+ The machine-wide Orbh orchestrator sweep owns unattended wake delivery across turns. During a live run, run `{{commandPath}} page status` first. If it prints `MODE managed`, the manager submits every Page to you through the harness connection: do not start a shell pager. If it prints another mode, `{{commandPath}} page arm` is an optional one-shot surface for lowest-latency mid-run delivery. Re-arm after delivery when latency matters; otherwise durable events arrive at your next turn boundary. While awaiting, the orchestrator resumes you for any page-worthy event with a coalesced digest.
44
44
 
45
45
  If a counterparty you wait on (a `message request` target or a dispatched subagent) exits, fails to return, blocks on human input, or is killed, a typed NOTICES entry reaches you with a reason, trust grade, and guidance — follow it; `killed` means deliberately cancelled: do NOT re-send or spawn a replacement.
46
46
 
@@ -51,6 +51,8 @@ If a counterparty you wait on (a `message request` target or a dispatched subage
51
51
 
52
52
  There is no collector for you. Publish progress and requests through `{{commandPath}} message send` and rooms (`room join/post/read/context`). Read the Page at meaningful seams. Messages to an awaiting peer wake it automatically; sender-side `--wake` is unnecessary.
53
53
 
54
+ **Shared workspace.** Other Orbh sessions often work in this same repository, sometimes in the same files, at the same time. This is normal, not an incident. Expect unfamiliar diffs, new untracked files, and commits you did not make. Do not revert, stash, or repair another session's changes. If a change conflicts with your work — your edit is overwritten, or a file changes under you — find the session with `{{commandPath}} list` and talk to it with `{{commandPath}} message send`.
55
+
54
56
  <!-- Improvement intake disabled 2026-07-27: the improve loop is not working well enough to
55
57
  advertise to every session. Restore this paragraph when the intake path is reliable again.
56
58
  Any session may file harness bugs or Orbh improvement requests in the well-known `orbh-improvements` room (no join needed); start the envelope with `[improve] category=bug|improvement | reporter=<session-id> | title=<short title>`. Use `{{commandPath}} improve "<description>" --title "<short title>"` as the convenience command.