devrites 3.2.1 → 3.2.2

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 (54) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +1 -1
  3. package/engine/hooks.go +17 -3
  4. package/engine/hooks_workspace.go +18 -3
  5. package/engine/tests/hook_test.go +93 -0
  6. package/pack/generated/codex/AGENTS.md +4 -3
  7. package/pack/generated/codex/hooks.json +15 -0
  8. package/pack/generated/codex/skills/devrites-api-interface/SKILL.md +4 -4
  9. package/pack/generated/codex/skills/devrites-audit/SKILL.md +4 -4
  10. package/pack/generated/codex/skills/devrites-browser-proof/SKILL.md +4 -4
  11. package/pack/generated/codex/skills/devrites-debug-recovery/SKILL.md +4 -4
  12. package/pack/generated/codex/skills/devrites-doubt/SKILL.md +4 -4
  13. package/pack/generated/codex/skills/devrites-frontend-craft/SKILL.md +4 -4
  14. package/pack/generated/codex/skills/devrites-interview/SKILL.md +4 -4
  15. package/pack/generated/codex/skills/devrites-lib/SKILL.md +4 -4
  16. package/pack/generated/codex/skills/devrites-prose-craft/SKILL.md +4 -4
  17. package/pack/generated/codex/skills/devrites-refresh-indexes/SKILL.md +4 -4
  18. package/pack/generated/codex/skills/devrites-source-driven/SKILL.md +4 -4
  19. package/pack/generated/codex/skills/devrites-ux-shape/SKILL.md +4 -4
  20. package/pack/generated/codex/skills/rite/SKILL.md +4 -4
  21. package/pack/generated/codex/skills/rite-adopt/SKILL.md +4 -4
  22. package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +4 -4
  23. package/pack/generated/codex/skills/rite-build/SKILL.md +4 -4
  24. package/pack/generated/codex/skills/rite-clarify/SKILL.md +4 -4
  25. package/pack/generated/codex/skills/rite-converge/SKILL.md +4 -4
  26. package/pack/generated/codex/skills/rite-customize/SKILL.md +4 -4
  27. package/pack/generated/codex/skills/rite-define/SKILL.md +4 -4
  28. package/pack/generated/codex/skills/rite-doctor/SKILL.md +4 -4
  29. package/pack/generated/codex/skills/rite-dogfood/SKILL.md +4 -4
  30. package/pack/generated/codex/skills/rite-explain/SKILL.md +4 -4
  31. package/pack/generated/codex/skills/rite-frame/SKILL.md +4 -4
  32. package/pack/generated/codex/skills/rite-handoff/SKILL.md +4 -4
  33. package/pack/generated/codex/skills/rite-learn/SKILL.md +4 -4
  34. package/pack/generated/codex/skills/rite-plan/SKILL.md +4 -4
  35. package/pack/generated/codex/skills/rite-polish/SKILL.md +4 -4
  36. package/pack/generated/codex/skills/rite-pov/SKILL.md +4 -4
  37. package/pack/generated/codex/skills/rite-pr-feedback/SKILL.md +4 -4
  38. package/pack/generated/codex/skills/rite-pressure-test/SKILL.md +4 -4
  39. package/pack/generated/codex/skills/rite-prototype/SKILL.md +4 -4
  40. package/pack/generated/codex/skills/rite-prove/SKILL.md +4 -4
  41. package/pack/generated/codex/skills/rite-quick/SKILL.md +4 -4
  42. package/pack/generated/codex/skills/rite-resolve/SKILL.md +4 -4
  43. package/pack/generated/codex/skills/rite-review/SKILL.md +4 -4
  44. package/pack/generated/codex/skills/rite-seal/SKILL.md +4 -4
  45. package/pack/generated/codex/skills/rite-ship/SKILL.md +4 -4
  46. package/pack/generated/codex/skills/rite-spec/SKILL.md +4 -4
  47. package/pack/generated/codex/skills/rite-status/SKILL.md +4 -4
  48. package/pack/generated/codex/skills/rite-temper/SKILL.md +4 -4
  49. package/pack/generated/codex/skills/rite-upgrade/SKILL.md +4 -4
  50. package/pack/generated/codex/skills/rite-vet/SKILL.md +4 -4
  51. package/pack/generated/codex/skills/rite-zoom-out/SKILL.md +4 -4
  52. package/package.json +1 -1
  53. package/scripts/codex-generate.sh +24 -8
  54. package/scripts/npm-audit-exceptions.json +12 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to DevRites are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and DevRites adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Releases are generated automatically by [semantic-release](https://semantic-release.gitbook.io/) from Conventional Commits on `main`.
4
4
 
5
+ ## [3.2.2](https://github.com/ViktorsBaikers/DevRites/compare/v3.2.1...v3.2.2) (2026-07-25)
6
+
7
+ ### Fixed
8
+
9
+ * **agents:** restore guarded codex dispatch ([2d05e20](https://github.com/ViktorsBaikers/DevRites/commit/2d05e20f6196774827d1496275f4c3cb5c5e22e2))
10
+ * **ci:** govern bundled brace expansion advisory ([d1d0786](https://github.com/ViktorsBaikers/DevRites/commit/d1d078667fa42b61d8bec823136c628ca53fc6d8))
11
+
5
12
  ## [3.2.1](https://github.com/ViktorsBaikers/DevRites/compare/v3.2.0...v3.2.1) (2026-07-24)
6
13
 
7
14
  ### Fixed
package/README.md CHANGED
@@ -25,7 +25,7 @@ final commit, push, and tag, and it requires a typed `GO` confirmation.
25
25
  Unattended runs may create local WIP checkpoint commits along the way, but only
26
26
  Ship collapses and pushes them.
27
27
 
28
- **Status:** [`v3.2.1`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v3.2.1): see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
28
+ **Status:** [`v3.2.2`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v3.2.2): see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
29
29
 
30
30
  ## Quick start
31
31
 
package/engine/hooks.go CHANGED
@@ -246,16 +246,21 @@ const (
246
246
  devritesAgentNone devritesAgentKind = iota
247
247
  devritesAgentReadonly
248
248
  devritesAgentWright
249
+ devritesAgentGenericWright
249
250
  devritesAgentInvalid
250
251
  )
251
252
 
252
253
  // devritesAgent identifies the one write-capable leaf without copying the agent
253
254
  // roster. DEVRITES_AGENT_RUN supplies identity when a hook payload cannot carry
254
- // agent_type.
255
+ // agent_type; the generated Codex project hook explicitly opts built-in
256
+ // explorer/worker identities into the same policies.
255
257
  func devritesAgent(payloadAgent string) devritesAgentKind {
256
258
  payloadAgent = strings.TrimSpace(payloadAgent)
257
259
  envAgent := strings.TrimSpace(os.Getenv("DEVRITES_ACTIVE_AGENT"))
258
- declared := os.Getenv("DEVRITES_AGENT_RUN") == "1" || strings.HasPrefix(payloadAgent, "devrites-")
260
+ genericCompat := os.Getenv("DEVRITES_CODEX_GENERIC_AGENT_COMPAT") == "1"
261
+ declared := os.Getenv("DEVRITES_AGENT_RUN") == "1" ||
262
+ strings.HasPrefix(payloadAgent, "devrites-") ||
263
+ (genericCompat && (payloadAgent == "explorer" || payloadAgent == "worker"))
259
264
  if !declared {
260
265
  return devritesAgentNone
261
266
  }
@@ -269,6 +274,10 @@ func devritesAgent(payloadAgent string) devritesAgentKind {
269
274
  switch {
270
275
  case agent == "devrites-slice-wright":
271
276
  return devritesAgentWright
277
+ case genericCompat && agent == "worker":
278
+ return devritesAgentGenericWright
279
+ case genericCompat && agent == "explorer":
280
+ return devritesAgentReadonly
272
281
  case strings.HasPrefix(agent, "devrites-") && len(agent) > len("devrites-"):
273
282
  return devritesAgentReadonly
274
283
  default:
@@ -459,13 +468,18 @@ func hookReviewerReadonly(h harness.Harness, stdin io.Reader, stdout, stderr io.
459
468
  }
460
469
  in := h.ParseGuardInput(bytes.NewReader(data))
461
470
  kind := devritesAgent(in.AgentType)
471
+ if kind == devritesAgentNone &&
472
+ os.Getenv("DEVRITES_CODEX_GENERIC_AGENT_COMPAT") == "1" &&
473
+ in.AgentType == "" {
474
+ return exitOK
475
+ }
462
476
 
463
477
  // Do not let a global hook interfere with the main thread or another
464
478
  // product's agent when no DevRites run is declared.
465
479
  if kind == devritesAgentNone && (in.AgentType != "" || os.Getenv("DEVRITES_REVIEWER_AGENT_REQUIRED") == "1") {
466
480
  return exitOK
467
481
  }
468
- if kind == devritesAgentWright {
482
+ if kind == devritesAgentWright || kind == devritesAgentGenericWright {
469
483
  if !isAgentDispatchTool(in.ToolName) {
470
484
  return exitOK
471
485
  }
@@ -563,9 +563,15 @@ func hookWrightScope(h harness.Harness, stdin io.Reader, stdout, stderr io.Write
563
563
  }
564
564
  in := h.ParseGuardInput(bytes.NewReader(data))
565
565
  kind := devritesAgent(in.AgentType)
566
+ if kind == devritesAgentNone &&
567
+ os.Getenv("DEVRITES_CODEX_GENERIC_AGENT_COMPAT") == "1" &&
568
+ in.AgentType == "" {
569
+ return exitOK
570
+ }
566
571
  forgeDeclared := forgeWrightDeclared()
567
- active := kind != devritesAgentNone
568
- if forgeDeclared && kind != devritesAgentWright {
572
+ genericWright := kind == devritesAgentGenericWright
573
+ active := kind != devritesAgentNone && (!genericWright || forgeDeclared)
574
+ if forgeDeclared && kind != devritesAgentWright && !genericWright {
569
575
  return denyWright(h, stdout, stderr, forgeWrightDenyReason, drvreason.HookForgeBindingDenied)
570
576
  }
571
577
  if kind == devritesAgentNone && (in.AgentType != "" || os.Getenv("DEVRITES_WRIGHT_AGENT_REQUIRED") == "1") {
@@ -607,6 +613,15 @@ func hookWrightScope(h harness.Harness, stdin io.Reader, stdout, stderr io.Write
607
613
  }
608
614
  return exitOK
609
615
  }
616
+ if genericWright && !forgeDeclared {
617
+ if !wsIsFile(filepath.Join(dir, ".reconcile-base")) {
618
+ return exitOK
619
+ }
620
+ if wsIsFile(filepath.Join(dir, ".reconcile-inline")) {
621
+ return denyWright(h, stdout, stderr, wrightForbiddenReason, drvreason.HookWrightForbiddenDenied)
622
+ }
623
+ active = true
624
+ }
610
625
 
611
626
  if wrightForbiddenShellRe.MatchString(in.Command) ||
612
627
  (opaqueInterpreterRe.MatchString(in.Command) && !safeReadonlyShellCommand(in.Command)) {
@@ -617,7 +632,7 @@ func hookWrightScope(h harness.Harness, stdin io.Reader, stdout, stderr io.Write
617
632
  }
618
633
 
619
634
  projectDir := filepath.Dir(root)
620
- if !forgeDeclared && kind == devritesAgentWright && insideForgeStaging(projectDir) {
635
+ if !forgeDeclared && (kind == devritesAgentWright || genericWright) && insideForgeStaging(projectDir) {
621
636
  return denyOrObserveWright(h, stdout, stderr, dir, true, forgeWrightDenyReason, drvreason.HookForgeBindingDenied, []string{"missing Forge binding"})
622
637
  }
623
638
  if forgeDeclared {
@@ -347,6 +347,36 @@ func TestHookReviewerReadonlyAgentRequiredSkipsNonDevrites(t *testing.T) {
347
347
  }
348
348
  }
349
349
 
350
+ func TestHookReviewerReadonlyBindsCodexExplorerCompatibility(t *testing.T) {
351
+ root := newWorkspace(t)
352
+ in := `{"tool_name":"Edit","tool_input":{"file_path":"src/app.go"},"agent_type":"explorer"}`
353
+ out, errOut, code := runDevritesIO(t, root, in,
354
+ []string{"DEVRITES_CODEX_GENERIC_AGENT_COMPAT=1"},
355
+ "hook", "reviewer-readonly", "--harness=codex")
356
+ if code != 0 {
357
+ t.Fatalf("exit=%d stderr=%q", code, errOut)
358
+ }
359
+ if decision, _ := parsePermissionDecision(t, out); decision != "deny" {
360
+ t.Fatalf("generic explorer mutation was not denied: %q", out)
361
+ }
362
+ }
363
+
364
+ func TestCodexGenericCompatibilityDoesNotShadowRoot(t *testing.T) {
365
+ root := newWorkspace(t)
366
+ in := `{"tool_name":"Edit","tool_input":{"file_path":"src/app.go"}}`
367
+ env := []string{
368
+ "DEVRITES_CODEX_GENERIC_AGENT_COMPAT=1",
369
+ "DEVRITES_HOOK_PROFILE=strict",
370
+ }
371
+ for _, guard := range []string{"reviewer-readonly", "wright-scope"} {
372
+ out, errOut, code := runDevritesIO(t, root, in, env,
373
+ "hook", guard, "--harness=codex")
374
+ if code != 0 || strings.TrimSpace(out) != "" {
375
+ t.Fatalf("%s shadowed root: exit=%d out=%q stderr=%q", guard, code, out, errOut)
376
+ }
377
+ }
378
+ }
379
+
350
380
  func TestHookReviewerReadonlyActiveLeafDeniesEveryMutationSurface(t *testing.T) {
351
381
  root := newWorkspace(t)
352
382
  env := []string{
@@ -435,6 +465,53 @@ func TestHookWrightScopeUsesExactOrchestratorAllowlist(t *testing.T) {
435
465
  }
436
466
  }
437
467
 
468
+ func TestHookWrightScopeBindsCodexWorkerDuringReconcileWindow(t *testing.T) {
469
+ root := newWorkspace(t)
470
+ writeActive(t, root, "auth-tokens")
471
+ workspace := filepath.Join(root, "features", "auth-tokens")
472
+ if err := os.WriteFile(filepath.Join(workspace, ".wright-allowlist"), []byte("src/app.go\n"), 0o600); err != nil {
473
+ t.Fatal(err)
474
+ }
475
+ if err := os.WriteFile(filepath.Join(workspace, ".reconcile-base"), []byte("snapshot\n"), 0o600); err != nil {
476
+ t.Fatal(err)
477
+ }
478
+ env := []string{"DEVRITES_CODEX_GENERIC_AGENT_COMPAT=1"}
479
+
480
+ for _, test := range []struct {
481
+ name string
482
+ input string
483
+ deny bool
484
+ }{
485
+ {"listed edit", `{"tool_name":"Edit","tool_input":{"file_path":"src/app.go"},"agent_type":"worker"}`, false},
486
+ {"unlisted edit", `{"tool_name":"Edit","tool_input":{"file_path":"src/other.go"},"agent_type":"worker"}`, true},
487
+ } {
488
+ t.Run(test.name, func(t *testing.T) {
489
+ out, errOut, code := runDevritesIO(t, root, test.input, env,
490
+ "hook", "wright-scope", "--harness=codex")
491
+ if code != 0 {
492
+ t.Fatalf("exit=%d stderr=%q", code, errOut)
493
+ }
494
+ if test.deny {
495
+ if decision, _ := parsePermissionDecision(t, out); decision != "deny" {
496
+ t.Fatalf("expected deny, got %q", out)
497
+ }
498
+ } else if strings.TrimSpace(out) != "" {
499
+ t.Fatalf("expected allow, got %q", out)
500
+ }
501
+ })
502
+ }
503
+
504
+ if err := os.Remove(filepath.Join(workspace, ".reconcile-base")); err != nil {
505
+ t.Fatal(err)
506
+ }
507
+ out, _, code := runDevritesIO(t, root,
508
+ `{"tool_name":"Edit","tool_input":{"file_path":"src/other.go"},"agent_type":"worker"}`,
509
+ env, "hook", "wright-scope", "--harness=codex")
510
+ if code != 0 || strings.TrimSpace(out) != "" {
511
+ t.Fatalf("generic worker outside a reconcile window was shadowed: exit=%d out=%q", code, out)
512
+ }
513
+ }
514
+
438
515
  func TestHookWrightScopeFailsClosedWhenWorkspaceResolutionFails(t *testing.T) {
439
516
  root := newWorkspace(t)
440
517
  if err := os.Remove(filepath.Join(root, "ACTIVE")); err != nil && !os.IsNotExist(err) {
@@ -523,6 +600,22 @@ func TestHookWrightScopeBindsForgeCandidateManifestIdentity(t *testing.T) {
523
600
  if code != 0 || strings.TrimSpace(out) != "" {
524
601
  t.Fatalf("valid Forge candidate was denied: exit=%d stdout=%s stderr=%s", code, out, stderr)
525
602
  }
603
+ genericEnv := append([]string{"DEVRITES_CODEX_GENERIC_AGENT_COMPAT=1"}, baseEnv[2:]...)
604
+ genericInput := `{"tool_name":"Edit","agent_id":"worker-a","agent_type":"worker","tool_input":{"file_path":"tracked.txt"}}`
605
+ out, stderr, code = runDevritesAt(t, repo, candidate.Worktree, genericInput, genericEnv,
606
+ "hook", "wright-scope", "--harness=codex")
607
+ if code != 0 || strings.TrimSpace(out) != "" {
608
+ t.Fatalf("valid generic Forge worker was denied: exit=%d stdout=%s stderr=%s", code, out, stderr)
609
+ }
610
+ out, _, code = runDevritesAt(t, repo, candidate.Worktree,
611
+ `{"tool_name":"Edit","agent_id":"worker-a","agent_type":"worker","tool_input":{"file_path":"outside.txt"}}`,
612
+ genericEnv, "hook", "wright-scope", "--harness=codex")
613
+ if code != 0 {
614
+ t.Fatalf("generic Forge worker hook exit=%d", code)
615
+ }
616
+ if decision, _ := parsePermissionDecision(t, out); decision != "deny" {
617
+ t.Fatalf("generic Forge worker escaped its allowlist: %s", out)
618
+ }
526
619
 
527
620
  replaceEnv := func(name, value string) []string {
528
621
  env := append([]string(nil), baseEnv...)
@@ -13,9 +13,10 @@ This project has DevRites installed for both Claude Code and Codex.
13
13
  - Before using any DevRites workflow skill, read `.agents/skills/devrites-lib/reference/standards/core.md`. Load other `.agents/skills/devrites-lib/reference/standards/*.md` files when the skill or rule index asks for them. These are DevRites engineering standards, not Codex exec-policy `.rules` files.
14
14
  - Custom Codex subagents generated from the DevRites review agents live in `.codex/agents`.
15
15
  - In DevRites guidance, **invoke** means run a skill inline in the current context; **dispatch** means start a fresh agent with `spawn_agent`, wait for it, and reconcile its result.
16
- - For a DevRites dispatch, first use the named `devrites-<role>` custom role. If a read-only role is unavailable but `spawn_agent` still works, use generic `explorer` only when the host proves runtime-enforced read-only sandboxing; tell it to read `.codex/agents/devrites-<role>.toml` before executing the unchanged packet.
17
- - Do not use generic `worker` for the wright unless exact DevRites identity and `.wright-allowlist` enforcement are proven. Codex exposes that fallback as `agent_type=worker`, which the generated leaf hooks intentionally do not treat as a declared DevRites run. Reject the unsafe worker rung and use the documented labelled inline `.reconcile-inline` path with full reconciliation.
18
- - Other inline work is allowed only when no spawn primitive exists or higher-priority policy rejects a safe spawn; label it `independence: fallback`, never independent. A missing read-only custom role alone is not such a rejection, but an unconfined generic explorer is.
16
+ - Inspect the current `spawn_agent` role list. Use an exposed named `devrites-<role>` with `fork_turns="none"`; full-history forks inherit the parent type.
17
+ - If a named role is not exposed, use generic `explorer` for read-only work with `fork_turns="none"` and tell it to read `.codex/agents/devrites-<role>.toml`. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer guard.
18
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch it with `fork_turns="none"`, the unchanged packet, and `.codex/agents/devrites-slice-wright.toml`.
19
+ - A missing custom role is not evidence that spawning is unavailable. Use the labelled inline `.reconcile-inline` path only when project hooks are unavailable or untrusted, spawning is unavailable, or higher-priority policy rejects the safe rung.
19
20
  - Claude Code agent hook metadata is not active in Codex. The generated Codex agents preserve read-only intent with Codex sandbox settings where possible; still follow DevRites' scope and no-mutation rules explicitly.
20
21
 
21
22
  ## Workflow contract
@@ -25,6 +25,21 @@
25
25
  "statusMessage": "DevRites: checking build write boundary"
26
26
  }
27
27
  ]
28
+ },
29
+ {
30
+ "matcher": "Bash|Shell|sh|exec_command|run_command|Edit|Write|MultiEdit|NotebookEdit|apply_patch|exec|js|python|computer|computer_use|write_stdin|run_code|Agent|Task|spawn_agent|delegate|dispatch_agent|create_agent",
31
+ "hooks": [
32
+ {
33
+ "type": "command",
34
+ "command": "payload=\"$(cat)\"; if ! command -v devrites-engine >/dev/null 2>&1; then if printf '%s' \"$payload\" | grep -Eq '\"agent_type\"[[:space:]]*:[[:space:]]*\"(explorer|worker)\"'; then printf '%s\\n' 'DevRites: generic Codex leaf guard unavailable; install or repair devrites-engine. (devrites-codex-generic-guard)' >&2; exit 2; fi; exit 0; fi; cd \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)\" 2>/dev/null || { printf '%s\\n' 'DevRites: cannot resolve the project root for a generic Codex leaf. (devrites-codex-generic-guard)' >&2; exit 2; }; printf '%s' \"$payload\" | DEVRITES_CODEX_GENERIC_AGENT_COMPAT=1 devrites-engine hook reviewer-readonly --harness=codex; rc=$?; case \"$rc\" in 0) exit 0 ;; 2) exit 2 ;; *) printf '%s\\n' 'DevRites: generic Codex reviewer guard unavailable or crashed; install or repair devrites-engine. (devrites-codex-generic-guard)' >&2; exit 2 ;; esac",
35
+ "statusMessage": "DevRites: checking generic reviewer boundary"
36
+ },
37
+ {
38
+ "type": "command",
39
+ "command": "payload=\"$(cat)\"; if ! command -v devrites-engine >/dev/null 2>&1; then if printf '%s' \"$payload\" | grep -Eq '\"agent_type\"[[:space:]]*:[[:space:]]*\"(explorer|worker)\"'; then printf '%s\\n' 'DevRites: generic Codex leaf guard unavailable; install or repair devrites-engine. (devrites-codex-generic-guard)' >&2; exit 2; fi; exit 0; fi; cd \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)\" 2>/dev/null || { printf '%s\\n' 'DevRites: cannot resolve the project root for a generic Codex leaf. (devrites-codex-generic-guard)' >&2; exit 2; }; printf '%s' \"$payload\" | DEVRITES_CODEX_GENERIC_AGENT_COMPAT=1 devrites-engine hook wright-scope --harness=codex; rc=$?; case \"$rc\" in 0) exit 0 ;; 2) exit 2 ;; *) printf '%s\\n' 'DevRites: generic Codex wright guard unavailable or crashed; install or repair devrites-engine. (devrites-codex-generic-guard)' >&2; exit 2 ;; esac",
40
+ "statusMessage": "DevRites: checking generic wright boundary"
41
+ }
42
+ ]
28
43
  }
29
44
  ],
30
45
  "PostToolUse": [
@@ -11,10 +11,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
11
11
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
12
12
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
13
13
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
14
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
16
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
17
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
14
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
16
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
17
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
18
18
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
19
19
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
20
20
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -12,10 +12,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
12
12
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
13
13
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
14
14
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
15
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
16
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
17
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
18
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
15
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
16
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
17
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
18
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
19
19
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
20
20
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
21
21
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -11,10 +11,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
11
11
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
12
12
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
13
13
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
14
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
16
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
17
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
14
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
16
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
17
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
18
18
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
19
19
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
20
20
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -11,10 +11,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
11
11
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
12
12
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
13
13
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
14
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
16
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
17
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
14
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
16
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
17
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
18
18
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
19
19
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
20
20
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -11,10 +11,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
11
11
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
12
12
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
13
13
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
14
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
16
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
17
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
14
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
16
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
17
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
18
18
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
19
19
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
20
20
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -11,10 +11,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
11
11
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
12
12
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
13
13
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
14
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
16
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
17
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
14
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
16
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
17
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
18
18
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
19
19
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
20
20
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -11,10 +11,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
11
11
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
12
12
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
13
13
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
14
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
16
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
17
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
14
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
16
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
17
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
18
18
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
19
19
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
20
20
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -12,10 +12,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
12
12
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
13
13
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
14
14
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
15
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
16
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
17
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
18
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
15
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
16
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
17
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
18
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
19
19
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
20
20
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
21
21
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -11,10 +11,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
11
11
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
12
12
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
13
13
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
14
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
16
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
17
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
14
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
16
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
17
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
18
18
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
19
19
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
20
20
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -11,10 +11,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
11
11
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
12
12
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
13
13
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
14
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
16
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
17
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
14
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
16
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
17
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
18
18
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
19
19
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
20
20
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.
@@ -11,10 +11,10 @@ This is the Codex mirror of a DevRites skill. In Codex:
11
11
  - Load DevRites engineering standards from `.agents/skills/devrites-lib/reference/standards/`. Read `.agents/skills/devrites-lib/reference/standards/core.md` before workflow work, then load the other `.agents/skills/devrites-lib/reference/standards/*.md` files exactly when this skill asks for them.
12
12
  - Use the installed `devrites-engine` binary as the canonical runtime helper surface for orientation, gates, and state mutation.
13
13
  - **Invocation and dispatch are different:** invoke means run a skill in this context; dispatch means start a fresh agent with `spawn_agent`, await it, and reconcile its result. Never describe inline skill work as a dispatch.
14
- - For every DevRites specialist or writer dispatch, first call `spawn_agent` with the named `devrites-<role>` custom role. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
- - If `spawn_agent` is callable but a named read-only role is unavailable, use generic `explorer` only when the host proves that run has a runtime-enforced read-only sandbox. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. A missing read-only custom role is not evidence that spawning is unavailable.
16
- - Never dispatch generic `worker` for `devrites-slice-wright` unless the host proves that worker run carries exact DevRites identity and the same `.wright-allowlist` enforcement as the named role. Codex reports a generic run as `agent_type=worker`, so the generated global hooks cannot prove that binding. Reject that unsafe rung and use the documented labelled inline wright path with `.reconcile-inline` plus the full reconcile gate.
17
- - If the host cannot prove the generic explorer is runtime read-only, reject that rung too. Only when no spawn primitive exists or a higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, and apply every fallback risk gate. An unbound generic wright or unconfined generic explorer is such a safety rejection, not evidence that no agents exist.
14
+ - Inspect the current `spawn_agent` role list. When the named `devrites-<role>` is exposed, dispatch it with `fork_turns="none"`; full-history forks inherit the parent type. The matching project contract is `.codex/agents/devrites-<role>.toml`.
15
+ - If a named role is not exposed, use generic `explorer` for every read-only role with `fork_turns="none"`. Tell it to read `.codex/agents/devrites-<role>.toml`, follow its `developer_instructions`, and execute the unchanged packet. Trusted `.codex/hooks.json` binds `agent_type=explorer` to the fail-closed reviewer read-only guard.
16
+ - For `devrites-slice-wright`, trusted `.codex/hooks.json` binds generic `worker` (`agent_type=worker`) to the active reconcile window and exact `.wright-allowlist`. Dispatch that worker with `fork_turns="none"`, tell it to read `.codex/agents/devrites-slice-wright.toml`, and execute the unchanged packet. Never create `.reconcile-inline` when this safe rung is available.
17
+ - A missing custom role is not evidence that spawning is unavailable. Only when the project hooks are unavailable or untrusted, no spawn primitive exists, or higher-priority policy rejects a safe spawn may the root run the documented discipline inline. Label it `independence: fallback`, never call it independent, create `.reconcile-inline` only for that path, and apply every fallback risk gate.
18
18
  - Wait for every required fresh-context dispatch before reconciling or advancing. A backgrounded or lost result is incomplete.
19
19
  - Codex project hooks are installed in `.codex/hooks.json`; declared-leaf hooks are scoped inside `.codex/agents/devrites-*.toml`. Review and trust them with `/hooks` before relying on hook enforcement.
20
20
  - When this skill asks a HITL question via `AskUserQuestion`: Codex's equivalent (`request_user_input`) exists only in Plan mode. Outside Plan mode, render the option set as a plain numbered list in chat and **end the turn** so the human answers: NEVER silently pick an option yourself; auto-picking is AFK's contract, gated by the `.devrites/AFK` sentinel.