@reticlehq/server 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +30 -28
- package/dist/command/cli/adhoc-suite.d.ts +19 -0
- package/dist/command/cli/adhoc-suite.js +88 -0
- package/dist/command/cli/adhoc-verdict.d.ts +23 -2
- package/dist/command/cli/adhoc-verdict.js +18 -10
- package/dist/command/cli/auth/device-flow.d.ts +2 -2
- package/dist/command/cli/cli-doctor.js +37 -5
- package/dist/command/cli/cli-flow-commands.d.ts +2 -1
- package/dist/command/cli/cli-kill.js +1 -1
- package/dist/command/cli/cli-parse-grammar.d.ts +7 -0
- package/dist/command/cli/cli-parse-grammar.js +7 -0
- package/dist/command/cli/cli-parse-verify.d.ts +2 -5
- package/dist/command/cli/cli-parse-verify.js +86 -13
- package/dist/command/cli/cli-parse.d.ts +8 -1
- package/dist/command/cli/cli-parse.js +38 -7
- package/dist/command/cli/cli-verify.d.ts +59 -0
- package/dist/command/cli/cli-verify.js +131 -19
- package/dist/command/cli/cloud-cli.js +7 -6
- package/dist/command/cli/cloud-kit.d.ts +0 -2
- package/dist/command/cli/cloud-kit.js +3 -7
- package/dist/command/cli/config/config-discovery.d.ts +12 -0
- package/dist/command/cli/config/config-discovery.js +19 -0
- package/dist/command/cli/doctor/doctor-rows.d.ts +12 -0
- package/dist/command/cli/doctor/doctor-rows.js +12 -0
- package/dist/command/cli/doctor/doctor-sessions-line.d.ts +2 -1
- package/dist/command/cli/drive/drive-command.js +1 -1
- package/dist/command/cli/launch/cli-launch.d.ts +3 -23
- package/dist/command/cli/launch/cli-launch.js +29 -70
- package/dist/command/cli/lifecycle/daemon-lifecycle.d.ts +33 -0
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +198 -0
- package/dist/command/cli/mcp-command.js +5 -3
- package/dist/command/cli/ports/resolve/cli-port.d.ts +15 -1
- package/dist/command/cli/ports/resolve/cli-port.js +50 -2
- package/dist/command/cli/report-command.d.ts +16 -0
- package/dist/command/cli/report-command.js +97 -0
- package/dist/command/cli/status/status-lines.d.ts +28 -0
- package/dist/command/cli/status/status-lines.js +117 -0
- package/dist/command/cli.d.ts +1 -1
- package/dist/command/cli.js +29 -177
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +32 -0
- package/dist/command/daemon/binding/daemon-status-probe.js +93 -0
- package/dist/command/daemon/binding/loopback-reach.d.ts +42 -0
- package/dist/command/daemon/binding/loopback-reach.js +63 -0
- package/dist/command/daemon/binding/port-presence.d.ts +1 -1
- package/dist/command/daemon/daemon-resilience.d.ts +13 -1
- package/dist/command/daemon/daemon-resilience.js +12 -1
- package/dist/command/daemon/daemon.d.ts +2 -11
- package/dist/command/daemon/daemon.js +8 -11
- package/dist/command/daemon/idle-shutdown.d.ts +2 -1
- package/dist/command/daemon/lifetime/heartbeat.d.ts +8 -0
- package/dist/command/daemon/lifetime/heartbeat.js +10 -0
- package/dist/command/daemon/lifetime/log-cap.d.ts +68 -0
- package/dist/command/daemon/lifetime/log-cap.js +115 -0
- package/dist/command/setup/agent-notice-memory.d.ts +16 -0
- package/dist/command/setup/agent-notice-memory.js +65 -0
- package/dist/command/setup/bringup/dev-server-wait.d.ts +1 -0
- package/dist/command/setup/bringup/dev-server-wait.js +16 -0
- package/dist/command/setup/bringup/ensure-daemon.js +1 -1
- package/dist/command/setup/init/init-host.js +8 -0
- package/dist/command/setup/init/init-runtime.js +13 -1
- package/dist/command/setup/node-effects.js +1 -1
- package/dist/command/setup/probe/page-probe.js +9 -2
- package/dist/command/setup/run-setup.d.ts +25 -7
- package/dist/command/setup/run-setup.js +51 -9
- package/dist/command/setup/setup-command.js +31 -3
- package/dist/command/setup/terminal/confirm.js +2 -1
- package/dist/command/update/updater.d.ts +27 -0
- package/dist/command/update/updater.js +35 -2
- package/dist/features/crawl/crawl-tools.js +3 -1
- package/dist/features/crawl/crawl.d.ts +2 -0
- package/dist/features/crawl/crawl.js +3 -1
- package/dist/features/harness/drive-report.d.ts +73 -0
- package/dist/features/harness/drive-report.js +196 -0
- package/dist/features/harness/driver.js +29 -8
- package/dist/features/harness/drivers.d.ts +19 -0
- package/dist/features/harness/drivers.js +19 -0
- package/dist/features/harness/fill-values.d.ts +67 -0
- package/dist/features/harness/fill-values.js +153 -0
- package/dist/features/harness/jev-driver.d.ts +188 -0
- package/dist/features/harness/jev-driver.js +661 -0
- package/dist/features/harness/openai-driver.d.ts +46 -0
- package/dist/features/harness/openai-driver.js +197 -0
- package/dist/features/harness/platform-config.d.ts +62 -0
- package/dist/features/harness/platform-config.js +97 -0
- package/dist/features/visual/visual-tools.js +26 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +80 -130
- package/dist/judgement/capsule/capsule-store.d.ts +31 -2
- package/dist/judgement/capsule/capsule-store.js +58 -6
- package/dist/judgement/capsule/capsule.js +5 -0
- package/dist/judgement/capsule/causal-summary.d.ts +13 -1
- package/dist/judgement/capsule/causal-summary.js +7 -0
- package/dist/judgement/domain/domain-model.js +38 -9
- package/dist/judgement/domain/domain-tools.js +4 -2
- package/dist/judgement/outcome/assertion-integrity.d.ts +3 -3
- package/dist/judgement/phenomena/phenomena.d.ts +2 -1
- package/dist/judgement/runs/artifact/gap-report.d.ts +17 -0
- package/dist/judgement/runs/artifact/gap-report.js +46 -0
- package/dist/judgement/runs/artifact/gap-summary.d.ts +58 -0
- package/dist/judgement/runs/artifact/gap-summary.js +85 -0
- package/dist/judgement/runs/artifact/render-report.js +4 -1
- package/dist/judgement/runs/artifact/to-artifact.d.ts +7 -2
- package/dist/judgement/runs/artifact/to-artifact.js +1 -1
- package/dist/judgement/runs/context-tools.js +21 -3
- package/dist/judgement/runs/drive-run.js +7 -2
- package/dist/judgement/runs/verification-sync.d.ts +2 -2
- package/dist/judgement/runs/verification-sync.js +9 -2
- package/dist/language/flows/affected-tools.js +6 -3
- package/dist/language/flows/annotate-notes/annotate.d.ts +0 -15
- package/dist/language/flows/annotate-notes/annotate.js +66 -18
- package/dist/language/flows/flow-anchor.d.ts +12 -0
- package/dist/language/flows/flow-anchor.js +20 -0
- package/dist/language/flows/flow-expect-grammar.d.ts +2 -2
- package/dist/language/flows/flow-expect-grammar.js +92 -11
- package/dist/language/flows/flow-intent.js +1 -1
- package/dist/language/flows/flow-learning.d.ts +3 -0
- package/dist/language/flows/flow-learning.js +39 -8
- package/dist/language/flows/flow-replay-run.d.ts +55 -10
- package/dist/language/flows/flow-replay-run.js +217 -58
- package/dist/language/flows/flow-replay-types.d.ts +9 -0
- package/dist/language/flows/flow-replay.d.ts +29 -11
- package/dist/language/flows/flow-replay.js +221 -203
- package/dist/language/flows/flow-result.d.ts +18 -1
- package/dist/language/flows/flow-result.js +18 -2
- package/dist/language/flows/flow-step-runners.d.ts +26 -10
- package/dist/language/flows/flow-step-runners.js +20 -4
- package/dist/language/flows/flow-store-for-session.d.ts +2 -1
- package/dist/language/flows/flow-success.d.ts +21 -6
- package/dist/language/flows/flow-success.js +50 -138
- package/dist/language/flows/flow-tools.js +8 -4
- package/dist/language/flows/flows.d.ts +15 -10
- package/dist/language/flows/flows.js +17 -4
- package/dist/language/flows/heal.d.ts +9 -1
- package/dist/language/flows/heal.js +24 -2
- package/dist/language/flows/learned-sources.d.ts +21 -0
- package/dist/language/flows/learned-sources.js +84 -0
- package/dist/language/flows/narrow-write.d.ts +4 -4
- package/dist/language/flows/recording/recording-backtrack.d.ts +0 -7
- package/dist/language/flows/recording/recording-backtrack.js +1 -1
- package/dist/language/flows/recording/replay-halt.d.ts +2 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +2 -2
- package/dist/language/flows/replay.js +13 -9
- package/dist/language/flows/stores/annotation-store.d.ts +5 -5
- package/dist/language/flows/stores/assertion-tiers-store.js +2 -3
- package/dist/language/flows/stores/flake-store.js +2 -3
- package/dist/language/flows/suite/coverage.d.ts +1 -1
- package/dist/language/flows/suite/parallel-suite.d.ts +2 -1
- package/dist/language/flows/suite-selection.d.ts +15 -1
- package/dist/language/flows/suite-selection.js +1 -1
- package/dist/language/flows/verify-change-tools.js +21 -4
- package/dist/memory/cloud/account-state.d.ts +1 -1
- package/dist/memory/cloud/account-state.js +5 -4
- package/dist/memory/cloud/cloud-config.d.ts +9 -0
- package/dist/memory/cloud/cloud-config.js +9 -0
- package/dist/memory/cloud/cloud-sync.d.ts +7 -4
- package/dist/memory/cloud/cloud-sync.js +11 -6
- package/dist/memory/cloud/harness-config.d.ts +12 -0
- package/dist/memory/cloud/harness-config.js +58 -0
- package/dist/memory/cloud/harness-offer.d.ts +44 -0
- package/dist/memory/cloud/harness-offer.js +146 -0
- package/dist/memory/cloud/harness-switch.d.ts +11 -0
- package/dist/memory/cloud/harness-switch.js +53 -0
- package/dist/memory/cloud/sync-cycle.d.ts +12 -0
- package/dist/memory/cloud/sync-cycle.js +29 -4
- package/dist/memory/cloud/sync-daemon.d.ts +35 -2
- package/dist/memory/cloud/sync-daemon.js +45 -0
- package/dist/memory/cloud/sync-disk.js +11 -6
- package/dist/memory/impact/impact-recorder.d.ts +8 -0
- package/dist/memory/impact/impact-recorder.js +2 -1
- package/dist/memory/impact/impact-store.d.ts +5 -0
- package/dist/memory/impact/impact-store.js +25 -0
- package/dist/memory/intent/inline-intent.js +8 -3
- package/dist/memory/intent/intent-shard-store.d.ts +33 -47
- package/dist/memory/intent/intent-shard-store.js +253 -141
- package/dist/memory/intent/intent-shard.d.ts +22 -23
- package/dist/memory/intent/intent-shard.js +1 -1
- package/dist/memory/intent/intent-store.d.ts +13 -8
- package/dist/memory/intent/intent-store.js +46 -90
- package/dist/memory/intent/intent-tools.js +34 -23
- package/dist/memory/journal/ambient-store.js +2 -3
- package/dist/memory/journal/attach-journal.d.ts +11 -0
- package/dist/memory/journal/attach-journal.js +1 -1
- package/dist/memory/journal/deviation-report.js +4 -1
- package/dist/memory/journal/deviation-service.js +10 -2
- package/dist/memory/journal/drive-flow.d.ts +2 -2
- package/dist/memory/journal/drive-flow.js +21 -12
- package/dist/memory/journal/envelope-store.js +2 -3
- package/dist/memory/journal/journal-query.d.ts +35 -1
- package/dist/memory/journal/journal-query.js +46 -0
- package/dist/memory/journal/journal-recorder.d.ts +71 -2
- package/dist/memory/journal/journal-recorder.js +45 -7
- package/dist/memory/journal/on-disk/retain-policy.d.ts +34 -0
- package/dist/memory/journal/on-disk/retain-policy.js +44 -0
- package/dist/memory/journal/on-disk/retention.d.ts +91 -2
- package/dist/memory/journal/on-disk/retention.js +181 -11
- package/dist/memory/journal/on-disk/startup-maintenance.d.ts +42 -0
- package/dist/memory/journal/on-disk/startup-maintenance.js +14 -0
- package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +0 -2
- package/dist/memory/journal/on-disk/workspace-gitignore.js +6 -38
- package/dist/memory/journal/on-disk/workspace-tiers.d.ts +52 -0
- package/dist/memory/journal/on-disk/workspace-tiers.js +88 -0
- package/dist/memory/journal/route-template.d.ts +22 -0
- package/dist/memory/journal/route-template.js +44 -0
- package/dist/memory/journal/self-observation.d.ts +3 -0
- package/dist/memory/journal/self-observation.js +67 -0
- package/dist/memory/journal/session-end.d.ts +17 -4
- package/dist/memory/journal/session-end.js +85 -7
- package/dist/memory/journal/session-journal.d.ts +122 -5
- package/dist/memory/journal/session-journal.js +489 -32
- package/dist/memory/project/artifact-root-resolver.d.ts +3 -0
- package/dist/memory/project/artifact-root-resolver.js +89 -0
- package/dist/memory/project/artifact-root.d.ts +39 -2
- package/dist/memory/project/artifact-root.js +58 -1
- package/dist/memory/project/baselines.d.ts +1 -1
- package/dist/memory/project/dir/fill-value-store.d.ts +32 -0
- package/dist/memory/project/dir/fill-value-store.js +88 -0
- package/dist/memory/project/dir/reticle-dir.d.ts +15 -5
- package/dist/memory/project/dir/reticle-dir.js +11 -0
- package/dist/memory/project/fs/fs-port.d.ts +22 -1
- package/dist/memory/project/fs/fs-port.js +72 -5
- package/dist/memory/project/fs/write-atomic.d.ts +26 -0
- package/dist/memory/project/fs/write-atomic.js +48 -0
- package/dist/memory/project/learned-routes.d.ts +16 -2
- package/dist/memory/project/learned-routes.js +26 -10
- package/dist/memory/project/project-for-root.d.ts +30 -0
- package/dist/memory/project/project-for-root.js +43 -0
- package/dist/memory/project/project-tools.js +10 -5
- package/dist/memory/project/session-root.d.ts +35 -6
- package/dist/memory/project/session-root.js +70 -8
- package/dist/memory/recall/prior/connection-memory.d.ts +6 -0
- package/dist/memory/recall/prior/connection-memory.js +8 -0
- package/dist/memory/recall/registered-projects.d.ts +2 -1
- package/dist/portal/bridge/auth-failure-reason.d.ts +9 -0
- package/dist/portal/bridge/auth-failure-reason.js +20 -3
- package/dist/portal/bridge/bridge.d.ts +6 -1
- package/dist/portal/bridge/bridge.js +36 -2
- package/dist/portal/input/real-input.js +2 -1
- package/dist/portal/pool/browser-pool.d.ts +10 -0
- package/dist/portal/pool/browser-pool.js +10 -0
- package/dist/portal/pool/playwright-launcher.js +1 -0
- package/dist/portal/pool/pool-contract.d.ts +2 -0
- package/dist/portal/pool/storage-seed.d.ts +2 -1
- package/dist/portal/pool/zero-install.d.ts +27 -0
- package/dist/portal/pool/zero-install.js +54 -0
- package/dist/portal/realm/web-realm.js +6 -0
- package/dist/portal/session/dev-server/dev-server-probe.d.ts +2 -1
- package/dist/portal/session/dev-server/served-document.d.ts +21 -0
- package/dist/portal/session/dev-server/served-document.js +57 -0
- package/dist/portal/session/facts/background-traffic.d.ts +9 -0
- package/dist/portal/session/facts/background-traffic.js +25 -0
- package/dist/portal/session/facts/session-replaced.d.ts +19 -0
- package/dist/portal/session/facts/session-replaced.js +22 -0
- package/dist/portal/session/live-control-tools.js +48 -3
- package/dist/portal/session/no-session-diagnosis.d.ts +1 -0
- package/dist/portal/session/no-session-diagnosis.js +67 -60
- package/dist/portal/session/no-session-next-action.js +3 -2
- package/dist/portal/session/no-session-watch.js +14 -10
- package/dist/portal/session/presence/attachment-history.d.ts +13 -2
- package/dist/portal/session/rebind.d.ts +18 -0
- package/dist/portal/session/rebind.js +38 -0
- package/dist/portal/session/session-health.d.ts +61 -0
- package/dist/portal/session/session-health.js +40 -1
- package/dist/portal/session/session-info.d.ts +6 -0
- package/dist/portal/session/session-manager.d.ts +13 -0
- package/dist/portal/session/session-manager.js +42 -3
- package/dist/portal/session/session-successor.d.ts +11 -0
- package/dist/portal/session/session-successor.js +14 -1
- package/dist/portal/session/session-verdict-facts.d.ts +28 -0
- package/dist/portal/session/session-verdict-facts.js +15 -0
- package/dist/portal/session/session.d.ts +26 -10
- package/dist/portal/session/session.js +48 -49
- package/dist/status-payload.d.ts +12 -1
- package/dist/status-payload.js +4 -1
- package/dist/surface/http-server.js +3 -5
- package/dist/surface/mcp/faults/mcp-outage.d.ts +2 -1
- package/dist/surface/mcp/faults/mcp-outage.js +20 -4
- package/dist/surface/mcp/mcp-proxy.d.ts +10 -1
- package/dist/surface/mcp/mcp-proxy.js +23 -12
- package/dist/surface/mcp/mcp.d.ts +10 -1
- package/dist/surface/mcp/mcp.js +59 -29
- package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +15 -2
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +22 -5
- package/dist/surface/mcp/proxy/proxy-log.d.ts +5 -11
- package/dist/surface/mcp/proxy/proxy-log.js +7 -22
- package/dist/surface/mcp/proxy-idle-exit.d.ts +2 -1
- package/dist/surface/mcp/server-instructions.js +12 -1
- package/dist/surface/tools/act/act-preflight.js +6 -1
- package/dist/surface/tools/act/already-true.d.ts +40 -0
- package/dist/surface/tools/act/already-true.js +36 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +6 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.js +13 -0
- package/dist/surface/tools/act/sequence-grade.js +13 -0
- package/dist/surface/tools/act/settle-in-flight.d.ts +6 -2
- package/dist/surface/tools/act/settle-in-flight.js +29 -6
- package/dist/surface/tools/act-capsule.js +49 -8
- package/dist/surface/tools/act-tools.js +25 -24
- package/dist/surface/tools/args/numeric-bounds.d.ts +15 -2
- package/dist/surface/tools/args/numeric-bounds.js +30 -3
- package/dist/surface/tools/assert/assert-grade.js +14 -2
- package/dist/surface/tools/assert/assert-verdict.js +74 -21
- package/dist/surface/tools/browser-tools.js +4 -3
- package/dist/surface/tools/coverage-tools.js +5 -2
- package/dist/surface/tools/dynamic-tools.js +43 -46
- package/dist/surface/tools/error-recovery.d.ts +6 -0
- package/dist/surface/tools/error-recovery.js +15 -0
- package/dist/surface/tools/explore-tools.js +80 -7
- package/dist/surface/tools/feedback-tools.d.ts +2 -1
- package/dist/surface/tools/feedback-tools.js +50 -3
- package/dist/surface/tools/first-sentence.d.ts +24 -0
- package/dist/surface/tools/first-sentence.js +0 -0
- package/dist/surface/tools/harness-explore.d.ts +125 -1
- package/dist/surface/tools/harness-explore.js +401 -15
- package/dist/surface/tools/harness-plan.d.ts +76 -0
- package/dist/surface/tools/harness-plan.js +156 -0
- package/dist/surface/tools/harness-toolset.js +12 -1
- package/dist/surface/tools/invoke-tool.js +82 -9
- package/dist/surface/tools/lease-hint.d.ts +8 -0
- package/dist/surface/tools/lease-hint.js +10 -0
- package/dist/surface/tools/lease-tools.d.ts +16 -28
- package/dist/surface/tools/lease-tools.js +53 -5
- package/dist/surface/tools/lineage-tools.js +1 -1
- package/dist/surface/tools/live-call-text.d.ts +6 -0
- package/dist/surface/tools/live-call-text.js +36 -2
- package/dist/surface/tools/observe-tools.js +69 -15
- package/dist/surface/tools/read/query-windowed.d.ts +1 -1
- package/dist/surface/tools/read/query-windowed.js +1 -1
- package/dist/surface/tools/read-tools.js +1 -2
- package/dist/surface/tools/real-input-attempt.d.ts +0 -5
- package/dist/surface/tools/real-input-attempt.js +1 -1
- package/dist/surface/tools/tool-kit.d.ts +23 -3
- package/dist/surface/tools/tool-kit.js +6 -1
- package/dist/surface/tools/tool-surface.js +17 -5
- package/dist/surface/tools/tools-helpers.d.ts +8 -7
- package/dist/surface/tools/tools-helpers.js +11 -13
- package/dist/surface/tools/tools.js +70 -30
- package/dist/telemetry/bug-found.js +32 -2
- package/dist/telemetry/feedback-context.js +3 -3
- package/dist/telemetry/feedback-local.d.ts +1 -0
- package/dist/telemetry/feedback-local.js +1 -3
- package/dist/telemetry/feedback.d.ts +1 -1
- package/dist/telemetry/harness-drive.d.ts +6 -0
- package/dist/telemetry/harness-drive.js +39 -0
- package/dist/telemetry/hud-metrics.d.ts +32 -0
- package/dist/telemetry/hud-metrics.js +95 -0
- package/dist/telemetry/mcp-connection.d.ts +14 -1
- package/dist/telemetry/mcp-connection.js +17 -2
- package/dist/telemetry/onboarding-firsts.d.ts +30 -1
- package/dist/telemetry/onboarding-firsts.js +54 -12
- package/dist/telemetry/session-metrics.d.ts +5 -0
- package/dist/telemetry/session-metrics.js +15 -1
- package/dist/telemetry/verification-of.js +31 -3
- package/dist/wire-journal.d.ts +31 -0
- package/dist/wire-journal.js +100 -0
- package/docs/README.md +1 -0
- package/docs/agent-cheatsheet.md +7 -3
- package/docs/autodrive.md +42 -2
- package/docs/benchmarks.md +1 -1
- package/docs/capabilities.mdx +1 -1
- package/docs/cli/cloud.mdx +11 -9
- package/docs/cli/doctor.mdx +1 -0
- package/docs/cli/init.mdx +1 -0
- package/docs/cli/report.mdx +44 -0
- package/docs/cli/status.mdx +35 -20
- package/docs/cli.mdx +8 -18
- package/docs/desktop.mdx +1 -1
- package/docs/faq.mdx +1 -1
- package/docs/flows.md +11 -0
- package/docs/frameworks.mdx +113 -1
- package/docs/install-agentic.mdx +36 -0
- package/docs/install-manual.mdx +1 -1
- package/docs/packages/tauri.mdx +1 -1
- package/docs/packages.mdx +1 -1
- package/docs/predicates.mdx +144 -4
- package/docs/system-map.md +6 -4
- package/docs/telemetry.md +2 -1
- package/docs/token-efficiency.md +2 -2
- package/docs/tools/overview.mdx +1 -1
- package/docs/tools/query.mdx +10 -10
- package/docs/troubleshooting.mdx +8 -2
- package/docs/usage.md +2 -2
- package/docs/what-is-recorded.md +62 -0
- package/package.json +5 -5
- package/dist/judgement/outcome/predicate-to-expect.d.ts +0 -44
- package/dist/judgement/outcome/predicate-to-expect.js +0 -148
|
@@ -52,12 +52,12 @@ declare const IntentRecordSchema: z.ZodObject<{
|
|
|
52
52
|
flow: z.ZodOptional<z.ZodString>;
|
|
53
53
|
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
54
54
|
}, "strip", z.ZodTypeAny, {
|
|
55
|
-
route?: string | undefined;
|
|
56
55
|
flow?: string | undefined;
|
|
56
|
+
route?: string | undefined;
|
|
57
57
|
files?: string[] | undefined;
|
|
58
58
|
}, {
|
|
59
|
-
route?: string | undefined;
|
|
60
59
|
flow?: string | undefined;
|
|
60
|
+
route?: string | undefined;
|
|
61
61
|
files?: string[] | undefined;
|
|
62
62
|
}>>;
|
|
63
63
|
provenBy: z.ZodOptional<z.ZodObject<{
|
|
@@ -94,15 +94,15 @@ declare const IntentRecordSchema: z.ZodObject<{
|
|
|
94
94
|
/** When it was last touched, so a stale-looking record can be told from an untouched one. */
|
|
95
95
|
updatedAt: z.ZodOptional<z.ZodNumber>;
|
|
96
96
|
}, "strip", z.ZodTypeAny, {
|
|
97
|
-
status: "proved" | "
|
|
97
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
98
98
|
state: "proved" | "declared" | "bound";
|
|
99
99
|
id: string;
|
|
100
100
|
subject: string;
|
|
101
101
|
statement: string;
|
|
102
102
|
declaredAt: number;
|
|
103
103
|
surface?: {
|
|
104
|
-
route?: string | undefined;
|
|
105
104
|
flow?: string | undefined;
|
|
105
|
+
route?: string | undefined;
|
|
106
106
|
files?: string[] | undefined;
|
|
107
107
|
} | undefined;
|
|
108
108
|
source?: string | undefined;
|
|
@@ -119,15 +119,15 @@ declare const IntentRecordSchema: z.ZodObject<{
|
|
|
119
119
|
statement: string;
|
|
120
120
|
}[] | undefined;
|
|
121
121
|
}, {
|
|
122
|
-
status: "proved" | "
|
|
122
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
123
123
|
state: "proved" | "declared" | "bound";
|
|
124
124
|
id: string;
|
|
125
125
|
subject: string;
|
|
126
126
|
statement: string;
|
|
127
127
|
declaredAt: number;
|
|
128
128
|
surface?: {
|
|
129
|
-
route?: string | undefined;
|
|
130
129
|
flow?: string | undefined;
|
|
130
|
+
route?: string | undefined;
|
|
131
131
|
files?: string[] | undefined;
|
|
132
132
|
} | undefined;
|
|
133
133
|
source?: string | undefined;
|
|
@@ -159,12 +159,12 @@ export declare const IntentShardSchema: z.ZodObject<{
|
|
|
159
159
|
flow: z.ZodOptional<z.ZodString>;
|
|
160
160
|
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
161
161
|
}, "strip", z.ZodTypeAny, {
|
|
162
|
-
route?: string | undefined;
|
|
163
162
|
flow?: string | undefined;
|
|
163
|
+
route?: string | undefined;
|
|
164
164
|
files?: string[] | undefined;
|
|
165
165
|
}, {
|
|
166
|
-
route?: string | undefined;
|
|
167
166
|
flow?: string | undefined;
|
|
167
|
+
route?: string | undefined;
|
|
168
168
|
files?: string[] | undefined;
|
|
169
169
|
}>>;
|
|
170
170
|
provenBy: z.ZodOptional<z.ZodObject<{
|
|
@@ -201,15 +201,15 @@ export declare const IntentShardSchema: z.ZodObject<{
|
|
|
201
201
|
/** When it was last touched, so a stale-looking record can be told from an untouched one. */
|
|
202
202
|
updatedAt: z.ZodOptional<z.ZodNumber>;
|
|
203
203
|
}, "strip", z.ZodTypeAny, {
|
|
204
|
-
status: "proved" | "
|
|
204
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
205
205
|
state: "proved" | "declared" | "bound";
|
|
206
206
|
id: string;
|
|
207
207
|
subject: string;
|
|
208
208
|
statement: string;
|
|
209
209
|
declaredAt: number;
|
|
210
210
|
surface?: {
|
|
211
|
-
route?: string | undefined;
|
|
212
211
|
flow?: string | undefined;
|
|
212
|
+
route?: string | undefined;
|
|
213
213
|
files?: string[] | undefined;
|
|
214
214
|
} | undefined;
|
|
215
215
|
source?: string | undefined;
|
|
@@ -226,15 +226,15 @@ export declare const IntentShardSchema: z.ZodObject<{
|
|
|
226
226
|
statement: string;
|
|
227
227
|
}[] | undefined;
|
|
228
228
|
}, {
|
|
229
|
-
status: "proved" | "
|
|
229
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
230
230
|
state: "proved" | "declared" | "bound";
|
|
231
231
|
id: string;
|
|
232
232
|
subject: string;
|
|
233
233
|
statement: string;
|
|
234
234
|
declaredAt: number;
|
|
235
235
|
surface?: {
|
|
236
|
-
route?: string | undefined;
|
|
237
236
|
flow?: string | undefined;
|
|
237
|
+
route?: string | undefined;
|
|
238
238
|
files?: string[] | undefined;
|
|
239
239
|
} | undefined;
|
|
240
240
|
source?: string | undefined;
|
|
@@ -255,15 +255,15 @@ export declare const IntentShardSchema: z.ZodObject<{
|
|
|
255
255
|
version: 1;
|
|
256
256
|
subject: string;
|
|
257
257
|
intents: Record<string, {
|
|
258
|
-
status: "proved" | "
|
|
258
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
259
259
|
state: "proved" | "declared" | "bound";
|
|
260
260
|
id: string;
|
|
261
261
|
subject: string;
|
|
262
262
|
statement: string;
|
|
263
263
|
declaredAt: number;
|
|
264
264
|
surface?: {
|
|
265
|
-
route?: string | undefined;
|
|
266
265
|
flow?: string | undefined;
|
|
266
|
+
route?: string | undefined;
|
|
267
267
|
files?: string[] | undefined;
|
|
268
268
|
} | undefined;
|
|
269
269
|
source?: string | undefined;
|
|
@@ -284,15 +284,15 @@ export declare const IntentShardSchema: z.ZodObject<{
|
|
|
284
284
|
version: 1;
|
|
285
285
|
subject: string;
|
|
286
286
|
intents: Record<string, {
|
|
287
|
-
status: "proved" | "
|
|
287
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
288
288
|
state: "proved" | "declared" | "bound";
|
|
289
289
|
id: string;
|
|
290
290
|
subject: string;
|
|
291
291
|
statement: string;
|
|
292
292
|
declaredAt: number;
|
|
293
293
|
surface?: {
|
|
294
|
-
route?: string | undefined;
|
|
295
294
|
flow?: string | undefined;
|
|
295
|
+
route?: string | undefined;
|
|
296
296
|
files?: string[] | undefined;
|
|
297
297
|
} | undefined;
|
|
298
298
|
source?: string | undefined;
|
|
@@ -311,7 +311,6 @@ export declare const IntentShardSchema: z.ZodObject<{
|
|
|
311
311
|
}>;
|
|
312
312
|
}>;
|
|
313
313
|
export type IntentShard = z.infer<typeof IntentShardSchema>;
|
|
314
|
-
export declare const summarise: (statement: string) => string;
|
|
315
314
|
/** One line per intent: enough to decide whether to open the shard, and no more. */
|
|
316
315
|
declare const IntentIndexEntrySchema: z.ZodObject<{
|
|
317
316
|
id: z.ZodString;
|
|
@@ -319,12 +318,12 @@ declare const IntentIndexEntrySchema: z.ZodObject<{
|
|
|
319
318
|
statement: z.ZodString;
|
|
320
319
|
status: z.ZodEnum<["proposed", "agreed", "proved", "stale"]>;
|
|
321
320
|
}, "strip", z.ZodTypeAny, {
|
|
322
|
-
status: "proved" | "
|
|
321
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
323
322
|
id: string;
|
|
324
323
|
subject: string;
|
|
325
324
|
statement: string;
|
|
326
325
|
}, {
|
|
327
|
-
status: "proved" | "
|
|
326
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
328
327
|
id: string;
|
|
329
328
|
subject: string;
|
|
330
329
|
statement: string;
|
|
@@ -338,19 +337,19 @@ export declare const IntentIndexSchema: z.ZodObject<{
|
|
|
338
337
|
statement: z.ZodString;
|
|
339
338
|
status: z.ZodEnum<["proposed", "agreed", "proved", "stale"]>;
|
|
340
339
|
}, "strip", z.ZodTypeAny, {
|
|
341
|
-
status: "proved" | "
|
|
340
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
342
341
|
id: string;
|
|
343
342
|
subject: string;
|
|
344
343
|
statement: string;
|
|
345
344
|
}, {
|
|
346
|
-
status: "proved" | "
|
|
345
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
347
346
|
id: string;
|
|
348
347
|
subject: string;
|
|
349
348
|
statement: string;
|
|
350
349
|
}>, "many">;
|
|
351
350
|
}, "strip", z.ZodTypeAny, {
|
|
352
351
|
entries: {
|
|
353
|
-
status: "proved" | "
|
|
352
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
354
353
|
id: string;
|
|
355
354
|
subject: string;
|
|
356
355
|
statement: string;
|
|
@@ -358,7 +357,7 @@ export declare const IntentIndexSchema: z.ZodObject<{
|
|
|
358
357
|
version: 1;
|
|
359
358
|
}, {
|
|
360
359
|
entries: {
|
|
361
|
-
status: "proved" | "
|
|
360
|
+
status: "proved" | "proposed" | "agreed" | "stale";
|
|
362
361
|
id: string;
|
|
363
362
|
subject: string;
|
|
364
363
|
statement: string;
|
|
@@ -74,7 +74,7 @@ export const IntentShardSchema = z.object({
|
|
|
74
74
|
* can do to a file meant to be read every session, which is the reason to keep it.
|
|
75
75
|
*/
|
|
76
76
|
const SUMMARY_MAX = 72;
|
|
77
|
-
|
|
77
|
+
const summarise = (statement) => statement.length <= SUMMARY_MAX ? statement : `${statement.slice(0, SUMMARY_MAX - 1).trimEnd()}…`;
|
|
78
78
|
/** One line per intent: enough to decide whether to open the shard, and no more. */
|
|
79
79
|
const IntentIndexEntrySchema = z.object({
|
|
80
80
|
id: z.string().min(1),
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { type Intent, type IntentSurface } from '@reticlehq/core/artifacts';
|
|
2
2
|
import type { FileSystemPort } from '../project/fs/fs-port.js';
|
|
3
3
|
import type { Clock } from '../../machine/clock.js';
|
|
4
|
+
/**
|
|
5
|
+
* The intent ledger's domain operations: declare, place, bind, discharge.
|
|
6
|
+
*
|
|
7
|
+
* Every operation is a PURE transition from core (`redeclareIntent`, `bindIntent`,
|
|
8
|
+
* `dischargeIntent`) handed to the ledger's atomic upsert. Storage is `IntentShardStore` —
|
|
9
|
+
* `.reticle/intent/<subject>/intent.json`, a flow's name being its subject — and this class writes no
|
|
10
|
+
* file of its own, so there is exactly one place an intent can be.
|
|
11
|
+
*/
|
|
4
12
|
export declare class IntentStore {
|
|
5
13
|
#private;
|
|
6
14
|
constructor(fs: FileSystemPort, root: string, clock: Clock);
|
|
@@ -12,7 +20,8 @@ export declare class IntentStore {
|
|
|
12
20
|
* Declare one or more intents.
|
|
13
21
|
*
|
|
14
22
|
* Batched because the marginal cost of the whole mechanism has to stay at one call per feature; an
|
|
15
|
-
* agent that must make five calls to declare five things will make none.
|
|
23
|
+
* agent that must make five calls to declare five things will make none. Saying an intent again
|
|
24
|
+
* does not unsay it: see `redeclareIntent` for what survives.
|
|
16
25
|
*/
|
|
17
26
|
declare(entries: readonly {
|
|
18
27
|
id: string;
|
|
@@ -22,13 +31,9 @@ export declare class IntentStore {
|
|
|
22
31
|
/**
|
|
23
32
|
* File a record under where it turned out to be about.
|
|
24
33
|
*
|
|
25
|
-
* Separate from `declare` because
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* the intent is ABOUT only exists after the consequence lands.
|
|
29
|
-
*
|
|
30
|
-
* Write-once: an existing surface is never overwritten. A record placed by an agent that named its
|
|
31
|
-
* own subject must not be re-filed by a later run that happened to be somewhere else.
|
|
34
|
+
* Separate from `declare` because an inline intent is declared BEFORE the action, and the route
|
|
35
|
+
* that describes it only exists after the consequence lands. Write-once: an existing surface is
|
|
36
|
+
* never overwritten. A flow named here moves the record into that flow's directory.
|
|
32
37
|
*/
|
|
33
38
|
place(id: string, surface: IntentSurface): Promise<boolean>;
|
|
34
39
|
/** Attach the predicate that would prove an intent. False when the id names nothing. */
|
|
@@ -1,115 +1,71 @@
|
|
|
1
|
-
import { bindIntent, declareIntent,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { IntentState, bindIntent, declareIntent, redeclareIntent, dischargeIntent, isActionLabel, } from '@reticlehq/core/artifacts';
|
|
2
|
+
import { IntentShardStore } from './intent-shard-store.js';
|
|
3
|
+
import { IntentStatus } from './intent-shard.js';
|
|
4
4
|
/**
|
|
5
|
-
* The intent ledger
|
|
5
|
+
* The intent ledger's domain operations: declare, place, bind, discharge.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* Every operation goes through the same file lock the other stores use, because two sessions driving
|
|
13
|
-
* one project is ordinary and a lost declaration would be silent.
|
|
7
|
+
* Every operation is a PURE transition from core (`redeclareIntent`, `bindIntent`,
|
|
8
|
+
* `dischargeIntent`) handed to the ledger's atomic upsert. Storage is `IntentShardStore` —
|
|
9
|
+
* `.reticle/intent/<subject>/intent.json`, a flow's name being its subject — and this class writes no
|
|
10
|
+
* file of its own, so there is exactly one place an intent can be.
|
|
14
11
|
*/
|
|
15
|
-
const JSON_INDENT = 2;
|
|
16
12
|
export class IntentStore {
|
|
17
|
-
#
|
|
18
|
-
#root;
|
|
13
|
+
#ledger;
|
|
19
14
|
#clock;
|
|
20
15
|
constructor(fs, root, clock) {
|
|
21
|
-
this.#
|
|
22
|
-
this.#root = root;
|
|
16
|
+
this.#ledger = new IntentShardStore(fs, root, clock);
|
|
23
17
|
this.#clock = clock;
|
|
24
18
|
}
|
|
25
|
-
#path() {
|
|
26
|
-
return reticleDirPaths(this.#root).intent;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Load the ledger, failing soft to empty.
|
|
30
|
-
*
|
|
31
|
-
* This is a git-checked file an agent can write and a human can hand-merge, so a malformed one is
|
|
32
|
-
* genuinely reachable — a conflict marker left in place is the obvious case. Throwing here would
|
|
33
|
-
* take down the verdict that was only asking what was still open, which trades a small problem for
|
|
34
|
-
* a large one.
|
|
35
|
-
*/
|
|
36
|
-
async #load() {
|
|
37
|
-
try {
|
|
38
|
-
const raw = await this.#fs.readFile(this.#path());
|
|
39
|
-
return parseIntentFile(JSON.parse(raw));
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return emptyIntentFile();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
/** Byte-stable: 2-space indent, one trailing newline. An unchanged ledger produces no diff. */
|
|
46
|
-
async #save(file) {
|
|
47
|
-
await this.#fs.mkdir(reticleDirPaths(this.#root).root);
|
|
48
|
-
await this.#fs.writeFile(this.#path(), `${JSON.stringify(file, null, JSON_INDENT)}\n`);
|
|
49
|
-
}
|
|
50
19
|
/** Every intent, in declaration order. */
|
|
51
20
|
async read() {
|
|
52
|
-
return
|
|
21
|
+
return this.#ledger.all();
|
|
53
22
|
}
|
|
54
23
|
/** Everything not yet proved — what an agent asking "am I done?" still owes. */
|
|
55
24
|
async open() {
|
|
56
|
-
|
|
25
|
+
// Stale is not owed: it is kept as history, not as work.
|
|
26
|
+
return (await this.#ledger.all()).filter((record) => IntentState.PROVED !== record.state && IntentStatus.STALE !== record.status);
|
|
57
27
|
}
|
|
58
28
|
/**
|
|
59
29
|
* Declare one or more intents.
|
|
60
30
|
*
|
|
61
31
|
* Batched because the marginal cost of the whole mechanism has to stay at one call per feature; an
|
|
62
|
-
* agent that must make five calls to declare five things will make none.
|
|
32
|
+
* agent that must make five calls to declare five things will make none. Saying an intent again
|
|
33
|
+
* does not unsay it: see `redeclareIntent` for what survives.
|
|
63
34
|
*/
|
|
64
35
|
async declare(entries) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
declared.push(stored);
|
|
77
|
-
}
|
|
78
|
-
await this.#save(file);
|
|
79
|
-
return declared;
|
|
80
|
-
});
|
|
36
|
+
const now = this.#clock.now();
|
|
37
|
+
const declared = [];
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
// A step label is a log line, not a rule: every route that declares comes through here.
|
|
40
|
+
if (isActionLabel(entry.statement))
|
|
41
|
+
continue;
|
|
42
|
+
const stored = await this.#ledger.upsert(entry.id, (existing) => redeclareIntent(existing, declareIntent({ ...entry, now })));
|
|
43
|
+
if (stored !== undefined)
|
|
44
|
+
declared.push(stored);
|
|
45
|
+
}
|
|
46
|
+
return declared;
|
|
81
47
|
}
|
|
82
48
|
/**
|
|
83
49
|
* File a record under where it turned out to be about.
|
|
84
50
|
*
|
|
85
|
-
* Separate from `declare` because
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* the intent is ABOUT only exists after the consequence lands.
|
|
89
|
-
*
|
|
90
|
-
* Write-once: an existing surface is never overwritten. A record placed by an agent that named its
|
|
91
|
-
* own subject must not be re-filed by a later run that happened to be somewhere else.
|
|
51
|
+
* Separate from `declare` because an inline intent is declared BEFORE the action, and the route
|
|
52
|
+
* that describes it only exists after the consequence lands. Write-once: an existing surface is
|
|
53
|
+
* never overwritten. A flow named here moves the record into that flow's directory.
|
|
92
54
|
*/
|
|
93
55
|
async place(id, surface) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const existing = file.intents[id];
|
|
56
|
+
let placed = false;
|
|
57
|
+
await this.#ledger.upsert(id, (existing) => {
|
|
97
58
|
if (existing === undefined || existing.surface !== undefined)
|
|
98
|
-
return
|
|
99
|
-
|
|
100
|
-
return
|
|
59
|
+
return undefined;
|
|
60
|
+
placed = true;
|
|
61
|
+
return { ...existing, surface };
|
|
101
62
|
});
|
|
63
|
+
return placed;
|
|
102
64
|
}
|
|
103
65
|
/** Attach the predicate that would prove an intent. False when the id names nothing. */
|
|
104
66
|
async bind(id, binding) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const existing = file.intents[id];
|
|
108
|
-
if (existing === undefined)
|
|
109
|
-
return false;
|
|
110
|
-
await this.#save(upsertIntent(file, bindIntent(existing, binding)));
|
|
111
|
-
return true;
|
|
112
|
-
});
|
|
67
|
+
const stored = await this.#ledger.upsert(id, (existing) => existing === undefined ? undefined : bindIntent(existing, binding));
|
|
68
|
+
return stored !== undefined;
|
|
113
69
|
}
|
|
114
70
|
/**
|
|
115
71
|
* Record that a verdict proved an intent.
|
|
@@ -118,16 +74,16 @@ export class IntentStore {
|
|
|
118
74
|
* and must never be the reason one fails to return.
|
|
119
75
|
*/
|
|
120
76
|
async discharge(id, proof) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const existing = file.intents[id];
|
|
77
|
+
let proved = false;
|
|
78
|
+
await this.#ledger.upsert(id, (existing) => {
|
|
124
79
|
if (existing === undefined)
|
|
125
|
-
return
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
128
|
-
return
|
|
129
|
-
|
|
130
|
-
return
|
|
80
|
+
return undefined;
|
|
81
|
+
const next = dischargeIntent(existing, proof);
|
|
82
|
+
if (next === existing)
|
|
83
|
+
return undefined;
|
|
84
|
+
proved = true;
|
|
85
|
+
return next;
|
|
131
86
|
});
|
|
87
|
+
return proved;
|
|
132
88
|
}
|
|
133
89
|
}
|
|
@@ -4,8 +4,10 @@ import { IntentShardStore } from './intent-shard-store.js';
|
|
|
4
4
|
import { IntentStatus } from './intent-shard.js';
|
|
5
5
|
import { ReticleTool } from '@reticlehq/core';
|
|
6
6
|
import { sessionIdShape } from '../../surface/tools/tool-kit.js';
|
|
7
|
+
import { PredicateSchema } from '@reticlehq/engine/question/predicate/predicate.js';
|
|
7
8
|
import { sessionRoot } from '../project/session-root.js';
|
|
8
9
|
import { asString } from '@reticlehq/core';
|
|
10
|
+
import { isActionLabel } from '@reticlehq/core/artifacts';
|
|
9
11
|
/**
|
|
10
12
|
* Declare what a change was SUPPOSED to make true, while somebody still knows.
|
|
11
13
|
*
|
|
@@ -24,11 +26,13 @@ const INDEX = 'index';
|
|
|
24
26
|
const SUBJECT = 'subject';
|
|
25
27
|
const GET = 'get';
|
|
26
28
|
const RECORD = 'record';
|
|
29
|
+
/** Why a step label is not stored, in words that say what to write instead. */
|
|
30
|
+
const STEP_LABEL_REFUSAL = 'describes a step that was done, not what must be true. State the rule, e.g. "saving the form shows the new row in the list"';
|
|
27
31
|
const MIGRATE = 'migrate';
|
|
28
32
|
export const INTENT_TOOLS = [
|
|
29
33
|
{
|
|
30
34
|
name: ReticleTool.INTENT,
|
|
31
|
-
description: 'Record what a change is SUPPOSED to make true, as a durable statement ABOUT THE PRODUCT that a teammate who was not here will understand in six months — name the behaviour, not this run or its step number, and never "renders cleanly", which nothing can check. It is SHARED memory: pooled per project and read back by later agents. Capture it while you still know — then verification does not have to re-derive it from the DOM later. { action:"declare", intents:[{ id, statement, surface? }] } takes prose and needs NO predicate: at declare time there is often no route, no ref and no code yet, and a predicate demanded there is just a mechanism. Declare EARLY (as you build) and batch them — one call per feature is the whole budget. { action:"bind", id, binding } attaches the predicate that would prove it once you know how; an intent with no binding is not a failure, it is the most interesting row in the ledger — something meant that nothing can currently prove. { action:"list" } returns what is still open. Stored in .reticle/intent.json, git-checked so a human sees in review if an intent was later narrowed to match what was easy to prove.',
|
|
35
|
+
description: 'Record what a change is SUPPOSED to make true, as a durable statement ABOUT THE PRODUCT that a teammate who was not here will understand in six months — name the behaviour, not this run or its step number, and never "renders cleanly", which nothing can check. It is SHARED memory: pooled per project and read back by later agents. Capture it while you still know — then verification does not have to re-derive it from the DOM later. { action:"declare", intents:[{ id, statement, surface? }] } takes prose and needs NO predicate: at declare time there is often no route, no ref and no code yet, and a predicate demanded there is just a mechanism. Declare EARLY (as you build) and batch them — one call per feature is the whole budget. { action:"bind", id, binding } attaches the predicate that would prove it once you know how; an intent with no binding is not a failure, it is the most interesting row in the ledger — something meant that nothing can currently prove. { action:"list" } returns what is still open. Stored in .reticle/intent/<subject>/intent.json (a flow name is its subject), git-checked so a human sees in review if an intent was later narrowed to match what was easy to prove.',
|
|
32
36
|
example: {
|
|
33
37
|
action: DECLARE,
|
|
34
38
|
intents: [
|
|
@@ -56,8 +60,8 @@ export const INTENT_TOOLS = [
|
|
|
56
60
|
.describe('record only: how settled it is. Defaults to proposed.'),
|
|
57
61
|
intents: z
|
|
58
62
|
.array(z.object({
|
|
59
|
-
id: z.string(),
|
|
60
|
-
statement: z.string(),
|
|
63
|
+
id: z.string().min(1),
|
|
64
|
+
statement: z.string().min(1),
|
|
61
65
|
surface: z
|
|
62
66
|
.object({
|
|
63
67
|
route: z.string().optional(),
|
|
@@ -69,10 +73,19 @@ export const INTENT_TOOLS = [
|
|
|
69
73
|
.optional()
|
|
70
74
|
.describe('declare only. Batchable — declare every intent for a feature in one call.'),
|
|
71
75
|
id: z.string().optional().describe('bind only: which intent the predicate proves.'),
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
/*
|
|
77
|
+
* The predicate schema, not `unknown`.
|
|
78
|
+
*
|
|
79
|
+
* The description has always said "in reticle_assert's shape" and the type said "anything",
|
|
80
|
+
* so a client reading the surface to build this call learned the field's name and nothing
|
|
81
|
+
* else — the same degradation the recursive `until` predicate suffered when it was converted
|
|
82
|
+
* without the SDK's own options. This one was not a converter bug: it was declared that way.
|
|
83
|
+
* Caught by `weakest-client-schemas.test.ts`, which is the first thing that ever looked.
|
|
84
|
+
*
|
|
85
|
+
* Accepting the real shape also means a malformed binding is refused at the boundary instead
|
|
86
|
+
* of being written into the ledger and failing later against a verdict it can never satisfy.
|
|
87
|
+
*/
|
|
88
|
+
binding: PredicateSchema.optional().describe("bind only: the predicate that would prove it, in reticle_assert's shape."),
|
|
76
89
|
...sessionIdShape,
|
|
77
90
|
},
|
|
78
91
|
outputSchema: {
|
|
@@ -81,6 +94,10 @@ export const INTENT_TOOLS = [
|
|
|
81
94
|
.optional()
|
|
82
95
|
.describe('The intents this call declared, or on `list` everything still open — each { id, statement, state, declaredAt, binding?, surface?, provenBy?, amended? }. `state` is declared (prose only), bound (a predicate exists), or proved (a verdict satisfied it).'),
|
|
83
96
|
bound: z.boolean().optional().describe('bind only: false when the id names no intent.'),
|
|
97
|
+
refused: z
|
|
98
|
+
.array(z.object({ id: z.string(), reason: z.string() }))
|
|
99
|
+
.optional()
|
|
100
|
+
.describe('declare only: statements not stored, and why.'),
|
|
84
101
|
path: z.string().optional().describe('Where the ledger was written.'),
|
|
85
102
|
entries: z
|
|
86
103
|
.array(z.unknown())
|
|
@@ -130,28 +147,22 @@ export const INTENT_TOOLS = [
|
|
|
130
147
|
return { bound: await store.bind(id, args['binding']) };
|
|
131
148
|
}
|
|
132
149
|
if (LIST === action) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
* `.reticle/intent/`. Listing only the flat one meant a recorded intent could not be found
|
|
138
|
-
* again by the agent that had just written it — and the lesson an agent draws from that is
|
|
139
|
-
* "the intent does not exist", not "there are two stores".
|
|
140
|
-
*
|
|
141
|
-
* Merged HERE rather than inside either store: this tool is the one seam that knows both
|
|
142
|
-
* exist, and neither store should have to learn the other's layout to stay honest.
|
|
143
|
-
*/
|
|
144
|
-
const flat = await store.open();
|
|
145
|
-
const seen = new Set(flat.map((intent) => intent.id));
|
|
146
|
-
const fromShards = (await shards.all()).filter((record) => !seen.has(record.id));
|
|
147
|
-
return { intents: [...flat, ...fromShards] };
|
|
150
|
+
// One ledger, so one read. This merged two stores while `declare` and `record` wrote two
|
|
151
|
+
// different files; kept past that, it would add back every PROVED intent to a list that
|
|
152
|
+
// promises only what is still open.
|
|
153
|
+
return { intents: await store.open() };
|
|
148
154
|
}
|
|
149
155
|
const raw = args['intents'];
|
|
150
156
|
const entries = Array.isArray(raw)
|
|
151
157
|
? raw
|
|
152
158
|
: [];
|
|
153
159
|
const declared = await store.declare(entries);
|
|
154
|
-
|
|
160
|
+
// Said, not swallowed: an agent that declared something and finds nothing stored would
|
|
161
|
+
// otherwise conclude the ledger lost it.
|
|
162
|
+
const refused = entries
|
|
163
|
+
.filter((entry) => isActionLabel(entry.statement))
|
|
164
|
+
.map((entry) => ({ id: entry.id, reason: STEP_LABEL_REFUSAL }));
|
|
165
|
+
return { intents: declared, ...(0 === refused.length ? {} : { refused }), path: root };
|
|
155
166
|
},
|
|
156
167
|
},
|
|
157
168
|
];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { dirname } from 'node:path';
|
|
2
|
+
import { writeFileAtomic } from '../project/fs/write-atomic.js';
|
|
2
3
|
import { reticleDirPaths } from '../project/dir/reticle-dir.js';
|
|
3
4
|
import { AmbientFileSchema } from './on-disk/ambient-file.js';
|
|
4
5
|
import { onlyStableAmbient } from '@reticlehq/engine/window/ambient.js';
|
|
@@ -45,8 +46,6 @@ export class AmbientStore {
|
|
|
45
46
|
// numbering, so persisting it teaches the next session to suppress an element it never saw.
|
|
46
47
|
const regions = onlyStableAmbient(counts);
|
|
47
48
|
const body = `${JSON.stringify({ version: AMBIENT_FILE_VERSION, regions }, null, 2)}\n`;
|
|
48
|
-
|
|
49
|
-
await this.#fs.writeFile(tmp, body);
|
|
50
|
-
await this.#fs.rename(tmp, this.#path);
|
|
49
|
+
await writeFileAtomic(this.#fs, this.#path, body);
|
|
51
50
|
}
|
|
52
51
|
}
|
|
@@ -3,6 +3,17 @@ import { JournalRecorder, type JournalReader } from './journal-recorder.js';
|
|
|
3
3
|
/** The minimal Session surface the journal attachment needs (Session satisfies it structurally). */
|
|
4
4
|
export interface JournalTarget {
|
|
5
5
|
readonly id: string;
|
|
6
|
+
/**
|
|
7
|
+
* The `.reticle` this session's artifacts belong in, stamped on session-create before this runs.
|
|
8
|
+
*
|
|
9
|
+
* The journal used to go to the daemon's own root — wherever the agent was launched — while the
|
|
10
|
+
* run artifact written at teardown already used this one. The journal is the worse half to
|
|
11
|
+
* misroute: it carries URLs, request and response bodies and DOM text from the app under test, so
|
|
12
|
+
* a daemon started in a backend wrote that app's traffic into a repository nobody instrumented,
|
|
13
|
+
* and the `.reticle/.gitignore` meant to keep journals out of a shared repo was being written into
|
|
14
|
+
* the OTHER tree. Undefined only when no project could be resolved, which keeps the old fallback.
|
|
15
|
+
*/
|
|
16
|
+
readonly artifactRoot?: string | undefined;
|
|
6
17
|
/** Milliseconds since the session connected — the recorder's injected clock. */
|
|
7
18
|
elapsed(): number;
|
|
8
19
|
setJournal(recorder: JournalRecorder, reader?: JournalReader): void;
|
|
@@ -19,7 +19,7 @@ export function makeJournalAttach(deps) {
|
|
|
19
19
|
log('journal_skipped_unsafe_session_id', { sessionId: session.id });
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
const journal = new SessionJournal(deps.fs, deps.reticleRoot, session.id);
|
|
22
|
+
const journal = new SessionJournal(deps.fs, session.artifactRoot ?? deps.reticleRoot, session.id);
|
|
23
23
|
// Same SessionJournal is both the write sink and the read fall-through for queries after eviction.
|
|
24
24
|
session.setJournal(new JournalRecorder(journal, { now: () => session.elapsed() }), journal);
|
|
25
25
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { routeTemplate } from './route-template.js';
|
|
1
2
|
import { compareSegment, MIN_ENVELOPE_SAMPLES, } from './envelope.js';
|
|
2
3
|
function headlineFor(report) {
|
|
3
4
|
const truncNote = report.truncatedSegments > 0
|
|
@@ -31,7 +32,9 @@ export function buildDeviationReport(envelopes, segments, zThreshold) {
|
|
|
31
32
|
truncated += 1;
|
|
32
33
|
continue;
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
// The SAME key the service accumulates under — a lookup on the observed path would miss every
|
|
36
|
+
// envelope on an app with ids in its URLs, which is the case this templating exists for.
|
|
37
|
+
const envelope = envelopes.get(routeTemplate(segment.route));
|
|
35
38
|
if (envelope === undefined || envelope.samples < MIN_ENVELOPE_SAMPLES)
|
|
36
39
|
continue;
|
|
37
40
|
judged += 1;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { routeTemplate } from './route-template.js';
|
|
1
2
|
import { addSegmentToEnvelope, emptyEnvelope } from './envelope.js';
|
|
2
3
|
import { buildDeviationReport } from './deviation-report.js';
|
|
3
4
|
import { withFileLock } from '../project/file-lock.js';
|
|
@@ -22,8 +23,15 @@ export async function reportAndAccumulate(store, segments, zThreshold) {
|
|
|
22
23
|
// Never learn from a truncated sample — its understated counts would poison the baseline.
|
|
23
24
|
if (true === segment.truncated)
|
|
24
25
|
continue;
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
/*
|
|
27
|
+
* Keyed on the route TEMPLATE, not the observed path. Keyed on the path, an app with ids in
|
|
28
|
+
* its URLs mints one envelope per id, every envelope holds a single sample, and nothing ever
|
|
29
|
+
* reaches MIN_ENVELOPE_SAMPLES — so the deviation report answers "envelope too new" forever
|
|
30
|
+
* and the feature never turns on. See route-template.ts.
|
|
31
|
+
*/
|
|
32
|
+
const key = routeTemplate(segment.route);
|
|
33
|
+
const current = envelopes.get(key) ?? emptyEnvelope(key);
|
|
34
|
+
envelopes.set(key, addSegmentToEnvelope(current, segment));
|
|
27
35
|
}
|
|
28
36
|
await store.save(envelopes);
|
|
29
37
|
return report;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FlowName, Predicate } from '@reticlehq/core';
|
|
2
2
|
/**
|
|
3
3
|
* What this module needs a recorded step to BE, named structurally rather than imported.
|
|
4
4
|
*
|
|
@@ -12,7 +12,7 @@ export interface TapeStep {
|
|
|
12
12
|
tool: string;
|
|
13
13
|
args: Record<string, unknown>;
|
|
14
14
|
stable: boolean;
|
|
15
|
-
expect?:
|
|
15
|
+
expect?: Predicate;
|
|
16
16
|
/** Recorder-internal, and the field journeys are cut on. Never written to the saved flow. */
|
|
17
17
|
route?: string;
|
|
18
18
|
}
|