sneakoscope 1.20.2 → 1.20.4

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 (43) hide show
  1. package/README.md +7 -3
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/.sks-build-stamp.json +4 -4
  6. package/dist/bin/sks.js +1 -1
  7. package/dist/build-manifest.json +13 -9
  8. package/dist/cli/command-registry.d.ts +2 -0
  9. package/dist/cli/command-registry.js +1 -0
  10. package/dist/commands/mad-sks.d.ts +5 -0
  11. package/dist/core/agents/agent-orchestrator.js +1 -1
  12. package/dist/core/agents/fast-mode-policy.d.ts +28 -1
  13. package/dist/core/agents/fast-mode-policy.js +71 -3
  14. package/dist/core/commands/fast-mode-command.d.ts +28 -0
  15. package/dist/core/commands/fast-mode-command.js +81 -0
  16. package/dist/core/commands/mad-sks-command.d.ts +5 -0
  17. package/dist/core/commands/mad-sks-command.js +2 -0
  18. package/dist/core/commands/run-command.js +27 -1
  19. package/dist/core/feature-fixtures.js +4 -0
  20. package/dist/core/feature-registry.js +4 -2
  21. package/dist/core/fsx.d.ts +1 -1
  22. package/dist/core/fsx.js +1 -1
  23. package/dist/core/init.js +3 -0
  24. package/dist/core/release/gate-cache.d.ts +5 -0
  25. package/dist/core/release/gate-cache.js +6 -1
  26. package/dist/core/release/gate-manifest.d.ts +2 -0
  27. package/dist/core/release/gate-manifest.js +0 -0
  28. package/dist/core/routes.d.ts +1 -1
  29. package/dist/core/routes.js +18 -1
  30. package/dist/core/safety/mutation-guard.d.ts +1 -0
  31. package/dist/core/safety/mutation-guard.js +25 -2
  32. package/dist/core/safety/side-effect-runtime-report.d.ts +24 -0
  33. package/dist/core/safety/side-effect-runtime-report.js +84 -0
  34. package/dist/core/skills/core-skill-deployment.d.ts +18 -2
  35. package/dist/core/skills/core-skill-deployment.js +39 -10
  36. package/dist/core/version.d.ts +1 -1
  37. package/dist/core/version.js +1 -1
  38. package/dist/core/zellij/zellij-command.d.ts +18 -0
  39. package/dist/core/zellij/zellij-command.js +75 -4
  40. package/dist/core/zellij/zellij-launcher.d.ts +16 -0
  41. package/dist/core/zellij/zellij-launcher.js +16 -3
  42. package/dist/scripts/release-parallel-check.js +6 -0
  43. package/package.json +11 -5
package/README.md CHANGED
@@ -16,7 +16,11 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
16
16
 
17
17
  ## Current Release
18
18
 
19
- SKS **1.20.2** is a stabilization patch that closes the enforcement/integration/execution layers on top of the 1.20.1 infrastructure: a **Mutation Guard** routes genuinely-risky global/config/permission/package mutations through the Requested-Scope Contract + Mutation Ledger (`safety:mutation-callsite-coverage` fails any unguarded, unallowlisted risky call site); `release:check:dynamic:execute` turns the change-aware planner into a real **caching gate runner** (schema v2, real/heavy gates deferred to `release:real-check`, dynamic-only cannot authorize publish); the **Core Skill** deployed snapshot is now read by the route runtime and recorded in `agent-proof-evidence.json` (`selected_core_skill`), with promotions written to the mutation ledger; and `sks doctor` exposes an explicit **`zellij_readiness`** block (`zellij:doctor-readiness`). See `docs/dynamic-release-pipeline.md`.
19
+ SKS **1.20.4** is a targeted `sks --mad` / codex-lb Zellij usability patch: when a background MAD Zellij session launches successfully, SKS now prints the exact `Attach with: ZELLIJ_SOCKET_DIR=... zellij attach ...` command so operators can enter the fresh session without manually reconstructing the socket namespace.
20
+
21
+ SKS **1.20.3** added the macOS Zellij launch fallback and project-local Fast mode control. SKS supplies a short per-user `ZELLIJ_SOCKET_DIR` by default, caps generated session names safely, records `*_command_with_env` attach commands, and classifies `IPC socket path is too long` as `zellij_socket_path_too_long` instead of a generic launch failure. It also adds `sks fast-mode on|off|status|clear`, `$Fast-On`, `$Fast-Off`, and `$Fast-Mode`; saved project preferences are used only when no explicit `--fast`, `--no-fast`, or `--service-tier` flag is present.
22
+
23
+ It carries forward the **1.20.2** stabilization layer: **Mutation Guard** routes genuinely-risky global/config/permission/package mutations through the Requested-Scope Contract + Mutation Ledger (`safety:mutation-callsite-coverage` fails any unguarded, unallowlisted risky call site); `release:check:dynamic:execute` is the real **caching gate runner** (schema v2, real/heavy gates deferred to `release:real-check`, dynamic-only cannot authorize publish); the **Core Skill** deployed snapshot is read by the route runtime and recorded in `agent-proof-evidence.json` (`selected_core_skill`), with promotions written to the mutation ledger; and `sks doctor` exposes an explicit **`zellij_readiness`** block (`zellij:doctor-readiness`). See `docs/dynamic-release-pipeline.md`.
20
24
 
21
25
  SKS **1.20.1** introduces the **SKS Core Skill Engine** — a SkillOpt-style self-evolving skill layer — while locking the harness into a deploy-ready stable build. Skills are the agent's *external, versioned state* (Core Skill Cards): an optimizer proposes **bounded** add/delete/replace edits to a single skill document under a **textual edit budget**, edits are accepted **only on strict held-out improvement**, rejected edits are buffered so they are never retried, and the **deployed snapshot is immutable**. Critically, the optimizer runs only in training/evaluation — the **deployment/inference path reads the deployed snapshot and never makes an extra model call**, and a skill patch can never mutate code/config/package/global files.
22
26
 
@@ -140,7 +144,7 @@ The cleanup contract is policy-backed in `.sneakoscope/policy.json`, but the def
140
144
  - Agent patch queue: [docs/agent-patch-queue.md](docs/agent-patch-queue.md)
141
145
  - Native CLI Session Swarm: [docs/native-cli-session-swarm.md](docs/native-cli-session-swarm.md)
142
146
  - No-subagent scaling: [docs/no-subagent-scaling.md](docs/no-subagent-scaling.md)
143
- - Fast mode default: [docs/fast-mode-default.md](docs/fast-mode-default.md)
147
+ - Fast mode default and `$Fast-On`/`$Fast-Off` toggles: [docs/fast-mode-default.md](docs/fast-mode-default.md)
144
148
  - Migration 1.18.7 to 1.18.8: [docs/migration-1.18.7-to-1.18.8.md](docs/migration-1.18.7-to-1.18.8.md)
145
149
  - Codex official Goal mode: [docs/codex-official-goal-mode.md](docs/codex-official-goal-mode.md)
146
150
  - Release parallel full coverage: [docs/release-parallel-full-coverage.md](docs/release-parallel-full-coverage.md)
@@ -731,7 +735,7 @@ npm run release:check
731
735
  npm run publish:dry
732
736
  ```
733
737
 
734
- `release:check` runs the 1.19.0 Zellij dependency-repair closure DAG, writes a source digest stamp under `.sneakoscope/reports/`, then refreshes release readiness so publish commands can verify the same stamp. The DAG preserves the 1.18 baseline gates and adds patch swarm runtime truth, transaction journaling, serial conflict rebase, strict strategy-to-patch proof, rollback command proof, Native CLI Session Swarm 5/10/20-process proof, Real Worker Backend Router proof, Codex child overlap proof, model-authored patch-envelope separation, Zellij layout/pane/screen proof, no-subagent-scaling proof, Fast mode default/worker/Codex/MAD propagation proof, Appshots attachment provenance, MCP runtime overlap evidence, Codex 0.134/0.135 runner truth, task graph expansion, schema-bound follow-up work, actual Agent/Team/Research/QA route blackboxes, scheduler proof hardening, Source Intelligence propagation, and Goal mode propagation checks. Broader live gates remain explicit scripts such as `release:real-check`; real Codex patch smoke, real Codex parallel worker proof, and real Zellij proof are optional unless their `SKS_REQUIRE_REAL_*` or `SKS_REQUIRE_ZELLIJ=1` environment variables are set. Generate the human-readable registry with `sks features inventory --write-docs`. Plain `npm publish` uses the `latest` dist-tag. npm's `prepublishOnly` verifies the fresh release stamp instead of rerunning the full gate, and `prepack` only rebuilds `dist`; publish no longer repeats the expensive release suite during packaging. `npm run publish:dry` remains the explicit dry-run helper.
738
+ `release:check` runs the current 1.20.x release-closure DAG, writes a source digest stamp under `.sneakoscope/reports/`, then refreshes release readiness so publish commands can verify the same stamp. The DAG preserves the 1.18 baseline gates and adds patch swarm runtime truth, transaction journaling, serial conflict rebase, strict strategy-to-patch proof, rollback command proof, Native CLI Session Swarm 5/10/20-process proof, Real Worker Backend Router proof, Codex child overlap proof, model-authored patch-envelope separation, Zellij layout/pane/screen/socket-dir proof, no-subagent-scaling proof, Fast mode default/worker/Codex/MAD propagation proof, Appshots attachment provenance, MCP runtime overlap evidence, Codex 0.134/0.135 runner truth, task graph expansion, schema-bound follow-up work, actual Agent/Team/Research/QA route blackboxes, scheduler proof hardening, Source Intelligence propagation, and Goal mode propagation checks. Broader live gates remain explicit scripts such as `release:real-check`; real Codex patch smoke, real Codex parallel worker proof, and real Zellij proof are optional unless their `SKS_REQUIRE_REAL_*` or `SKS_REQUIRE_ZELLIJ=1` environment variables are set. Generate the human-readable registry with `sks features inventory --write-docs`. Plain `npm publish` uses the `latest` dist-tag. npm's `prepublishOnly` verifies the fresh release stamp instead of rerunning the full gate, and `prepack` only rebuilds `dist`; publish no longer repeats the expensive release suite during packaging. `npm run publish:dry` remains the explicit dry-run helper.
735
739
 
736
740
  Version bumps are manual. Run `sks versioning bump` only when preparing release metadata; SKS will not create `.git/hooks/pre-commit` or auto-bump during ordinary commits.
737
741
 
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "1.20.2"
79
+ version = "1.20.4"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "1.20.2"
3
+ version = "1.20.4"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
4
4
  fn main() {
5
5
  let mut args = std::env::args().skip(1);
6
6
  match args.next().as_deref() {
7
- Some("--version") => println!("sks-rs 1.20.2"),
7
+ Some("--version") => println!("sks-rs 1.20.4"),
8
8
  Some("compact-info") => {
9
9
  let mut input = String::new();
10
10
  let _ = io::stdin().read_to_string(&mut input);
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schema": "sks.dist-build-stamp.v1",
3
3
  "package_name": "sneakoscope",
4
- "package_version": "1.20.2",
5
- "source_digest": "d1ccddca4a2c7be54d3129554ea90f8d07efb093592c1e269399fa0e5b92d3ba",
6
- "source_file_count": 1740,
7
- "built_at_source_time": 1780235613612
4
+ "package_version": "1.20.4",
5
+ "source_digest": "491c4c03f8a989f3ea78aa47b16a937edbd54e653b71ef79b5ce767916df7395",
6
+ "source_file_count": 1750,
7
+ "built_at_source_time": 1780281006481
8
8
  }
package/dist/bin/sks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '1.20.2';
2
+ const FAST_PACKAGE_VERSION = '1.20.4';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--agent' && args[1] === 'worker') {
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "schema": "sks.dist-build.v2",
3
- "version": "1.20.2",
4
- "package_version": "1.20.2",
3
+ "version": "1.20.4",
4
+ "package_version": "1.20.4",
5
5
  "typescript": true,
6
6
  "mjs_runtime_files": 0,
7
- "compiled_file_count": 1016,
8
- "compiled_js_count": 508,
9
- "compiled_dts_count": 508,
10
- "source_digest": "d1ccddca4a2c7be54d3129554ea90f8d07efb093592c1e269399fa0e5b92d3ba",
11
- "source_file_count": 1740,
12
- "source_files_hash": "7484278e30e61755c2158548e697943af09e5a59de7c6b60018a0ac57848c6ec",
13
- "source_list_hash": "7484278e30e61755c2158548e697943af09e5a59de7c6b60018a0ac57848c6ec",
7
+ "compiled_file_count": 1020,
8
+ "compiled_js_count": 510,
9
+ "compiled_dts_count": 510,
10
+ "source_digest": "491c4c03f8a989f3ea78aa47b16a937edbd54e653b71ef79b5ce767916df7395",
11
+ "source_file_count": 1750,
12
+ "source_files_hash": "de93b15a72352d00481b958333ed964bf083563809e3beddfe4e64046720df75",
13
+ "source_list_hash": "de93b15a72352d00481b958333ed964bf083563809e3beddfe4e64046720df75",
14
14
  "src_mjs_runtime_files": 0,
15
15
  "dist_stamp_schema": "sks.dist-build-stamp.v1",
16
16
  "files": [
@@ -442,6 +442,8 @@
442
442
  "core/commands/dfix-command.js",
443
443
  "core/commands/eval-command.d.ts",
444
444
  "core/commands/eval-command.js",
445
+ "core/commands/fast-mode-command.d.ts",
446
+ "core/commands/fast-mode-command.js",
445
447
  "core/commands/gc-command.d.ts",
446
448
  "core/commands/gc-command.js",
447
449
  "core/commands/git-command.d.ts",
@@ -859,6 +861,8 @@
859
861
  "core/safety/mutation-ledger.js",
860
862
  "core/safety/requested-scope-contract.d.ts",
861
863
  "core/safety/requested-scope-contract.js",
864
+ "core/safety/side-effect-runtime-report.d.ts",
865
+ "core/safety/side-effect-runtime-report.js",
862
866
  "core/secret-redaction.d.ts",
863
867
  "core/secret-redaction.js",
864
868
  "core/session/project-namespace.d.ts",
@@ -58,6 +58,7 @@ export declare const COMMANDS: {
58
58
  'dollar-commands': CommandEntry;
59
59
  dollars: CommandEntry;
60
60
  $: CommandEntry;
61
+ 'fast-mode': CommandEntry;
61
62
  commit: CommandEntry;
62
63
  'commit-and-push': CommandEntry;
63
64
  dfix: CommandEntry;
@@ -146,6 +147,7 @@ export declare const TYPED_COMMANDS: {
146
147
  'dollar-commands': CommandEntry;
147
148
  dollars: CommandEntry;
148
149
  $: CommandEntry;
150
+ 'fast-mode': CommandEntry;
149
151
  commit: CommandEntry;
150
152
  'commit-and-push': CommandEntry;
151
153
  dfix: CommandEntry;
@@ -111,6 +111,7 @@ export const COMMANDS = {
111
111
  'dollar-commands': entry('stable', 'List Codex App dollar commands', 'dist/core/commands/basic-cli.js', basicArgs('dollarCommandsCommand')),
112
112
  dollars: entry('stable', 'Alias for dollar-commands', 'dist/core/commands/basic-cli.js', basicArgs('dollarCommandsCommand')),
113
113
  '$': entry('stable', 'Alias for dollar-commands', 'dist/core/commands/basic-cli.js', basicArgs('dollarCommandsCommand')),
114
+ 'fast-mode': entry('stable', 'Toggle SKS Fast mode default for dollar-command routes', 'dist/core/commands/fast-mode-command.js', argsCommand(() => import('../core/commands/fast-mode-command.js'), 'fastModeCommand', 'dist/core/commands/fast-mode-command.js')),
114
115
  commit: entry('stable', 'Create a simple git commit', 'dist/commands/commit.js', directCommand(() => import('../commands/commit.js'), 'dist/commands/commit.js')),
115
116
  'commit-and-push': entry('stable', 'Create a simple git commit and push', 'dist/commands/commit-and-push.js', directCommand(() => import('../commands/commit-and-push.js'), 'dist/commands/commit-and-push.js')),
116
117
  dfix: entry('stable', 'Run DFix diagnose/plan/patch/verify loop', 'dist/core/commands/dfix-command.js', commandArgsCommand(() => import('../core/commands/dfix-command.js'), 'dfixCommand', 'dist/core/commands/dfix-command.js')),
@@ -12,8 +12,13 @@ export declare function run(_command: any, args?: any): Promise<void | {
12
12
  layout_artifact: string;
13
13
  command: string[];
14
14
  launch_command: string[];
15
+ launch_command_with_env: string;
15
16
  background_command: string[];
17
+ background_command_with_env: string;
16
18
  attach_command: string;
19
+ attach_command_with_env: string;
20
+ zellij_socket_dir: string | null;
21
+ zellij_socket_dir_source: import("../core/zellij/zellij-command.js").ZellijSocketDirSource;
17
22
  pane_proof_path: string;
18
23
  pane_proof: {
19
24
  schema: string;
@@ -51,7 +51,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
51
51
  const route = opts.route || '$Agent';
52
52
  const routeCommand = String(opts.routeCommand || defaultRouteCommand(route));
53
53
  const routeBlackboxKind = String(opts.routeBlackboxKind || defaultRouteBlackboxKind(route));
54
- const fastModePolicy = resolveFastModePolicy(opts);
54
+ const fastModePolicy = resolveFastModePolicy({ ...opts, root });
55
55
  const backend = normalizeAgentBackend(opts.backend || (opts.mock ? 'fake' : 'codex-exec'));
56
56
  const maxAgentCount = Number.isFinite(Number(opts.maxAgentCount)) && Number(opts.maxAgentCount) >= 1 ? Math.floor(Number(opts.maxAgentCount)) : MAX_AGENT_COUNT;
57
57
  const realZellij = backend === 'zellij' && opts.real === true;
@@ -1,18 +1,45 @@
1
1
  export declare const FAST_MODE_POLICY_SCHEMA = "sks.fast-mode-policy.v1";
2
2
  export declare const FAST_MODE_PROPAGATION_PROOF_SCHEMA = "sks.fast-mode-propagation-proof.v1";
3
+ export declare const FAST_MODE_PREFERENCE_SCHEMA = "sks.fast-mode-preference.v1";
3
4
  export type AgentServiceTier = 'fast' | 'standard';
5
+ export type FastModePreferenceMode = AgentServiceTier;
4
6
  export interface FastModePolicy {
5
7
  schema: typeof FAST_MODE_POLICY_SCHEMA;
6
8
  generated_at: string;
7
9
  fast_mode: boolean;
8
10
  service_tier: AgentServiceTier;
9
11
  default_fast_mode: true;
10
- disabled_by: 'none' | 'no-fast' | 'service-tier-standard';
12
+ disabled_by: 'none' | 'no-fast' | 'service-tier-standard' | 'preference-standard';
11
13
  explicit_fast: boolean;
12
14
  explicit_no_fast: boolean;
13
15
  explicit_service_tier: AgentServiceTier | null;
16
+ preference_mode: FastModePreferenceMode | null;
17
+ preference_path: string | null;
18
+ preference_source: 'project-state' | null;
19
+ }
20
+ export interface FastModePreference {
21
+ schema: typeof FAST_MODE_PREFERENCE_SCHEMA;
22
+ updated_at: string;
23
+ mode: FastModePreferenceMode;
24
+ fast_mode: boolean;
25
+ service_tier: AgentServiceTier;
26
+ source: string;
14
27
  }
15
28
  export declare function resolveFastModePolicy(input?: any): FastModePolicy;
29
+ export declare function fastModePreferencePath(root?: string): string;
30
+ export declare function readFastModePreferenceSync(root?: string | null): (FastModePreference & {
31
+ path: string;
32
+ }) | null;
33
+ export declare function readFastModePreference(root?: string): Promise<(FastModePreference & {
34
+ path: string;
35
+ }) | null>;
36
+ export declare function writeFastModePreference(root: string | undefined, mode: FastModePreferenceMode, source?: string): Promise<FastModePreference & {
37
+ path: string;
38
+ }>;
39
+ export declare function clearFastModePreference(root?: string): Promise<{
40
+ path: string;
41
+ removed: boolean;
42
+ }>;
16
43
  export declare function fastModeEnv(policy: FastModePolicy): NodeJS.ProcessEnv;
17
44
  export declare function applyFastModeToRoster<T extends Record<string, any>>(roster: T, policy: FastModePolicy): T;
18
45
  export declare function writeFastModePropagationProof(root: string, input?: {
@@ -1,29 +1,85 @@
1
+ import fsSync from 'node:fs';
1
2
  import fs from 'node:fs/promises';
2
3
  import path from 'node:path';
3
4
  import { nowIso, readJson, writeJsonAtomic } from '../fsx.js';
4
5
  export const FAST_MODE_POLICY_SCHEMA = 'sks.fast-mode-policy.v1';
5
6
  export const FAST_MODE_PROPAGATION_PROOF_SCHEMA = 'sks.fast-mode-propagation-proof.v1';
7
+ export const FAST_MODE_PREFERENCE_SCHEMA = 'sks.fast-mode-preference.v1';
6
8
  export function resolveFastModePolicy(input = {}) {
7
9
  const explicitTier = normalizeServiceTier(input.serviceTier ?? input.service_tier, null);
8
10
  const explicitNoFast = input.fastMode === false || input.fast_mode === false || input.noFast === true || input.no_fast === true;
9
11
  const explicitFast = input.fastMode === true || input.fast_mode === true || input.fast === true;
12
+ const preference = explicitNoFast || explicitFast || explicitTier
13
+ ? null
14
+ : readFastModePreferenceSync(input.preferenceRoot || input.preference_root || input.root);
10
15
  const serviceTier = explicitNoFast
11
16
  ? 'standard'
12
17
  : explicitTier === 'standard'
13
18
  ? 'standard'
14
- : 'fast';
19
+ : preference?.mode === 'standard'
20
+ ? 'standard'
21
+ : 'fast';
15
22
  return {
16
23
  schema: FAST_MODE_POLICY_SCHEMA,
17
24
  generated_at: nowIso(),
18
25
  fast_mode: serviceTier === 'fast',
19
26
  service_tier: serviceTier,
20
27
  default_fast_mode: true,
21
- disabled_by: explicitNoFast ? 'no-fast' : serviceTier === 'standard' ? 'service-tier-standard' : 'none',
28
+ disabled_by: explicitNoFast ? 'no-fast' : explicitTier === 'standard' ? 'service-tier-standard' : preference?.mode === 'standard' ? 'preference-standard' : 'none',
22
29
  explicit_fast: explicitFast,
23
30
  explicit_no_fast: explicitNoFast,
24
- explicit_service_tier: explicitTier
31
+ explicit_service_tier: explicitTier,
32
+ preference_mode: preference?.mode || null,
33
+ preference_path: preference?.path || null,
34
+ preference_source: preference ? 'project-state' : null
25
35
  };
26
36
  }
37
+ export function fastModePreferencePath(root = process.cwd()) {
38
+ return path.join(path.resolve(root), '.sneakoscope', 'state', 'fast-mode.json');
39
+ }
40
+ export function readFastModePreferenceSync(root) {
41
+ if (!root)
42
+ return null;
43
+ const file = fastModePreferencePath(root);
44
+ try {
45
+ const parsed = JSON.parse(fsSync.readFileSync(file, 'utf8'));
46
+ const mode = normalizeServiceTier(parsed?.mode ?? parsed?.service_tier, null);
47
+ if (!mode)
48
+ return null;
49
+ return normalizeFastModePreference({ ...parsed, mode }, file);
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }
55
+ export async function readFastModePreference(root = process.cwd()) {
56
+ const file = fastModePreferencePath(root);
57
+ const parsed = await readJson(file, null);
58
+ const mode = normalizeServiceTier(parsed?.mode ?? parsed?.service_tier, null);
59
+ if (!mode)
60
+ return null;
61
+ return normalizeFastModePreference({ ...parsed, mode }, file);
62
+ }
63
+ export async function writeFastModePreference(root = process.cwd(), mode, source = 'sks fast-mode') {
64
+ const normalized = normalizeServiceTier(mode, 'fast') || 'fast';
65
+ const file = fastModePreferencePath(root);
66
+ const preference = {
67
+ schema: FAST_MODE_PREFERENCE_SCHEMA,
68
+ updated_at: nowIso(),
69
+ mode: normalized,
70
+ fast_mode: normalized === 'fast',
71
+ service_tier: normalized,
72
+ source
73
+ };
74
+ await writeJsonAtomic(file, preference);
75
+ return { ...preference, path: file };
76
+ }
77
+ export async function clearFastModePreference(root = process.cwd()) {
78
+ const file = fastModePreferencePath(root);
79
+ const existed = fsSync.existsSync(file);
80
+ await fs.rm(file, { force: true }).catch(() => { });
81
+ return { path: file, removed: existed };
82
+ }
27
83
  export function fastModeEnv(policy) {
28
84
  return {
29
85
  SKS_FAST_MODE: policy.fast_mode ? '1' : '0',
@@ -114,6 +170,18 @@ function normalizeServiceTier(value, fallback = 'fast') {
114
170
  return text;
115
171
  return fallback;
116
172
  }
173
+ function normalizeFastModePreference(parsed, file) {
174
+ const mode = normalizeServiceTier(parsed?.mode ?? parsed?.service_tier, 'fast') || 'fast';
175
+ return {
176
+ schema: FAST_MODE_PREFERENCE_SCHEMA,
177
+ updated_at: typeof parsed?.updated_at === 'string' ? parsed.updated_at : nowIso(),
178
+ mode,
179
+ fast_mode: mode === 'fast',
180
+ service_tier: mode,
181
+ source: typeof parsed?.source === 'string' ? parsed.source : 'unknown',
182
+ path: file
183
+ };
184
+ }
117
185
  function normalizeReasoningProfile(value, policy) {
118
186
  const profile = String(value || 'sks-agent-medium-fast');
119
187
  return policy.fast_mode ? profile.replace(/-standard$/, '-fast') : profile.replace(/-fast$/, '-standard');
@@ -0,0 +1,28 @@
1
+ export declare const FAST_MODE_COMMAND_SCHEMA = "sks.fast-mode-command.v1";
2
+ export declare function fastModeCommand(args?: string[]): Promise<void | {
3
+ schema: string;
4
+ ok: boolean;
5
+ action: "off" | "clear" | "on" | "status";
6
+ root: string;
7
+ state_path: string;
8
+ preference: (import("../agents/fast-mode-policy.js").FastModePreference & {
9
+ path: string;
10
+ }) | null;
11
+ removed: boolean | null;
12
+ fast_mode: boolean;
13
+ service_tier: import("../agents/fast-mode-policy.js").AgentServiceTier;
14
+ disabled_by: "none" | "no-fast" | "service-tier-standard" | "preference-standard";
15
+ policy: import("../agents/fast-mode-policy.js").FastModePolicy;
16
+ dollar_commands: {
17
+ on: string;
18
+ off: string;
19
+ status: string;
20
+ };
21
+ cli_commands: {
22
+ on: string;
23
+ off: string;
24
+ clear: string;
25
+ status: string;
26
+ };
27
+ }>;
28
+ //# sourceMappingURL=fast-mode-command.d.ts.map
@@ -0,0 +1,81 @@
1
+ import path from 'node:path';
2
+ import { flag } from '../../cli/args.js';
3
+ import { printJson } from '../../cli/output.js';
4
+ import { projectRoot } from '../fsx.js';
5
+ import { clearFastModePreference, fastModePreferencePath, readFastModePreference, resolveFastModePolicy, writeFastModePreference } from '../agents/fast-mode-policy.js';
6
+ export const FAST_MODE_COMMAND_SCHEMA = 'sks.fast-mode-command.v1';
7
+ export async function fastModeCommand(args = []) {
8
+ const action = normalizeFastModeAction(args[0]);
9
+ const root = path.resolve(String(readOption(args, '--root', '') || await projectRoot()));
10
+ const statePath = fastModePreferencePath(root);
11
+ let preference = await readFastModePreference(root);
12
+ let removed = null;
13
+ if (action === 'on' || action === 'off') {
14
+ const mode = action === 'on' ? 'fast' : 'standard';
15
+ preference = await writeFastModePreference(root, mode, `sks fast-mode ${action}`);
16
+ }
17
+ else if (action === 'clear') {
18
+ const result = await clearFastModePreference(root);
19
+ removed = result.removed;
20
+ preference = null;
21
+ }
22
+ const policy = resolveFastModePolicy({ root });
23
+ const result = {
24
+ schema: FAST_MODE_COMMAND_SCHEMA,
25
+ ok: true,
26
+ action,
27
+ root,
28
+ state_path: statePath,
29
+ preference,
30
+ removed,
31
+ fast_mode: policy.fast_mode,
32
+ service_tier: policy.service_tier,
33
+ disabled_by: policy.disabled_by,
34
+ policy,
35
+ dollar_commands: {
36
+ on: '$Fast-On',
37
+ off: '$Fast-Off',
38
+ status: '$Fast-Mode'
39
+ },
40
+ cli_commands: {
41
+ on: 'sks fast-mode on',
42
+ off: 'sks fast-mode off',
43
+ clear: 'sks fast-mode clear',
44
+ status: 'sks fast-mode status'
45
+ }
46
+ };
47
+ if (flag(args, '--json'))
48
+ return printJson(result);
49
+ console.log('SKS Fast Mode');
50
+ console.log(`Root: ${root}`);
51
+ console.log(`Status: ${result.fast_mode ? 'on' : 'off'} (service_tier=${result.service_tier})`);
52
+ console.log(`State: ${path.relative(root, statePath)}`);
53
+ if (action === 'on')
54
+ console.log('Saved: fast mode on');
55
+ else if (action === 'off')
56
+ console.log('Saved: fast mode off');
57
+ else if (action === 'clear')
58
+ console.log(`Cleared: ${removed ? 'yes' : 'already default'}`);
59
+ else if (!preference)
60
+ console.log('Preference: default fast');
61
+ console.log('Dollar: $Fast-On | $Fast-Off | $Fast-Mode');
62
+ return result;
63
+ }
64
+ function normalizeFastModeAction(value) {
65
+ const text = String(value || 'status').toLowerCase();
66
+ if (['on', 'enable', 'enabled', 'fast'].includes(text))
67
+ return 'on';
68
+ if (['off', 'disable', 'disabled', 'standard', 'slow'].includes(text))
69
+ return 'off';
70
+ if (['clear', 'default', 'reset'].includes(text))
71
+ return 'clear';
72
+ return 'status';
73
+ }
74
+ function readOption(args = [], name, fallback = null) {
75
+ const index = args.indexOf(name);
76
+ if (index >= 0 && args[index + 1] && !String(args[index + 1]).startsWith('--'))
77
+ return args[index + 1];
78
+ const prefixed = args.find((arg) => String(arg).startsWith(name + '='));
79
+ return prefixed ? prefixed.slice(name.length + 1) : fallback;
80
+ }
81
+ //# sourceMappingURL=fast-mode-command.js.map
@@ -12,8 +12,13 @@ export declare function madHighCommand(args?: any, deps?: any): Promise<void | {
12
12
  layout_artifact: string;
13
13
  command: string[];
14
14
  launch_command: string[];
15
+ launch_command_with_env: string;
15
16
  background_command: string[];
17
+ background_command_with_env: string;
16
18
  attach_command: string;
19
+ attach_command_with_env: string;
20
+ zellij_socket_dir: string | null;
21
+ zellij_socket_dir_source: import("../zellij/zellij-command.js").ZellijSocketDirSource;
17
22
  pane_proof_path: string;
18
23
  pane_proof: {
19
24
  schema: string;
@@ -81,6 +81,8 @@ export async function madHighCommand(args = [], deps = {}) {
81
81
  const launch = await launchMadZellijUi([...cleanArgs, '--workspace', workspace], { ...launchOpts, missionId: madLaunch.mission_id, root: madLaunch.root, cwd: process.cwd(), ledgerRoot: path.join(madLaunch.dir, 'agents'), requireZellij: process.env.SKS_REQUIRE_ZELLIJ === '1' });
82
82
  if (!launch.ok)
83
83
  console.log(`MAD Zellij action: ${formatMadZellijAction(launch)}`);
84
+ else if (launch.attach_command_with_env)
85
+ console.log(`Attach with: ${launch.attach_command_with_env}`);
84
86
  return launch;
85
87
  }
86
88
  function formatMadZellijAction(launch) {
@@ -231,7 +231,7 @@ async function executeRouteCommand(root, route, prompt, { auto = false } = {}) {
231
231
  return routeExecutionResult(route, ['sks', ...commandArgs].join(' '), result, {
232
232
  okStatus: 'completed',
233
233
  trustStatus: 'verified_partial',
234
- executionKind: route.command === '$DB' || route.command === '$Wiki' ? 'safe_deterministic' : 'mock_safe',
234
+ executionKind: route.command === '$DB' || route.command === '$Wiki' || route.command === '$Fast-Mode' ? 'safe_deterministic' : 'mock_safe',
235
235
  });
236
236
  }
237
237
  async function runAutoVerification(root, missionId) {
@@ -344,8 +344,34 @@ function safeRouteExecutionArgs(route, prompt, { auto = false } = {}) {
344
344
  return ['db', 'check', '--sql', 'SELECT 1', '--json'];
345
345
  if (route.command === '$Wiki')
346
346
  return ['wiki', 'refresh', '--json'];
347
+ if (route.command === '$Fast-Mode')
348
+ return ['fast-mode', fastModeActionFromPrompt(prompt), '--json'];
347
349
  return ['team', prompt, '--mock', '--json', ...(auto ? ['--no-open-zellij'] : [])];
348
350
  }
351
+ function fastModeActionFromPrompt(prompt = '') {
352
+ const text = String(prompt || '');
353
+ const lower = text.toLowerCase();
354
+ if (/\$fast-off\b/.test(lower))
355
+ return 'off';
356
+ if (/\$fast-on\b/.test(lower))
357
+ return 'on';
358
+ const routeMatch = /\$fast-mode\b/i.exec(text);
359
+ if (!routeMatch)
360
+ return 'status';
361
+ const afterRoute = text
362
+ .slice(routeMatch.index + routeMatch[0].length)
363
+ .replace(/^[\s:=\-]+/, '')
364
+ .trimStart()
365
+ .toLowerCase();
366
+ const token = afterRoute.match(/^[^\s?!.,;:()"'`]+/)?.[0] || '';
367
+ if (['off', 'disable', 'disabled', 'standard', 'slow', '끄기', '꺼', '꺼줘'].includes(token) || token.startsWith('끄') || token.startsWith('꺼'))
368
+ return 'off';
369
+ if (['on', 'enable', 'enabled', 'fast', '켜기', '켜', '켜줘'].includes(token) || token.startsWith('켜'))
370
+ return 'on';
371
+ if (['clear', 'reset', 'default', '초기화', '기본'].includes(token) || token.startsWith('초기화'))
372
+ return 'clear';
373
+ return 'status';
374
+ }
349
375
  function destructiveDbPrompt(prompt = '') {
350
376
  return /\b(drop|truncate|delete\s+from|update\s+\w+\s+set|reset|db\s+push|disable\s+rls)\b/i.test(prompt);
351
377
  }
@@ -54,6 +54,7 @@ const FIXTURES = Object.freeze({
54
54
  'cli-memory': fixture('execute', 'sks memory --dry-run --json', [], 'pass'),
55
55
  'cli-stats': fixture('execute', 'sks stats --json', [], 'pass'),
56
56
  'cli-dollar-commands': fixture('execute', 'sks dollar-commands --json', [], 'pass'),
57
+ 'cli-fast-mode': fixture('execute', 'sks fast-mode status --json', [], 'pass'),
57
58
  'cli-dfix': fixture('execute_and_validate_artifacts', 'sks dfix fixture --json', ['completion-proof.json', 'dfix-gate.json', 'dfix-verification.json'], 'pass'),
58
59
  'cli-wiki': fixture('execute_and_validate_artifacts', 'sks wiki image-ingest test/fixtures/images/one-by-one.png --json', [{ path: '.sneakoscope/wiki/image-voxel-ledger.json', schema: 'sks.image-voxel-ledger.v1', require_anchors: false }], 'pass'),
59
60
  'cli-db': fixture('execute', 'sks db policy', [], 'pass'),
@@ -106,6 +107,9 @@ const FIXTURES = Object.freeze({
106
107
  'route-wiki': fixture('execute_and_validate_artifacts', 'sks wiki image-ingest test/fixtures/images/one-by-one.png --json', [{ path: 'completion-proof.json', schema: 'sks.completion-proof.v1' }, { path: 'image-voxel-ledger.json', schema: 'sks.image-voxel-ledger.v1' }], 'pass'),
107
108
  'route-gx': fixture('execute_and_validate_artifacts', 'sks gx validate fixture --mock --json', ['completion-proof.json', { path: 'image-voxel-ledger.json', schema: 'sks.image-voxel-ledger.v1' }, 'gx-validation.json'], 'pass'),
108
109
  'route-sks': fixture('mock', '$SKS control-surface route', ['completion-proof.json'], 'pass'),
110
+ 'route-fast-mode': fixture('execute', 'sks fast-mode status --json', [], 'pass'),
111
+ 'route-fast-on': fixture('mock', '$Fast-On covered by hermetic fast-mode blackbox toggle test', [], 'pass'),
112
+ 'route-fast-off': fixture('mock', '$Fast-Off covered by hermetic fast-mode blackbox toggle test', [], 'pass'),
109
113
  'route-help': fixture('mock', '$Help lightweight route', [], 'pass'),
110
114
  'route-commit': fixture('mock', '$Commit git route', ['completion-proof.json'], 'pass'),
111
115
  'route-commit-and-push': fixture('mock', '$Commit-And-Push git route', ['completion-proof.json'], 'pass'),
@@ -479,6 +479,7 @@ const SAFE_EXECUTABLE_FIXTURE_ARGS = Object.freeze({
479
479
  'cli-memory': ['memory', '--dry-run', '--json'],
480
480
  'cli-stats': ['stats', '--json'],
481
481
  'cli-dollar-commands': ['dollar-commands', '--json'],
482
+ 'cli-fast-mode': ['fast-mode', 'status', '--json'],
482
483
  'cli-dfix': ['dfix', 'fixture', '--json'],
483
484
  'cli-all-features': ['all-features', 'complete', '--json'],
484
485
  'route-team': ['team', 'fixture', '--mock', '--json'],
@@ -489,6 +490,7 @@ const SAFE_EXECUTABLE_FIXTURE_ARGS = Object.freeze({
489
490
  'route-image-ux-review': ['image-ux-review', 'fixture', '--mock', '--json'],
490
491
  'route-computer-use': ['computer-use', 'import-fixture', '--mock', '--json'],
491
492
  'route-dfix': ['dfix', 'fixture', '--json'],
493
+ 'route-fast-mode': ['fast-mode', 'status', '--json'],
492
494
  'route-db': ['db', 'check', '--sql', 'SELECT 1', '--json'],
493
495
  'route-wiki': ['wiki', 'image-ingest', 'test/fixtures/images/one-by-one.png', '--json'],
494
496
  'route-gx': ['gx', 'validate', 'fixture', '--mock', '--json']
@@ -817,14 +819,14 @@ function commandCategory(name) {
817
819
  return 'core-cli';
818
820
  }
819
821
  function commandMaturity(name) {
820
- if (['help', 'version', 'commands', 'usage', 'root', 'quickstart', 'setup', 'doctor', 'selftest', 'update-check'].includes(name))
822
+ if (['help', 'version', 'commands', 'usage', 'root', 'quickstart', 'setup', 'doctor', 'selftest', 'update-check', 'fast-mode'].includes(name))
821
823
  return 'stable';
822
824
  if (['codex', 'codex-app', 'codex-lb', 'hooks', 'features', 'all-features', 'wiki', 'wrongness', 'team', 'pipeline', 'goal', 'db', 'guard'].includes(name))
823
825
  return 'beta';
824
826
  return 'labs';
825
827
  }
826
828
  function routeMaturity(command) {
827
- if (['$Answer', '$DFix', '$SKS', '$Wiki', '$Help'].includes(command))
829
+ if (['$Answer', '$DFix', '$SKS', '$Fast-Mode', '$Wiki', '$Help'].includes(command))
828
830
  return 'stable';
829
831
  if (['$Team', '$Goal', '$DB', '$Computer-Use', '$CU', '$QA-LOOP', '$MAD-SKS'].includes(command))
830
832
  return 'beta';
@@ -1,4 +1,4 @@
1
- export declare const PACKAGE_VERSION = "1.20.2";
1
+ export declare const PACKAGE_VERSION = "1.20.4";
2
2
  export declare const DEFAULT_PROCESS_TAIL_BYTES: number;
3
3
  export declare const DEFAULT_PROCESS_TIMEOUT_MS: number;
4
4
  export interface RunProcessOptions {
package/dist/core/fsx.js CHANGED
@@ -5,7 +5,7 @@ import os from 'node:os';
5
5
  import crypto from 'node:crypto';
6
6
  import { spawn } from 'node:child_process';
7
7
  import { fileURLToPath } from 'node:url';
8
- export const PACKAGE_VERSION = '1.20.2';
8
+ export const PACKAGE_VERSION = '1.20.4';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11
  export function nowIso() {
package/dist/core/init.js CHANGED
@@ -1035,6 +1035,9 @@ export async function installSkills(root) {
1035
1035
  'dfix': `---\nname: dfix\ndescription: Direct Fix mode for $DFix or $dfix requests and inferred tiny copy/config/docs/labels/spacing/translation/simple mechanical edits.\n---\n\nUse for tiny copy/config/docs/labels/spacing/translation/simple mechanical edits. List exact micro-edits, inspect only needed files, apply only those edits, and run cheap verification. Keep broad implementation routed to Team; for UI/UX micro-edits read \`design.md\` when present and use imagegen for image/logo/raster assets. Bypass broad SKS routing, mission state, TriWiki/TriFix/reflection/state recording, Goal, Research, eval, redesign, and repeated full-route Honest Mode loops. Start the final answer with \`DFix 완료 요약:\` and include one \`DFix 솔직모드:\` line covering verified, not verified, and remaining issues. ${CODEX_IMAGEGEN_REQUIRED_POLICY}\n`,
1036
1036
  'answer': `---\nname: answer\ndescription: Answer-only research route for ordinary questions that should not start implementation.\n---\n\nUse for explanations, comparisons, status, facts, source-backed research, or docs guidance. Use repo/TriWiki first for project-local facts; hydrate low-trust claims from source. Browse or use Context7 for current external package/API/framework/MCP docs. End with a concise answer summary plus Honest Mode; do not create missions, subagents, or file edits.\n`,
1037
1037
  'sks': `---\nname: sks\ndescription: General Sneakoscope Codex command route for $SKS or $sks usage, setup, status, and workflow help.\n---\n\nUse local SKS commands: bootstrap, deps, commands, quickstart, codex-app, context7, guard, conflicts, reasoning, wiki, pipeline status, pipeline plan, skill-dream. Promote code-changing work to Team unless Answer/DFix/Help/Wiki/safety route fits. Surface route/guard/scope, use TriWiki, do not edit installed harness files outside this engine repo, and require human-approved conflict cleanup. ${skillDreamPolicyText()}\n`,
1038
+ 'fast-mode': `---\nname: fast-mode\ndescription: Dollar-command route for $Fast-Mode, $Fast-On, and $Fast-Off project-local Fast mode toggles.\n---\n\nUse when the user invokes $Fast-Mode, $Fast-On, $Fast-Off, or asks to turn SKS Fast mode on/off for dollar commands. Prefer \`sks fast-mode on|off|status|clear --json\`. The command writes only .sneakoscope/state/fast-mode.json in the active project. Explicit runtime flags still win: \`--fast\`, \`--no-fast\`, and \`--service-tier standard|fast\` override the saved preference for that run. Finish with a short status and Honest Mode; do not start Team or broad implementation for a toggle-only request.\n`,
1039
+ 'fast-on': `---\nname: fast-on\ndescription: Alias for $Fast-On project-local SKS Fast mode enablement.\n---\n\nUse the same rules as fast-mode. Run or instruct \`sks fast-mode on --json\`, then report the active state, state file, and the fact that explicit per-run flags still override the saved preference.\n`,
1040
+ 'fast-off': `---\nname: fast-off\ndescription: Alias for $Fast-Off project-local SKS Fast mode disablement.\n---\n\nUse the same rules as fast-mode. Run or instruct \`sks fast-mode off --json\`, then report the active state, state file, and the fact that explicit per-run flags still override the saved preference.\n`,
1038
1041
  'wiki': `---\nname: wiki\ndescription: Dollar-command route for $Wiki TriWiki refresh, pack, validate, and prune commands.\n---\n\nUse for $Wiki or Korean wiki-refresh requests. Refresh/update/갱신: run sks wiki refresh, then validate .sneakoscope/wiki/context-pack.json. Pack: run sks wiki pack, then validate. Prune/clean/정리: use sks wiki refresh --prune, or sks wiki prune --dry-run for inspection. Report claims, anchors, trust, attention.use_first/hydrate_first, validation, and blockers. Do not start ambiguity-gated implementation, subagents, or unrelated work.\n`,
1039
1042
  'team': `---\nname: team\ndescription: SKS Team orchestration for $Team/code work; $From-Chat-IMG is the explicit chat-image alias.\n---\n\nUse for $Team/code work. Auto-seal the route contract from prompt, TriWiki/current-code defaults, and conservative policy; do not surface a prequestion sheet. Read pipeline-plan.json or run sks pipeline plan to see the runtime lane, kept/skipped stages, and verification before implementation. Write team-roster.json; team-gate.json needs team_roster_confirmed=true. executor:N means N native analysis agents, N debate voices, then fresh N executors. ${MIN_TEAM_REVIEW_POLICY_TEXT} After consensus, compile team-graph.json, team-runtime-tasks.json, team-decomposition-report.json, and team-inbox/ so worker handoff uses concrete runtime task ids with role/path/domain/lane hints. Refresh/validate TriWiki before debate, implementation, review, and final; consume attention.use_first and hydrate attention.hydrate_first before risky decisions. ${outcomeRubricPolicyText()} ${speedLanePolicyText()} ${solutionScoutPolicyText('fix this broken behavior')} ${skillDreamPolicyText()} Log events and use sks team message for bounded inter-agent communication in transcript/lane panes. Color-coded Zellij lanes distinguish overview/native-analysis/planning/execution/review/safety sessions in one Zellij window using split panes when Zellij is available. $Team/$team plus sks --mad uses the MAD-SKS permission gate module: user-authorized target-project scopes such as files, shell, packages, services, network, browser/Computer Use, generated assets, file permissions, migrations, normal DB writes, Supabase MCP writes, direct SQL, and schema cleanup are open only for the active invocation; catastrophic wipe/all-row/project-management, credential exfiltration, persistent security weakening, and unrequested fallback guards remain. End with cleanup-zellij or a cleanup event so follow panes show cleanup and stop; pass team-session-cleanup.json, then reflection and Honest Mode. Parent integrates/verifies.\n\n${chatCaptureIntakeText()}\n`,
1040
1043
  'from-chat-img': `---\nname: from-chat-img\ndescription: Explicit $From-Chat-IMG Team alias for chat screenshot plus attachment analysis.\n---\n\nUse only for From-Chat-IMG/$From-Chat-IMG. It enters the normal Team pipeline. Treat uploads as chat screenshot plus originals. For web/browser/webapp targets use Codex Chrome Extension first; for native Mac/non-web app surfaces use Codex Computer Use visual inspection when available. List requirements first, match regions to attachments with confidence, write ${FROM_CHAT_IMG_COVERAGE_ARTIFACT}, ${FROM_CHAT_IMG_CHECKLIST_ARTIFACT}, ${FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT}, and ${FROM_CHAT_IMG_QA_LOOP_ARTIFACT}, then continue Team gates, review, reflection, and Honest Mode. ${CODEX_WEB_VERIFICATION_POLICY} ${CODEX_COMPUTER_USE_ONLY_POLICY} The ledger must account for every visible customer request, screenshot image region, and separate attachment; ${FROM_CHAT_IMG_CHECKLIST_ARTIFACT} must have a checked item for each request, image-region/attachment match, work item, scoped QA-LOOP, and verification step; ${FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT} stores temporary TriWiki-backed session context with expires_after_sessions=${FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS}. ${FROM_CHAT_IMG_QA_LOOP_ARTIFACT} must prove QA-LOOP ran over the exact customer-request work-order range after implementation, with every work item covered, post-fix verification complete, and zero unresolved findings. team-gate.json cannot pass From-Chat-IMG completion until unresolved_items is empty, every checklist box is checked, and scoped_qa_loop_completed=true.\n`,