@nodii/dev 0.6.33 → 0.6.35

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
@@ -131,12 +131,14 @@ nodii-dev decisions create|lock|supersede|amend
131
131
 
132
132
  nodii-dev lane gather [KEY] [--delta] [--objective TEXT] [--done-check TEXT]
133
133
  [--paths A,B] [--components K,L]
134
+ nodii-dev lane gather show [KEY] [--gather ID]
134
135
  nodii-dev lane freeze add KEY --section SECTION --file ITEM.json --reason TEXT
135
136
  nodii-dev lane freeze drop KEY --section SECTION --item ID --reason TEXT
136
137
  nodii-dev lane freeze swap KEY --section SECTION [--item ID] --file VALUE.json --reason TEXT
137
138
  nodii-dev lane freeze show KEY
138
139
  nodii-dev lane freeze history KEY
139
140
  nodii-dev rules find "QUESTION" [--limit N]
141
+ nodii-dev rules show CLAUSE_ID
140
142
  nodii-dev gather tune cases|runs
141
143
  nodii-dev gather tune replay CASE_ID
142
144
  nodii-dev gather tune start --cases all|ID,ID --corpus-ref REF [--trigger T] [--settings JSON]
@@ -404,7 +406,13 @@ changes, production-secret/test-auth bypasses, cleanup of Docker resources the
404
406
  run did not create, and deploy/apply commands without an exact grant. Allowed
405
407
  calls produce no output. Codex receives runtime-native `Bash` and `apply_patch`
406
408
  matchers, JSON denials, and `additionalContext` nudges. A compact session start
407
- prints the current lane Freeze again.
409
+ prints the current lane Freeze again, with how to fetch its full Clause map.
410
+
411
+ The Freeze pins only the ⚑ (counter-instinct) clauses, in full. Every other
412
+ Gather clause stays in the Clause map, which the Freeze references by Gather
413
+ id, listing one-line gists in rank order up to the 1,500-token cap ("+N more
414
+ in Clause map"). `lane gather show` prints the whole Clause map and
415
+ `rules show <ID>` prints one clause in full.
408
416
 
409
417
  Hard blocks apply only after Dev proves the current agent, branch and worktree
410
418
  belong to an active lane. Interactive or otherwise unproven sessions receive
@@ -807,6 +815,23 @@ The launched process uses the already-provisioned lowercase identity (for
807
815
  example `~/.config/nodii-dev/agents/lane-ah-12.json`), never the coordinator's
808
816
  Dev identity.
809
817
 
818
+ A lane's Figma scope is held by published key only (MW8-20): `--figma
819
+ FILE_KEY` for a whole file, or `--figma FILE_KEY=COMPONENT_SET_KEY[,KEY]` for
820
+ its component sets. A node id is refused. `--route /app/...` (repeatable)
821
+ derives the scope from the DS catalog (`https://design.nodii.co/registry.json`,
822
+ or `NODII_DEV_DS_REGISTRY_URL`): the route's Surfaces (page, dialogs, tabs),
823
+ each one's published `componentSetKey`, and its file. A route with no Surface
824
+ is `FIGMA_ROUTE_UNMAPPED` (a DS catalog fix), and a Surface whose key is not
825
+ published yet is `FIGMA_KEY_UNPUBLISHED`. The scope becomes the Freeze's Figma
826
+ boundaries. Gather sends the DS components those Surfaces are built from, so
827
+ their guidelines and U-docs apply, and pins one `figma-guidelines` lookup.
828
+ An explicit set key must be a published Surface in that file
829
+ (`FIGMA_KEY_UNKNOWN`). `figma lock`, `figma scope add|set` and the Figma
830
+ pre-write hook refuse a file, page, section or set outside the scope with
831
+ `FIGMA_OUTSIDE_LANE_SCOPE` (the hook exits 2). A lane that declared no Figma
832
+ scope is not bounded; a Freeze with `figma: []` means "no Figma" and refuses
833
+ every Figma lock and write.
834
+
810
835
  Objective, scope and rule changes are durable `lane amend` records, never chat
811
836
  messages. Every CLI call from a launched worktree checks the current watched
812
837
  run's acknowledgement version. A pending change is printed and blocks the
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  refuseFromLane,
21
21
  revokeOAuth,
22
22
  } from "./oauth.js";
23
- import { heartbeatCurrentLane, postHook, postHookFailure, preHook, sessionStartContext, settingsSnippet, workflowSuggestion } from "./hooks.js";
23
+ import { FIGMA_HOOK_DENIALS, heartbeatCurrentLane, postHook, postHookFailure, preHook, sessionStartContext, settingsSnippet, workflowSuggestion } from "./hooks.js";
24
24
  import { setupCommand } from "./setup.js";
25
25
  import { harnessCommand } from "./harness.js";
26
26
  import { hookRuntime, recordHookFire, safetyContext, safetyPostHook, safetyPreHook } from "./safety.js";
@@ -53,6 +53,7 @@ import {
53
53
  } from "./figma.js";
54
54
  export { figmaLock, submitMode } from "./figma.js";
55
55
  import { tuneCommand } from "./tune.js";
56
+ import { TUNING_MODELS, measurePickerLatency } from "./gather.js";
56
57
  import { docsCommand, rulebookCommand, rulesCommand } from "./upload.js";
57
58
  import { changeSetCommand, guidelineCommand } from "./guidelines.js";
58
59
  import { designCheck, designCheckText, designRoles, designRolesText } from "./design.js";
@@ -155,6 +156,7 @@ Usage: nodii-dev <command> [options] [--json]
155
156
  rules core # the generated core (M05-33); refused over the cap
156
157
  rules report [--section S] [--lane KEY] # delivery totals per document; rules served per lane
157
158
  rules find "QUESTION" [--limit N] # answer an ad-hoc rules question from the indexed sections
159
+ rules show CLAUSE_ID # one clause in full, from the current document version
158
160
  rules cap TOKENS # operator: set the core token cap (default 3000)
159
161
  gather tune cases|runs # Gather tuning (AH-11): frozen cases; runs with per-picker scores
160
162
  gather tune replay <case-id> # blind replay + trigger shortlist, for the lane-agent picker
@@ -165,16 +167,20 @@ Usage: nodii-dev <command> [options] [--json]
165
167
  gather tune trial <run-id> --case ID --picker P --iteration N [--documents A,B]
166
168
  # one trial; lane-agent passes its own --documents pick
167
169
  gather tune finalize <run-id> # Dev scores the full 5-picker x 5-repeat matrix
170
+ gather picker-latency [--picker gemma-12b|gemma-e4b|gemma-26b]
171
+ # cold (model unloaded first) and warm pick latency, for the tuning record
168
172
 
169
173
  coordinator start --machine NAME # register this machine's one watched coordinator; refuses a live second
170
174
  lane launch <key> --done-check TEXT --kind KIND --side SIDE
171
175
  --issue KEY --repo NAME=/SOURCE --branch NAME=BRANCH [--repo ... --branch ...]
172
176
  --machine NAME --runtime claude|codex --profile PATH --model MODEL --subagents N
173
177
  [--base NAME=REF] [--worktree NAME=PATH] [--owned-path NAME=PATH]
174
- [--figma FILE[=COMPONENT_SET[,SET]]] [--notes TEXT]
178
+ [--route /app/... ...] [--figma FILE_KEY[=COMPONENT_SET_KEY[,KEY]]] [--notes TEXT]
175
179
  [--narrowing-note TEXT --narrowing-remainder DESTINATION]
176
180
  # authoritative preflight, one worktree per repo, watched launch
177
181
  # uses the provisioned agents/lane-<key>.json Dev identity
182
+ # Figma scope by published key: --route derives it from the
183
+ # DS catalog (route -> Surfaces -> componentSetKey -> file)
178
184
  lane amend <key> --objective|--scope|--rules TEXT --reason TEXT
179
185
  lane gather [<key>] [--delta] [--objective TEXT] [--done-check TEXT] [--components a,b] [--paths a,b]
180
186
  # infers a launched worktree; explicit contract inputs support manual lane start
@@ -182,6 +188,7 @@ Usage: nodii-dev <command> [options] [--json]
182
188
  # the lane agent picks instead of local Gemma: alone it prints the
183
189
  # recorded trigger shortlist; with --shortlist/--documents it records
184
190
  # the pick (picker: agent) and the Clause map
191
+ lane gather show [<key>] [--gather ID] # the lane's Clause map (the Freeze references it, not its clauses)
185
192
  run [--kind build|test_run|subagent|deploy] [--name TEXT] -- <command> [args...]
186
193
  # watched command: registers with NODII_DEV_RUN_ID,
187
194
  # heartbeats, and records exit code + redacted log tail
@@ -584,6 +591,14 @@ export async function main(argv = process.argv.slice(2)) {
584
591
  if (command === "docs") return emitCommand(await docsCommand(action, rest, f));
585
592
  if (command === "rulebook" && ["list", "show", "diff"].includes(action)) return emitCommand(await rulebookCommand(action, rest, f));
586
593
  if (command === "rules") return emitCommand(await rulesCommand(action, rest, f));
594
+ if (command === "gather" && action === "picker-latency") {
595
+ const name = f.picker ?? "gemma-12b";
596
+ const model = Object.hasOwn(TUNING_MODELS, name) ? TUNING_MODELS[name] : null;
597
+ if (!model) throw new CliError("USAGE", `gather picker-latency [--picker ${Object.keys(TUNING_MODELS).join("|")}]`, 2);
598
+ const result = await measurePickerLatency({ model });
599
+ const line = (label, x) => `${label} ${x.wallMs} ms (Ollama total ${x.totalMs ?? "?"} ms, model load ${x.loadMs ?? "?"} ms)`;
600
+ return emit(result, json, (r) => `${r.model}\n${line("cold", r.cold)}\n${line("warm", r.warm)}`);
601
+ }
587
602
  if (command === "gather" && action === "tune") {
588
603
  const result = await tuneCommand(rest[0], rest.slice(1), f);
589
604
  emit(result.payload, json, result.human);
@@ -918,7 +933,7 @@ export async function main(argv = process.argv.slice(2)) {
918
933
  } catch (error) {
919
934
  // A known policy denial still blocks. Hook/runtime failures fail open
920
935
  // and stay silent so a broken environment cannot stop the session.
921
- if (!["FIGMA_FILE_KEY_MISSING", "FIGMA_LOCK_DENIED"].includes(error?.code)) return;
936
+ if (!FIGMA_HOOK_DENIALS.includes(error?.code)) return;
922
937
  if (payload && hookRuntime(payload) === "codex") {
923
938
  console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: `Blocked Figma write: ${error?.message ?? String(error)}` } }));
924
939
  return;
package/dist/core.js CHANGED
@@ -4,7 +4,7 @@ import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
4
4
  import { homedir, platform } from "node:os";
5
5
  import { dirname, join } from "node:path";
6
6
 
7
- export const VERSION = "0.6.33";
7
+ export const VERSION = "0.6.35";
8
8
  export const configPath = () =>
9
9
  process.env.NODII_DEV_CONFIG_PATH ??
10
10
  join(homedir(), ".config/nodii-dev/config.json");