@awak-app/simy-cli 0.6.22 → 0.6.25

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 (68) hide show
  1. package/README.md +71 -0
  2. package/package.json +3 -3
  3. package/src/backend-executable.js +75 -7
  4. package/src/cli-contract.js +9 -1
  5. package/src/codex-plugins/simy/hooks/acceptance-policy.mjs +5 -0
  6. package/src/codex-plugins/simy/hooks/delivery-loop.mjs +533 -74
  7. package/src/codex-plugins/simy/hooks/dev-work.mjs +23 -1
  8. package/src/codex-plugins/simy/hooks/purpose-cycle.mjs +63 -0
  9. package/src/codex-plugins/simy/hooks/purpose-evidence.mjs +154 -0
  10. package/src/codex-plugins/simy/hooks/purpose-rule-policy.mjs +34 -0
  11. package/src/codex-plugins/simy/hooks/purpose-rule-review.mjs +65 -0
  12. package/src/codex-plugins/simy/hooks/purpose-search.mjs +123 -0
  13. package/src/codex-plugins/simy/hooks/purpose-workspace.mjs +97 -0
  14. package/src/codex-plugins/simy/skills/delivery-loop/SKILL.md +19 -5
  15. package/src/codex-plugins/simy/skills/sqm-loop/SKILL.md +19 -4
  16. package/src/delivery-hooks/command.js +48 -0
  17. package/src/delivery-hooks/consistency-monitor.js +126 -0
  18. package/src/delivery-hooks/desktop-runtime.js +70 -0
  19. package/src/delivery-hooks/desktop.js +13 -3
  20. package/src/delivery-hooks/legacy-hook-routing.js +61 -0
  21. package/src/delivery-hooks/local-runtime.js +123 -0
  22. package/src/delivery-hooks/local-supervisor.js +25 -0
  23. package/src/delivery-hooks/runtime-watchdog.js +101 -0
  24. package/src/delivery-hooks/supervisor.js +90 -22
  25. package/src/desktop-host.js +45 -4
  26. package/src/desktop-status.js +4 -2
  27. package/src/dev-work-events.js +32 -3
  28. package/src/durable-local-task-worker.js +57 -12
  29. package/src/fp-narrative-image.js +180 -0
  30. package/src/index.js +1 -1
  31. package/src/local-task.js +4 -0
  32. package/src/orchestrator/audit.js +1 -1
  33. package/src/orchestrator/charter-repair.js +93 -0
  34. package/src/orchestrator/charter-validation.js +14 -6
  35. package/src/orchestrator/checklist-continuation.js +1 -1
  36. package/src/orchestrator/contract.js +1 -3
  37. package/src/orchestrator/delivery/WORKFLOW.md +33 -60
  38. package/src/orchestrator/delivery/controls/harness-controls.json +1326 -0
  39. package/src/orchestrator/delivery/references/delivery-levels.md +17 -44
  40. package/src/orchestrator/delivery/references/pr-closure.md +2 -3
  41. package/src/orchestrator/delivery/references/state-and-receipts.md +14 -5
  42. package/src/orchestrator/delivery/references/ux-specification.md +1 -2
  43. package/src/orchestrator/delivery-level.js +4 -5
  44. package/src/orchestrator/independent-audit.js +9 -5
  45. package/src/orchestrator/instruction.js +1 -0
  46. package/src/orchestrator/loop.js +55 -18
  47. package/src/orchestrator/risk.js +1 -1
  48. package/src/orchestrator/ux-specification.js +2 -2
  49. package/src/runner.js +22 -1
  50. package/src/session-supervision/analysis-manager.js +2 -2
  51. package/src/session-supervision/automatic-continuation.js +6 -5
  52. package/src/session-supervision/autonomous-upgrade.js +55 -0
  53. package/src/session-supervision/codex-app-server.js +200 -24
  54. package/src/session-supervision/consistency-auditor.js +113 -0
  55. package/src/session-supervision/index.js +38 -11
  56. package/src/session-supervision/purpose-candidate.js +44 -0
  57. package/src/session-supervision/purpose-instruction.js +47 -0
  58. package/src/session-supervision/purpose-observer.js +172 -0
  59. package/src/session-supervision/purpose-recovery.js +264 -0
  60. package/src/session-supervision/purpose-verification.js +154 -0
  61. package/src/sqm/agent-skill.js +6 -3
  62. package/src/sqm/artifact-paths.js +39 -0
  63. package/src/sqm/claude-plugin.js +7 -0
  64. package/src/sqm/command.js +95 -27
  65. package/src/sqm/history-store.js +3 -3
  66. package/src/sqm/repository.js +19 -5
  67. package/src/sqm/workflow-update.js +14 -0
  68. package/src/workflow-reporting.js +2 -0
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # SIMY CLI
2
2
 
3
+ ローカルDelivery Loopの0.6.24候補を版固定で実行するには、[ローカル候補版のインストール・実行](docs/local-delivery-runtime.md)を参照してください。
4
+
3
5
  Local execution agent for SIMY Local Tasks and Agentic Loop runs.
4
6
 
5
7
  Action candidate search runs once for each authenticated live conversation context,
@@ -236,6 +238,15 @@ SQM checks apply when you explicitly select `@simy`, invoke the SQM skill, or as
236
238
  After installation, restart Codex and find and install **SIMY** in **Plugins**
237
239
  before using `@simy` in a new task.
238
240
 
241
+ If **Connect SIMY** fails while the CLI is already signed in, check the recovery
242
+ message in connection settings. Finish or retry a pending SIMY update, or complete
243
+ or cancel an organization selection. If SIMY remains paused, use **SIMY → Quit
244
+ SIMY**, reopen it, and reconnect; closing the window alone does not restart the
245
+ background host. Refresh connections and confirm the conversation list returns.
246
+ Diagnostic `provider connection failed` entries distinguish `reason=update`,
247
+ `organization_change`, and `shutdown` without including credentials or transcripts.
248
+ Reconnection does not sign in to Codex CLI or restore revoked automatic continuation.
249
+
239
250
  The plugin also includes a non-blocking connection reminder. At task startup,
240
251
  resume, and prompt submission it reads the origin-scoped local discovery record
241
252
  and checks the loopback CLI health endpoint. It warns once per disconnected
@@ -593,6 +604,15 @@ preflight and returns the installed version, required version, and a recovery
593
604
  command to SIMY Web. Update Codex with
594
605
  `npm install -g @openai/codex@latest`; update Claude Code with `claude update`.
595
606
 
607
+ Codex discovery compares installed CLI versions across PATH (including shadowed
608
+ installs) and the known Codex/ChatGPT app bundles on macOS, selecting the newest
609
+ compatible version. Equal versions retain discovery order. A compatible
610
+ `SIMY_CODEX_BIN` override retains priority; a broken or unsupported override falls
611
+ back to automatic discovery. Refresh the connection status after updating Codex;
612
+ each new inspection checks installed versions again. SIMY does not download or
613
+ replace Codex. The desktop connection status and Codex conversation reader both
614
+ require `0.158.0` or later for the verified app-server writer-lock protocol.
615
+
596
616
  ## Your Desktop executor
597
617
 
598
618
  SIMY CLI is the `desktop` execution target, shown to users as **Your Desktop**.
@@ -909,6 +929,19 @@ To-Be and PR reviews, plus explicitly opted-in SQM before and after PR creation.
909
929
  The [workflow reference](src/orchestrator/delivery/references/shared-system-specifications.md)
910
930
  explains baseline updates, historical regression coverage and evidence limits.
911
931
 
932
+ ## Purpose-driven automatic continuation
933
+
934
+ The desktop **Continue automatically / 自動で続ける** switch enables purpose-driven
935
+ search: hypotheses, research, experiments, minimal implementation and independent
936
+ outcome review. Failed methods trigger replanning; review findings return to repair.
937
+ Independent authorized work can continue while a controller-tracked operation waits.
938
+ The existing Codex auto-continue switch enables read-only diagnosis for uncertain or
939
+ information-waiting conversations, then assessed work. No default time/turn cap is
940
+ added; explicitly enrolled purpose budgets and user stops are preserved. Native
941
+ provider approval waits still require the original provider boundary to settle.
942
+ Workflow rules are reassessed throughout. Turning the switch off pauses work.
943
+ Actual permissions, user stops and total budgets remain enforced. See the
944
+ [contract and limitations](docs/purpose-driven-continuation.md).
912
945
 
913
946
  ### Desktop SQM history
914
947
 
@@ -991,3 +1024,41 @@ Scope mismatch diagnostics identify the changed account, organization, device
991
1024
  or Web host and tell the caller to restore the original identity. Launch and
992
1025
  recovery operations do not switch identity automatically. The private
993
1026
  `/v1/connection` endpoint rejects browser requests and never returns tokens.
1027
+
1028
+ 自律判断の改定方針と人間判断候補の一覧: [AI判断を基本にする改定](docs/ai-decision-policy.md)。LLMの文脈理解・推論・調査を基本にし、HC-01〜HC-102を判断の批判視点として適用します。
1029
+
1030
+ ### Local autonomous recovery (0.6.25)
1031
+
1032
+ `simy delivery runtime install` pins a hash-verified snapshot. `runtime desktop-install`
1033
+ prepares a separately signed **SIMY Local** app from the installed native app; the
1034
+ public application and installer selection remain unchanged. After the previous
1035
+ app has finished its normal quit, `runtime desktop-activate` launches that candidate.
1036
+ `runtime watchdog-install` installs a per-user macOS observer that may relaunch only
1037
+ that explicitly activated candidate when no live desktop owns the state directory.
1038
+ A live unknown/mismatched owner is preserved and reported. `runtime doctor` reports
1039
+ expected versus observed host identity, the all-state consistency monitor, and
1040
+ remaining task findings. `runtime legacy-hooks` routes only the exact shipped
1041
+ 0.6.23/0.6.24 Codex hook entrypoints to the verified pin, retaining originals;
1042
+ customized hooks and trust settings remain unchanged. `runtime workflows` refreshes
1043
+ existing provider workflows without enabling them.
1044
+
1045
+ For existing opted-in Codex tasks, the controller verifies original session, cwd,
1046
+ model, provider link and consent epoch before an idempotent policy migration.
1047
+ Frozen goal, criteria, grants, budgets and failure history are retained. Observable
1048
+ legacy manual criteria receive a separate independent verification route; explicit
1049
+ human/customer acceptance remains manual. Known system no-progress pauses queue
1050
+ read-only diagnosis before any replay. OFF, archive, explicit pause/stop, rejection,
1051
+ unknown effects and original budgets remain boundaries.
1052
+
1053
+ The consistency monitor scans every managed state separately from the execution
1054
+ queue. Its independent AI reads original user instructions/corrections and primary
1055
+ evidence in a distinct read-only Codex context. Durable findings/outbox receipts,
1056
+ retry backoff, separate lease, measured token usage and failed/stale heartbeats are
1057
+ recorded; an audit receipt does not complete a task. SQM evidence stays bound to its
1058
+ repository/commit/diff scope and does not prove the whole user outcome. Git output
1059
+ no longer uses a 10 MiB `execFile` buffer; the full diff is still retained in memory.
1060
+
1061
+ Codex cold recovery and independent audit are supported. Claude retains its
1062
+ original live-hook boundary; cold recovery and detached independent audit are not
1063
+ implemented in this release and are exposed as a capability gap. Neither an
1064
+ unverified original model nor a different provider is substituted automatically.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awak-app/simy-cli",
3
- "version": "0.6.22",
3
+ "version": "0.6.25",
4
4
  "description": "Local SIMY executor for non-coding Local Tasks and Agentic Loop runs.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,7 +12,7 @@
12
12
  ],
13
13
  "scripts": {
14
14
  "start": "node ./src/index.js",
15
- "test": "node --test",
15
+ "test": "node --test --test-concurrency=2",
16
16
  "test:e2e:console": "node ./scripts/console-e2e.js",
17
17
  "test:e2e:work-activity": "node ./scripts/work-activity-e2e.js",
18
18
  "test:e2e:sqm-complete-loop": "node ./scripts/sqm-complete-loop-e2e.js",
@@ -38,7 +38,7 @@
38
38
  "test:e2e:console:real-provider": "node ./scripts/real-provider-console-e2e.js",
39
39
  "test:e2e:console:fullstack": "node ./scripts/fullstack-cli-smoke.js",
40
40
  "check": "npm run check:auto-update && node --check ./src/desktop-executor.js && node --check ./src/local-task.js && node --check ./scripts/desktop-executor-e2e.js && node --check ./scripts/pre-guardrail-e2e.js && node --check ./scripts/fixtures/fake-desktop-provider.js && npm run check:syntax && npm run check:session-supervision-syntax && npm run check:real-provider-syntax && npm test && npm run check:package",
41
- "check:session-supervision-syntax": "node --check ./src/session-supervision/index.js && node --check ./src/session-supervision/discovery-window.js && node --check ./src/session-supervision/codex-app-server.js && node --check ./src/session-supervision/claude-sessions.js && node --check ./src/session-supervision/original-session-target.js && node --check ./src/session-supervision/action-association.js && node --check ./src/session-supervision/action-association-host.js && node --check ./src/session-supervision/action-association-api.js && node --check ./src/session-supervision/association-store.js && node --check ./src/session-supervision/action-deadline.js && node --check ./src/session-supervision/action-deadline-store.js && node --check ./src/codex-plugins/simy/hooks/action-association.mjs",
41
+ "check:session-supervision-syntax": "node --check ./src/session-supervision/index.js && node --check ./src/session-supervision/discovery-window.js && node --check ./src/session-supervision/codex-app-server.js && node --check ./src/session-supervision/claude-sessions.js && node --check ./src/session-supervision/original-session-target.js && node --check ./src/session-supervision/action-association.js && node --check ./src/session-supervision/action-association-host.js && node --check ./src/session-supervision/action-association-api.js && node --check ./src/session-supervision/association-store.js && node --check ./src/session-supervision/action-deadline.js && node --check ./src/session-supervision/action-deadline-store.js && node --check ./src/codex-plugins/simy/hooks/action-association.mjs && node --check ./src/session-supervision/purpose-instruction.js && node --check ./src/session-supervision/purpose-recovery.js && node --check ./src/session-supervision/purpose-candidate.js && node --check ./src/codex-plugins/simy/hooks/purpose-cycle.mjs && node --check ./src/codex-plugins/simy/hooks/purpose-rule-review.mjs && node --check ./src/codex-plugins/simy/hooks/purpose-search.mjs && node --check ./src/codex-plugins/simy/hooks/purpose-evidence.mjs && node --check ./src/session-supervision/purpose-observer.js && node --check ./src/session-supervision/purpose-verification.js && node --check ./src/codex-plugins/simy/hooks/purpose-workspace.mjs && node --check ./scripts/purpose-search-live-e2e.js",
42
42
  "check:auto-update": "node --check ./src/auto-update.js && node --check ./scripts/auto-update-e2e.js && npm run check:sqm",
43
43
  "check:workflow-observation-sender": "node --check ./src/workflow-observation-sender.js",
44
44
  "check:sqm": "node --check ./src/sqm/canonical.js && node --check ./src/sqm/validation.js && node --check ./src/sqm/reliability.js && node --check ./src/sqm/repository.js && node --check ./src/sqm/checkers.js && node --check ./src/sqm/bundle-store.js && node --check ./src/sqm/proof.js && node --check ./src/sqm/evidence-client.js && node --check ./src/sqm/session.js && node --check ./src/sqm/index.js && node --check ./src/sqm/command.js && node --check ./src/sqm/agent-skill.js && node --check ./src/sqm/workflow-onboarding.js && node --check ./src/sqm/workflow-update.js && node --check ./src/sqm/history-store.js && node --check ./src/sqm/review-worker.js && node --check ./scripts/sqm-complete-loop-e2e.js && node --check ./scripts/sqm-local-review-e2e.js",
@@ -32,11 +32,30 @@ export async function inspectBackendExecutable(
32
32
  assertActive();
33
33
  const policy = versionPolicy(backend);
34
34
  const requiredVersion = minimumVersion || policy.minimumVersion;
35
+ const explicitCodex = backend === "codex"
36
+ ? (discoveryOptions.environment ?? process.env).SIMY_CODEX_BIN : null;
35
37
  candidates ??= [...backendCandidates(backend, discoveryOptions), ...await bundledClaudeCandidates(backend, discoveryOptions)];
38
+ candidates = [...new Set(candidates.filter(Boolean))];
36
39
  let fallback = null;
37
- for (const candidate of [...new Set(candidates.filter(Boolean))]) {
40
+ // An intentional override retains priority. Broken or unsupported overrides
41
+ // still fall back to automatic discovery, as before.
42
+ if (explicitCodex && candidates.includes(explicitCodex)) {
43
+ const pinned = await inspectBackendExecutable(backend, {
44
+ candidates: [explicitCodex], spawnImpl, timeoutMs, signal, minimumVersion,
45
+ discoveryOptions: { ...discoveryOptions, environment: {} },
46
+ });
47
+ if (pinned.compatible) return pinned;
48
+ if (pinned.available) fallback = pinned;
49
+ candidates = candidates.filter(candidate => candidate !== explicitCodex);
50
+ }
51
+ // Comparing all Codex installs must not turn several slow wrappers into a
52
+ // serial startup delay. Keep concurrency bounded and results in source order.
53
+ const probes = backend === "codex"
54
+ ? await probeCandidates(candidates, { spawnImpl, timeoutMs, signal }, assertActive) : null;
55
+ let selected = null;
56
+ for (const [index, candidate] of candidates.entries()) {
38
57
  assertActive();
39
- const probe = await probeExecutable(candidate, { spawnImpl, timeoutMs, signal });
58
+ const probe = probes ? probes[index] : await probeExecutable(candidate, { spawnImpl, timeoutMs, signal });
40
59
  assertActive();
41
60
  if (!probe.available) continue;
42
61
  const installedVersion = parseBackendVersion(probe.output);
@@ -52,12 +71,15 @@ export async function inspectBackendExecutable(
52
71
  update_command: policy.updateCommand,
53
72
  };
54
73
  // An executable that starts may still be too old for the requested feature.
55
- // Preserve candidate priority among compatible installs, and retain the
56
- // first runnable failure for actionable diagnostics if none qualifies.
57
- if (compatible) return inspection;
74
+ // Claude retains its existing priority. Codex chooses the newest version;
75
+ // equal versions retain discovery order regardless of probe completion order.
76
+ if (compatible) {
77
+ if (backend !== "codex") return inspection;
78
+ if (!selected || compareCodexVersions(installedVersion, selected.installed_version) > 0) selected = inspection;
79
+ }
58
80
  fallback ??= inspection;
59
81
  }
60
- return fallback || {
82
+ return selected || fallback || {
61
83
  backend,
62
84
  executable: null,
63
85
  available: false,
@@ -88,6 +110,8 @@ export function backendCandidates(backend, {
88
110
  return [
89
111
  environment.SIMY_CODEX_BIN,
90
112
  "codex",
113
+ ...codexPathCandidates(platform, environment),
114
+ ...(platform === "darwin" ? ["/opt/homebrew/bin/codex", "/usr/local/bin/codex"] : []),
91
115
  ...(platform === "darwin" ? ["/Applications", path.posix.join(home, "Applications")].flatMap(directory =>
92
116
  ["ChatGPT.app", "Codex.app"].flatMap(app => {
93
117
  const resources = path.posix.join(directory, app, "Contents", "Resources");
@@ -98,6 +122,48 @@ export function backendCandidates(backend, {
98
122
  ];
99
123
  }
100
124
 
125
+ function codexPathCandidates(platform, environment) {
126
+ const paths = platform === "win32" ? path.win32 : path.posix;
127
+ const names = platform === "win32" ? ["codex.exe", "codex.cmd", "codex.bat", "codex"] : ["codex"];
128
+ return (environment.PATH ?? environment.Path ?? "").split(paths.delimiter)
129
+ .map(directory => directory.replace(/^"(.*)"$/, "$1"))
130
+ .filter(directory => paths.isAbsolute(directory))
131
+ .flatMap(directory => names.map(name => paths.join(directory, name)))
132
+ .filter(candidate => { try { return statSync(candidate).isFile(); } catch { return false; } });
133
+ }
134
+
135
+ async function probeCandidates(candidates, options, assertActive) {
136
+ let next = 0;
137
+ const probes = new Array(candidates.length);
138
+ await Promise.all(Array.from({ length: Math.min(4, candidates.length) }, async () => {
139
+ while (next < candidates.length) {
140
+ // Drain every owned probe before reporting cancellation to callers.
141
+ if (options.signal?.aborted) break;
142
+ const index = next++;
143
+ probes[index] = await probeExecutable(candidates[index], options);
144
+ }
145
+ }));
146
+ assertActive();
147
+ return probes;
148
+ }
149
+
150
+ function compareCodexVersions(left, right) {
151
+ const core = compareVersions(left, right);
152
+ if (core) return core;
153
+ const prerelease = version => version.includes("-") ? version.slice(version.indexOf("-") + 1).split(".") : null;
154
+ const a = prerelease(left), b = prerelease(right);
155
+ if (!a || !b) return Number(!a) - Number(!b);
156
+ for (let index = 0; index < Math.max(a.length, b.length); index++) {
157
+ if (a[index] === b[index]) continue;
158
+ if (a[index] === undefined || b[index] === undefined) return a[index] === undefined ? -1 : 1;
159
+ const numericA = /^\d+$/.test(a[index]), numericB = /^\d+$/.test(b[index]);
160
+ if (numericA && numericB) return Number(a[index]) - Number(b[index]);
161
+ if (numericA !== numericB) return numericA ? -1 : 1;
162
+ return a[index] < b[index] ? -1 : 1;
163
+ }
164
+ return 0;
165
+ }
166
+
101
167
  // Claude Desktop can install below <version>/<content hash>/claude.app while
102
168
  // an older PATH wrapper still points at <version>/claude.app. Discover only the
103
169
  // known app layout; never recursively execute arbitrary files from user folders.
@@ -167,7 +233,9 @@ function probeExecutable(command, { spawnImpl, timeoutMs, signal }) {
167
233
  let settled = false, terminating = false;
168
234
  let timeout, force, limit;
169
235
  let output = Buffer.alloc(0);
170
- const child = spawnImpl(command, ["--version"], { stdio: ["ignore", "pipe", "pipe"] });
236
+ let child;
237
+ try { child = spawnImpl(command, ["--version"], { stdio: ["ignore", "pipe", "pipe"] }); }
238
+ catch { resolve({ available: false, output: "" }); return; }
171
239
  const capture = chunk => {
172
240
  // Version probes need a tiny prefix. Drain noisy executables without
173
241
  // retaining unbounded stdout/stderr in the desktop background process.
@@ -13,9 +13,16 @@ import {
13
13
  } from "./durable-local-task-steps-contract.js";
14
14
  import { buildExecutionCapabilityContract } from "./execution-capability-contract.js";
15
15
 
16
- export const CLI_VERSION = "0.6.22";
16
+ export const CLI_VERSION = "0.6.25";
17
17
  export const CLI_API_CONTRACT_VERSION = 10;
18
18
 
19
+ export function narrativeImageCapabilityMetadata() {
20
+ return {
21
+ schema_version: "fp_narrative_image.v1",
22
+ receipt_schema_version: "fp_native_image_receipt.v1",
23
+ };
24
+ }
25
+
19
26
  export function withCliContract(
20
27
  capabilities = {},
21
28
  installMode = null,
@@ -25,6 +32,7 @@ export function withCliContract(
25
32
  ...capabilities,
26
33
  cli_version: CLI_VERSION,
27
34
  api_contract_version: CLI_API_CONTRACT_VERSION,
35
+ fp_narrative_image: narrativeImageCapabilityMetadata(),
28
36
  local_task_file_capabilities: localTaskFileCapabilityMetadata(),
29
37
  local_task_scenario_packs: localTaskScenarioPackMetadata(),
30
38
  bounded_local_task_subtasks:
@@ -0,0 +1,5 @@
1
+ // Frozen manual acceptance is an explicit enrollment boundary. Its description
2
+ // or an old auto-continue switch cannot authorize a different verifier.
3
+ export function effectiveAcceptanceCriteria(managed) {
4
+ return managed?.acceptanceCriteria || [];
5
+ }