@awak-app/simy-cli 0.5.8 → 0.5.11

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 (32) hide show
  1. package/README.md +64 -0
  2. package/package.json +7 -3
  3. package/src/agent.js +70 -9
  4. package/src/auto-update.js +312 -35
  5. package/src/browser.js +24 -7
  6. package/src/cli-contract.js +1 -1
  7. package/src/codex-plugins/simy/skills/agentic-delivery-loop/SKILL.md +227 -18
  8. package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/acceptance-evidence.md +131 -0
  9. package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/change-boundary-matrix.md +20 -1
  10. package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/cross-repository-control.md +76 -0
  11. package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/delivery-levels.md +80 -0
  12. package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/minimum-completion.md +137 -0
  13. package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/shared-system-specifications.md +138 -0
  14. package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/state-and-receipts.md +18 -0
  15. package/src/codex-plugins/simy/skills/agentic-delivery-loop/scripts/check-acceptance.mjs +193 -0
  16. package/src/codex-plugins/simy/skills/agentic-delivery-loop/scripts/check-minimum-completion.mjs +221 -0
  17. package/src/console/app.js +21 -2
  18. package/src/console/commands.js +3 -0
  19. package/src/desktop-host.js +220 -0
  20. package/src/desktop-process-lock.js +231 -0
  21. package/src/desktop-status.js +263 -0
  22. package/src/direct-executor.js +6 -0
  23. package/src/index.js +37 -11
  24. package/src/install-update.js +494 -0
  25. package/src/orchestrator/audit.js +17 -2
  26. package/src/orchestrator/completion-contract.js +1 -1
  27. package/src/orchestrator/evidence.js +9 -1
  28. package/src/orchestrator/independent-audit.js +13 -1
  29. package/src/orchestrator/instruction.js +13 -1
  30. package/src/orchestrator/loop.js +34 -4
  31. package/src/orchestrator/minimum-completion.js +108 -0
  32. package/src/orchestrator/result.js +7 -0
package/README.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  Local execution agent for SIMY Local Tasks and Agentic Loop runs.
4
4
 
5
+ ## Apple Silicon Mac app
6
+
7
+ The macOS installer includes a native status window and menu bar app. Open
8
+ SIMY CLI from Applications and choose **Sign in**. The window shows SIMY login,
9
+ the connected Web address and last successful heartbeat, Codex installation and
10
+ login status, tasks, and updates separately. A Codex login check does not prove
11
+ that a task can execute successfully; permissions and service availability are
12
+ checked when work starts.
13
+
14
+ Closing the window keeps the agent running. Open the app again or choose
15
+ **Show SIMY CLI** from its menu bar icon to return. **Quit SIMY CLI** asks before
16
+ interrupting active tasks. The normal `simy` command remains available.
17
+
18
+ Signed patch/minor updates wait for idle and verify the new runtime before
19
+ handoff; failed startup restores the previous installed version. After a runtime
20
+ update, quit and reopen the app to load an updated native interface. The status
21
+ window reports App and runtime versions separately while they differ.
22
+
23
+ For development, `npm run build:macos-installer:dev` creates an unsigned app/DMG;
24
+ production builds require Developer ID signing and notarization. Never publish
25
+ unsigned development artifacts through the stable update manifest.
26
+
5
27
  For normal use, install SIMY globally and keep its background agent running:
6
28
 
7
29
  ```bash
@@ -373,6 +395,13 @@ processes, and exercises HIL plus lifecycle controls. It regenerates the
373
395
  screenshots, terminal frames, raw transcript, and SHA-256 manifest under
374
396
  `docs/pr-evidence/cli-agentic-loop-console/`.
375
397
 
398
+ ## Delivery Loop design proposals
399
+
400
+ The [minimum completion plan](docs/delivery-minimum-completion/README.md) describes
401
+ proposed checks for omitted requirements, inactive controls, unsaved results, and
402
+ broken integrations at every delivery level, with workflow, sequence, and state
403
+ diagrams. This is a design proposal, not a shipped completion guarantee.
404
+
376
405
  ## Publishing
377
406
 
378
407
  Publishing is handled by GitHub Actions in `.github/workflows/publish.yml`.
@@ -395,11 +424,46 @@ Deploy this CLI and the web capability proxy before enabling the backend scope
395
424
  requirement. Older clients receive an explicit upgrade error, never an expanded
396
425
  organization-wide bundle.
397
426
 
427
+ ### Minimum functional completion
428
+
429
+ Every CLI coding-loop promotion now requires a current two-layer observation
430
+ matrix: the requested operation and result, plus independently checked final
431
+ postcondition and integration. See the [minimum completion contract](src/codex-plugins/simy/skills/agentic-delivery-loop/references/minimum-completion.md)
432
+ for the executable format. Missing mappings, mismatching observations, changed
433
+ artifacts or stale revisions block promotion even when the executor reports
434
+ success. Independent review checks original-request coverage and the test oracle.
435
+
436
+ Existing v2 run history is retained; resumed/rechecked runs need the new evidence.
437
+ The same checker ships in the standalone Delivery Loop skill, but it does not
438
+ control the host's final response or establish deployment completion.
439
+
398
440
  ### Submit repaired local delivery evidence to SQM
399
441
 
442
+ The bundled Delivery Loop maintains an external acceptance checklist with separate
443
+ user-journey and technical-invariant results. It refreshes the table after each
444
+ evaluated action and marks evidence pending when the code or runtime context
445
+ changes. The [acceptance evidence guide](src/codex-plugins/simy/skills/agentic-delivery-loop/references/acceptance-evidence.md)
446
+ documents the offline validator shipped inside the skill. Its result establishes
447
+ record completeness and artifact integrity, not overall delivery or deployment.
448
+ At the start of each new run, the loop recommends and confirms one of five
449
+ [delivery levels](src/codex-plugins/simy/skills/agentic-delivery-loop/references/delivery-levels.md)
450
+ in chat. Risk-based ceilings keep sensitive or consequential changes on the
451
+ required safety level; the selection adjusts verification depth but grants no
452
+ additional authority.
453
+
400
454
  `simy sqm submit-evidence --file delivery.json --host https://app-dev.simy.one`
401
455
  submits an explicit bounded summary through your existing organization-bound device
402
456
  session. `--dry-run` previews the exact document without uploading it. See the
403
457
  [local evidence contract](src/codex-plugins/simy/skills/agentic-delivery-loop/references/local-sqm-evidence.md).
404
458
  The receipt identifies the source digest and analysis job; it is not a declaration
405
459
  that an incident or blocking rule has been published.
460
+
461
+ ## Delivery Loop shared specification
462
+
463
+ The [Delivery Loop system specification](docs/systems/delivery-loop/README.md)
464
+ explains its purpose, As-Is and proposed To-Be through twelve linked views. Keep
465
+ these as shared team documents; each change updates affected views and checks
466
+ cross-view consistency. The skill requires independent design, implementation-to-
467
+ To-Be and PR reviews, plus explicitly opted-in SQM before and after PR creation.
468
+ The [workflow reference](src/codex-plugins/simy/skills/agentic-delivery-loop/references/shared-system-specifications.md)
469
+ explains baseline updates, historical regression coverage and evidence limits.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awak-app/simy-cli",
3
- "version": "0.5.8",
3
+ "version": "0.5.11",
4
4
  "description": "Local SIMY executor for non-coding Local Tasks and Agentic Loop runs.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -40,8 +40,12 @@
40
40
  "check:auto-update": "node --check ./src/auto-update.js && node --check ./scripts/auto-update-e2e.js && npm run check:sqm",
41
41
  "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/review-worker.js && node --check ./scripts/sqm-complete-loop-e2e.js && node --check ./scripts/sqm-local-review-e2e.js",
42
42
  "check:real-provider-syntax": "node --check ./scripts/real-codex-probe.js && node --check ./scripts/real-claude-probe.js && node --check ./scripts/real-provider-console-fixture.js && node --check ./scripts/real-provider-console-e2e.js",
43
- "check:syntax": "node --check ./src/index.js && node --check ./src/agent.js && node --check ./src/browser.js && node --check ./src/web-api.js && node --check ./src/durable-local-task-worker.js && node --check ./src/durable-local-task-steps-contract.js && node --check ./src/bounded-local-task-subtasks-contract.js && node --check ./src/bounded-local-task-subtask-pool.js && node --check ./src/local-task-artifact-contract.js && node --check ./src/execution-capability-contract.js && node --check ./src/shutdown.js && node --check ./src/run-registry.js && node --check ./src/direct-executor.js && node --check ./src/execution-guardrail.js && node --check ./src/backend-executable.js && node --check ./src/provider-stream.js && node --check ./src/console/index.js && node --check ./src/console/app.js && node --check ./src/console/commands.js && node --check ./src/local-attachments.js && node --check ./src/repository-inventory.js && node --check ./src/session-store.js && node --check ./src/web-origin.js && node --check ./src/workspace-context.js && node --check ./src/orchestrator/index.js && node --check ./src/orchestrator/shared.js && node --check ./src/orchestrator/recovery.js && node --check ./src/orchestrator/risk.js && node --check ./src/orchestrator/contract.js && node --check ./src/orchestrator/completion-contract.js && node --check ./src/orchestrator/instruction.js && node --check ./src/orchestrator/problem-solving.js && node --check ./src/orchestrator/budget.js && node --check ./src/orchestrator/execution-io.js && node --check ./src/orchestrator/presentation.js && node --check ./src/orchestrator/result.js && node --check ./src/orchestrator/retry.js && node --check ./src/orchestrator/evidence.js && node --check ./src/orchestrator/independent-audit.js && node --check ./src/orchestrator/audit.js && node --check ./src/orchestrator/loop.js && node --check ./src/runner.js && node --check ./scripts/fixtures/completion-contract-fixture.js && node --check ./scripts/fixtures/fake-coding-backend.js && node --check ./scripts/e2e-terminal-evidence.js && node --check ./scripts/audit-gate-e2e.js && node --check ./scripts/completion-contract-e2e.js && node --check ./scripts/retry-circuit-e2e.js && node --check ./scripts/follow-up-charter-e2e.js && node --check ./scripts/task-routing-e2e.js && node --check ./scripts/executor-version-preflight-e2e.js && node --check ./scripts/blocked-recovery-e2e.js && node --check ./scripts/process-localization-e2e.js && node --check ./scripts/hypothesis-retries-e2e.js && node --check ./scripts/budget-enforcement-e2e.js && node --check ./scripts/local-task-default-workspace-e2e.js && node --check ./scripts/local-task-idempotency-e2e.js && node --check ./scripts/console-e2e-fixture.js && node --check ./scripts/console-e2e.js && node --check ./scripts/console-recovery-e2e-fixture.js && node --check ./scripts/console-recovery-e2e.js && node --check ./scripts/real-provider-console-fixture.js && node --check ./scripts/real-provider-console-e2e.js && node --check ./scripts/fullstack-cli-smoke.js && node --check ./scripts/check-package-contents.js",
44
- "check:package": "node ./scripts/check-package-contents.js"
43
+ "check:syntax": "node --check ./src/index.js && node --check ./src/install-update.js && node --check ./src/agent.js && node --check ./src/browser.js && node --check ./src/web-api.js && node --check ./src/durable-local-task-worker.js && node --check ./src/durable-local-task-steps-contract.js && node --check ./src/bounded-local-task-subtasks-contract.js && node --check ./src/bounded-local-task-subtask-pool.js && node --check ./src/local-task-artifact-contract.js && node --check ./src/execution-capability-contract.js && node --check ./src/shutdown.js && node --check ./src/run-registry.js && node --check ./src/direct-executor.js && node --check ./src/execution-guardrail.js && node --check ./src/backend-executable.js && node --check ./src/provider-stream.js && node --check ./src/console/index.js && node --check ./src/console/app.js && node --check ./src/console/commands.js && node --check ./src/local-attachments.js && node --check ./src/repository-inventory.js && node --check ./src/session-store.js && node --check ./src/web-origin.js && node --check ./src/workspace-context.js && node --check ./src/orchestrator/index.js && node --check ./src/orchestrator/shared.js && node --check ./src/orchestrator/recovery.js && node --check ./src/orchestrator/risk.js && node --check ./src/orchestrator/contract.js && node --check ./src/orchestrator/completion-contract.js && node --check ./src/orchestrator/minimum-completion.js && node --check ./src/codex-plugins/simy/skills/agentic-delivery-loop/scripts/check-minimum-completion.mjs && node --check ./src/orchestrator/instruction.js && node --check ./src/orchestrator/problem-solving.js && node --check ./src/orchestrator/budget.js && node --check ./src/orchestrator/execution-io.js && node --check ./src/orchestrator/presentation.js && node --check ./src/orchestrator/result.js && node --check ./src/orchestrator/retry.js && node --check ./src/orchestrator/evidence.js && node --check ./src/orchestrator/independent-audit.js && node --check ./src/orchestrator/audit.js && node --check ./src/orchestrator/loop.js && node --check ./src/runner.js && node --check ./scripts/fixtures/completion-contract-fixture.js && node --check ./scripts/fixtures/fake-coding-backend.js && node --check ./scripts/e2e-terminal-evidence.js && node --check ./scripts/audit-gate-e2e.js && node --check ./scripts/completion-contract-e2e.js && node --check ./scripts/retry-circuit-e2e.js && node --check ./scripts/follow-up-charter-e2e.js && node --check ./scripts/task-routing-e2e.js && node --check ./scripts/executor-version-preflight-e2e.js && node --check ./scripts/blocked-recovery-e2e.js && node --check ./scripts/process-localization-e2e.js && node --check ./scripts/hypothesis-retries-e2e.js && node --check ./scripts/budget-enforcement-e2e.js && node --check ./scripts/local-task-default-workspace-e2e.js && node --check ./scripts/local-task-idempotency-e2e.js && node --check ./scripts/console-e2e-fixture.js && node --check ./scripts/console-e2e.js && node --check ./scripts/console-recovery-e2e-fixture.js && node --check ./scripts/console-recovery-e2e.js && node --check ./scripts/real-provider-console-fixture.js && node --check ./scripts/real-provider-console-e2e.js && node --check ./scripts/fullstack-cli-smoke.js && node --check ./scripts/check-package-contents.js",
44
+ "check:package": "node ./scripts/check-package-contents.js",
45
+ "build:macos-installer:dev": "bash packaging/build-macos-arm64.sh --unsigned-dev",
46
+ "build:macos-installer": "bash packaging/build-macos-arm64.sh --production",
47
+ "test:macos-installer": "node --test packaging/test-macos-packaging.mjs",
48
+ "build:macos-installer:production": "bash packaging/build-macos-arm64.sh --production"
45
49
  },
46
50
  "engines": {
47
51
  "node": ">=20"
package/src/agent.js CHANGED
@@ -48,6 +48,12 @@ import {
48
48
  inspectDesktopExecutor,
49
49
  normalizeDesktopExecutionTarget,
50
50
  } from "./desktop-executor.js";
51
+ import {
52
+ createCodexStatusInspector,
53
+ createConnectionStatusTracker,
54
+ desktopAuthStatus,
55
+ desktopTaskStatus,
56
+ } from "./desktop-status.js";
51
57
  import { recoveryContractForPreflight } from "./orchestrator/recovery.js";
52
58
  import {
53
59
  DEFAULT_RETRY_BUDGET,
@@ -237,6 +243,25 @@ export async function startAgent({
237
243
  let heartbeatInFlight = null;
238
244
  let durableLocalTaskWorker = null;
239
245
  let sqmLocalReviewWorker = null;
246
+ let loginUrl = null;
247
+ const connectionStatus = createConnectionStatusTracker({ now: dependencies.statusNow });
248
+ const codexStatus = createCodexStatusInspector({
249
+ inspect: dependencies.inspectCodexStatus,
250
+ now: dependencies.statusNowMs,
251
+ });
252
+
253
+ const requestDesktopLogin = () => {
254
+ if (isSessionValid(session, Date.now(), apiOrigin)) return null;
255
+ if (!loginUrl) {
256
+ loginUrl = new URL("/local-cli/connect", apiOrigin);
257
+ loginUrl.searchParams.set("port", String(port));
258
+ loginUrl.searchParams.set("nonce", authNonce);
259
+ loginUrl.searchParams.set("cli_version", CLI_VERSION);
260
+ loginUrl.searchParams.set("api_contract_version", String(CLI_API_CONTRACT_VERSION));
261
+ if (installMode) loginUrl.searchParams.set("install_mode", installMode);
262
+ }
263
+ return loginUrl.toString();
264
+ };
240
265
 
241
266
  const restoreRemoteRuns = async () => {
242
267
  if (!isSessionValid(session, Date.now(), apiOrigin) || !session?.device_id) return;
@@ -268,6 +293,8 @@ export async function startAgent({
268
293
  const heartbeat = () => {
269
294
  if (!isSessionValid(session, Date.now(), apiOrigin)) return Promise.resolve(false);
270
295
  if (heartbeatInFlight) return heartbeatInFlight;
296
+ connectionStatus.attempt();
297
+ let deviceHeartbeatSucceeded = false;
271
298
  heartbeatInFlight = Promise.resolve()
272
299
  .then(() =>
273
300
  heartbeatDevice({
@@ -280,12 +307,26 @@ export async function startAgent({
280
307
  }),
281
308
  )
282
309
  .then(async () => {
310
+ deviceHeartbeatSucceeded = true;
311
+ connectionStatus.success();
283
312
  const sqmResult = sqmLocalReviewWorker
284
313
  ? await sqmLocalReviewWorker.poll()
285
314
  : null;
286
315
  if (!sqmResult && durableLocalTaskWorker) await durableLocalTaskWorker.poll();
287
316
  return true;
288
317
  })
318
+ .catch((error) => {
319
+ if (!deviceHeartbeatSucceeded) {
320
+ const state = connectionStatus.failure(error);
321
+ if (state === "unauthorized") {
322
+ session = null;
323
+ loginUrl = null;
324
+ refreshAvailableCapabilities();
325
+ requestDesktopLogin();
326
+ }
327
+ }
328
+ throw error;
329
+ })
289
330
  .finally(() => {
290
331
  heartbeatInFlight = null;
291
332
  });
@@ -1530,14 +1571,8 @@ export async function startAgent({
1530
1571
  console.log(`SIMY Web host: ${apiOrigin}`);
1531
1572
  }
1532
1573
 
1533
- let loginUrl = null;
1534
1574
  if (!isSessionValid(session, Date.now(), apiOrigin)) {
1535
- loginUrl = new URL("/local-cli/connect", apiOrigin);
1536
- loginUrl.searchParams.set("port", String(port));
1537
- loginUrl.searchParams.set("nonce", authNonce);
1538
- loginUrl.searchParams.set("cli_version", CLI_VERSION);
1539
- loginUrl.searchParams.set("api_contract_version", String(CLI_API_CONTRACT_VERSION));
1540
- if (installMode) loginUrl.searchParams.set("install_mode", installMode);
1575
+ requestDesktopLogin();
1541
1576
  if (!quiet) {
1542
1577
  console.log(`Sign in to SIMY: ${loginUrl.toString()}`);
1543
1578
  console.log(`Session file: ${sessionPath(apiOrigin, sessionRoot)}`);
@@ -1571,6 +1606,21 @@ export async function startAgent({
1571
1606
  server.on("close", () => {
1572
1607
  void shutdown().catch((error) => reportDurableLocalTaskError(error, quiet));
1573
1608
  });
1609
+ const getDesktopStatus = async () => {
1610
+ const auth = desktopAuthStatus(session, { webOrigin: apiOrigin });
1611
+ return {
1612
+ schemaVersion: 1,
1613
+ sampledAt: new Date().toISOString(),
1614
+ version: CLI_VERSION,
1615
+ webOrigin: apiOrigin,
1616
+ auth,
1617
+ connection: connectionStatus.snapshot({ authenticated: auth.state === "signed_in" }),
1618
+ tasks: desktopTaskStatus([registry, directRegistry, localTaskRegistry]),
1619
+ update: updateManager?.snapshot?.() ?? null,
1620
+ codex: await codexStatus(),
1621
+ loginUrl: auth.state === "signed_in" ? null : requestDesktopLogin(),
1622
+ };
1623
+ };
1574
1624
  return {
1575
1625
  server,
1576
1626
  port,
@@ -1582,8 +1632,17 @@ export async function startAgent({
1582
1632
  shutdown,
1583
1633
  webOrigin: apiOrigin,
1584
1634
  get loginUrl() {
1585
- return loginUrl?.toString() ?? null;
1635
+ return requestDesktopLogin();
1636
+ },
1637
+ requestDesktopLogin,
1638
+ getDesktopStatus,
1639
+ async refreshDesktopStatus() {
1640
+ if (isSessionValid(session, Date.now(), apiOrigin)) {
1641
+ await heartbeat().catch((error) => reportHeartbeatError(error, quiet));
1642
+ }
1643
+ return getDesktopStatus();
1586
1644
  },
1645
+ refreshCodexStatus: () => codexStatus({ force: true }),
1587
1646
  workspace,
1588
1647
  repositoryScanRoot,
1589
1648
  get capabilities() {
@@ -1778,7 +1837,9 @@ export async function heartbeatLocalDevice({
1778
1837
  );
1779
1838
  if (!response.ok) {
1780
1839
  const payload = await response.json().catch(() => null);
1781
- throw new Error(webApiErrorMessage(payload, response.status));
1840
+ const error = new Error(webApiErrorMessage(payload, response.status));
1841
+ error.status = response.status;
1842
+ throw error;
1782
1843
  }
1783
1844
  }
1784
1845