@reticlehq/server 3.4.0 → 3.6.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/README.md +1 -1
- package/SKILL.md +16 -8
- package/dist/chromium-launch-options.d.ts +3 -1
- package/dist/chromium-launch-options.js +2 -1
- package/dist/command/cli/adhoc-verdict.d.ts +1 -0
- package/dist/command/cli/adhoc-verdict.js +6 -3
- package/dist/command/cli/answers/open-note.d.ts +2 -0
- package/dist/command/cli/answers/open-note.js +22 -0
- package/dist/command/cli/auth/cloud-session.d.ts +4 -4
- package/dist/command/cli/auth/device-flow.d.ts +2 -2
- package/dist/command/cli/cli-flow-commands.js +4 -8
- package/dist/command/cli/cli-parse.d.ts +1 -1
- package/dist/command/cli/cli-parse.js +13 -11
- package/dist/command/cli/cli-verify.d.ts +1 -1
- package/dist/command/cli/cli-verify.js +35 -25
- package/dist/command/cli/cloud-cli.js +110 -12
- package/dist/command/cli/cloud-login.d.ts +9 -1
- package/dist/command/cli/cloud-login.js +43 -8
- package/dist/command/cli/demo/demo-page.js +11 -3
- package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
- package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
- package/dist/command/cli/drive/drive-attach.d.ts +27 -2
- package/dist/command/cli/drive/drive-attach.js +71 -4
- package/dist/command/cli/drive/drive-command.d.ts +2 -1
- package/dist/command/cli/drive/drive-command.js +13 -7
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +4 -1
- package/dist/command/cli/ports/port-holder.d.ts +10 -0
- package/dist/command/cli/ports/port-holder.js +24 -0
- package/dist/command/cli/setup-mcp-cli.js +15 -5
- package/dist/command/cli/tutorial.d.ts +2 -2
- package/dist/command/cli/tutorial.js +6 -9
- package/dist/command/cli.d.ts +6 -0
- package/dist/command/cli.js +45 -23
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
- package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
- package/dist/command/daemon/daemon-resolve.d.ts +14 -0
- package/dist/command/daemon/daemon-resolve.js +33 -2
- package/dist/command/setup/agent-writer.d.ts +1 -1
- package/dist/command/setup/agent-writer.js +3 -2
- package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
- package/dist/command/setup/bringup/connect-lease.js +1 -0
- package/dist/command/setup/bringup/dev-server-wait.d.ts +10 -0
- package/dist/command/setup/bringup/dev-server-wait.js +20 -1
- package/dist/command/setup/init/init-port.d.ts +4 -0
- package/dist/command/setup/init/init-port.js +10 -0
- package/dist/command/setup/init/init-runtime.d.ts +10 -0
- package/dist/command/setup/init/init-runtime.js +71 -9
- package/dist/command/setup/node-effects.js +8 -2
- package/dist/command/setup/remaining-steps.js +2 -1
- package/dist/command/setup/run-setup.d.ts +7 -0
- package/dist/command/setup/run-setup.js +38 -25
- package/dist/command/setup/setup-command.d.ts +2 -1
- package/dist/command/setup/setup-command.js +2 -0
- package/dist/command/setup/setup-mcp.d.ts +2 -0
- package/dist/command/setup/setup-mcp.js +14 -5
- package/dist/command/version/peer-announce.d.ts +6 -2
- package/dist/command/version/peer-announce.js +8 -6
- package/dist/command/version/version-nudge.d.ts +17 -3
- package/dist/command/version/version-nudge.js +25 -4
- package/dist/command/version/version-skew.js +11 -2
- package/dist/features/crawl/crawl-tools.js +4 -0
- package/dist/features/crawl/crawl.d.ts +6 -0
- package/dist/features/crawl/crawl.js +9 -1
- package/dist/features/exhaust/ledger.d.ts +7 -0
- package/dist/features/exhaust/ledger.js +35 -9
- package/dist/features/harness/app-findings.d.ts +2 -0
- package/dist/features/harness/app-findings.js +52 -0
- package/dist/features/harness/drive-report.d.ts +27 -1
- package/dist/features/harness/drive-report.js +162 -11
- package/dist/features/harness/drivers.d.ts +10 -14
- package/dist/features/harness/drivers.js +10 -14
- package/dist/features/harness/fill-values.d.ts +3 -69
- package/dist/features/harness/fill-values.js +3 -133
- package/dist/features/harness/goals.d.ts +21 -0
- package/dist/features/harness/goals.js +77 -0
- package/dist/features/harness/harness.d.ts +21 -0
- package/dist/features/harness/harness.js +69 -2
- package/dist/features/harness/platform/drive-target.d.ts +30 -0
- package/dist/features/harness/platform/drive-target.js +81 -0
- package/dist/features/harness/platform/local-apps.d.ts +94 -0
- package/dist/features/harness/platform/local-apps.js +204 -0
- package/dist/features/harness/platform/remote-drive.d.ts +180 -0
- package/dist/features/harness/platform/remote-drive.js +365 -0
- package/dist/features/harness/platform/script.d.ts +48 -0
- package/dist/features/harness/platform/script.js +128 -0
- package/dist/features/harness/platform/server-driver.d.ts +41 -0
- package/dist/features/harness/platform/server-driver.js +179 -0
- package/dist/features/harness/platform-config.d.ts +7 -0
- package/dist/features/harness/platform-config.js +14 -2
- package/dist/features/harness/script/app-controls.d.ts +5 -0
- package/dist/features/harness/script/app-controls.js +40 -0
- package/dist/features/harness/script/lane-ids.d.ts +14 -0
- package/dist/features/harness/script/lane-ids.js +16 -0
- package/dist/features/harness/script/script-run.d.ts +41 -0
- package/dist/features/harness/script/script-run.js +299 -0
- package/dist/features/license/license.d.ts +2 -2
- package/dist/features/visual/visual-tools.d.ts +10 -1
- package/dist/features/visual/visual-tools.js +40 -3
- package/dist/hooks/driven-by.d.ts +4 -0
- package/dist/hooks/driven-by.js +16 -0
- package/dist/hooks/hook-commands.js +15 -4
- package/dist/hooks/tool-log.d.ts +9 -0
- package/dist/hooks/tool-log.js +29 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +91 -89
- package/dist/judgement/capsule/capsule-store.d.ts +4 -4
- package/dist/judgement/runs/artifact/build-verification-run.js +6 -0
- package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
- package/dist/judgement/runs/artifact/replay-mapping.js +16 -6
- package/dist/judgement/runs/artifact/run-store.d.ts +1 -1
- package/dist/judgement/runs/artifact/run-store.js +26 -1
- package/dist/judgement/runs/drive-run.d.ts +22 -0
- package/dist/judgement/runs/drive-run.js +99 -1
- package/dist/judgement/runs/repair-prompt.js +1 -1
- package/dist/judgement/runs/reticle-runner.js +8 -1
- package/dist/judgement/runs/verification-sync.d.ts +3 -2
- package/dist/judgement/runs/verification-sync.js +4 -3
- package/dist/language/flows/change/gate.d.ts +10 -0
- package/dist/language/flows/change/gate.js +22 -0
- package/dist/language/flows/decision.js +34 -0
- package/dist/language/flows/flow-anchor.d.ts +54 -8
- package/dist/language/flows/flow-anchor.js +88 -3
- package/dist/language/flows/flow-cross-step.d.ts +15 -0
- package/dist/language/flows/flow-cross-step.js +21 -0
- package/dist/language/flows/flow-learning.js +8 -11
- package/dist/language/flows/flow-mutate-tools.js +5 -3
- package/dist/language/flows/flow-replay-run.d.ts +23 -9
- package/dist/language/flows/flow-replay-run.js +101 -94
- package/dist/language/flows/flow-replay.d.ts +23 -1
- package/dist/language/flows/flow-replay.js +92 -19
- package/dist/language/flows/flow-scope.js +5 -1
- package/dist/language/flows/flow-step-runners.d.ts +20 -2
- package/dist/language/flows/flow-step-runners.js +236 -42
- package/dist/language/flows/flow-store-for-session.d.ts +2 -2
- package/dist/language/flows/flow-store-for-session.js +2 -2
- package/dist/language/flows/flow-tools.js +58 -34
- package/dist/language/flows/flows.js +5 -2
- package/dist/language/flows/heal-run.js +6 -4
- package/dist/language/flows/recording/flake.d.ts +2 -2
- package/dist/language/flows/recording/tape/recordings.d.ts +30 -4
- package/dist/language/flows/recording/tape/recordings.js +40 -8
- package/dist/language/flows/replay-from-hud.d.ts +20 -0
- package/dist/language/flows/replay-from-hud.js +51 -0
- package/dist/language/flows/replay.d.ts +9 -5
- package/dist/language/flows/replay.js +27 -9
- package/dist/language/flows/suite/suite-flakes.js +2 -0
- package/dist/language/flows/suite-selection.d.ts +2 -15
- package/dist/language/flows/suite-selection.js +4 -3
- package/dist/language/flows/verify-change-tools.js +8 -4
- package/dist/launch-chromium.d.ts +27 -5
- package/dist/launch-chromium.js +38 -8
- package/dist/memory/cloud/cloud-config.d.ts +12 -0
- package/dist/memory/cloud/cloud-config.js +15 -0
- package/dist/memory/cloud/cloud-sync.d.ts +17 -14
- package/dist/memory/cloud/cloud-sync.js +12 -1
- package/dist/memory/cloud/harness-config.d.ts +26 -1
- package/dist/memory/cloud/harness-config.js +99 -4
- package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
- package/dist/memory/cloud/hud-notices-source.js +128 -0
- package/dist/memory/cloud/memory-scope.d.ts +144 -0
- package/dist/memory/cloud/memory-scope.js +205 -0
- package/dist/memory/cloud/sync-cycle.d.ts +21 -3
- package/dist/memory/cloud/sync-cycle.js +45 -5
- package/dist/memory/cloud/sync-daemon.js +7 -5
- package/dist/memory/cloud/sync-disk.d.ts +1 -1
- package/dist/memory/cloud/sync-disk.js +5 -8
- package/dist/memory/impact/account-watch.d.ts +19 -0
- package/dist/memory/impact/account-watch.js +34 -0
- package/dist/memory/impact/impact-recorder.d.ts +8 -0
- package/dist/memory/impact/impact-recorder.js +12 -2
- package/dist/memory/impact/impact-store.d.ts +16 -0
- package/dist/memory/impact/impact-store.js +142 -26
- package/dist/memory/intent/intent-shard.d.ts +2 -2
- package/dist/memory/intent/intent-tools.js +88 -5
- package/dist/memory/journal/envelope.d.ts +16 -16
- package/dist/memory/journal/journal-query.d.ts +14 -0
- package/dist/memory/journal/journal-query.js +15 -0
- package/dist/memory/journal/journal-recorder.js +7 -1
- package/dist/memory/journal/on-disk/retention.d.ts +3 -0
- package/dist/memory/journal/on-disk/retention.js +5 -0
- package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
- package/dist/memory/journal/on-disk/workspace-tiers.js +7 -4
- package/dist/memory/journal/session-end.js +6 -4
- package/dist/memory/project/artifact-root-resolver.d.ts +36 -1
- package/dist/memory/project/artifact-root-resolver.js +134 -26
- package/dist/memory/project/artifact-root.d.ts +42 -5
- package/dist/memory/project/artifact-root.js +87 -8
- package/dist/memory/project/dir/reticle-dir.d.ts +4 -2
- package/dist/memory/project/dir/reticle-dir.js +3 -1
- package/dist/memory/project/project-tools.js +22 -3
- package/dist/memory/project/session-root.d.ts +24 -1
- package/dist/memory/project/session-root.js +41 -5
- package/dist/memory/project/sync-status.d.ts +39 -0
- package/dist/memory/project/sync-status.js +90 -0
- package/dist/memory/recall/memory-tools.js +2 -0
- package/dist/memory/recall/project-memory.d.ts +19 -0
- package/dist/memory/recall/project-memory.js +45 -6
- package/dist/portal/bridge/bridge.d.ts +7 -4
- package/dist/portal/bridge/bridge.js +25 -3
- package/dist/portal/bridge/pairing-token.d.ts +9 -0
- package/dist/portal/bridge/pairing-token.js +17 -0
- package/dist/portal/input/real-input.d.ts +81 -10
- package/dist/portal/input/real-input.js +207 -22
- package/dist/portal/input/viewport-tools.js +19 -9
- package/dist/portal/pool/browser-pool.d.ts +22 -9
- package/dist/portal/pool/browser-pool.js +70 -35
- package/dist/portal/pool/playwright-launcher.d.ts +13 -0
- package/dist/portal/pool/playwright-launcher.js +17 -1
- package/dist/portal/pool/pool-contract.d.ts +7 -4
- package/dist/portal/session/command-payload.d.ts +8 -0
- package/dist/portal/session/command-payload.js +19 -0
- package/dist/portal/session/dev-server/dev-command.d.ts +12 -0
- package/dist/portal/session/dev-server/dev-command.js +61 -12
- package/dist/portal/session/facts/departure-note.d.ts +22 -0
- package/dist/portal/session/facts/departure-note.js +47 -0
- package/dist/portal/session/facts/session-replaced.d.ts +5 -0
- package/dist/portal/session/facts/session-replaced.js +5 -0
- package/dist/portal/session/first-run-wiring.d.ts +42 -0
- package/dist/portal/session/first-run-wiring.js +132 -0
- package/dist/portal/session/human/notes-ledger.d.ts +20 -0
- package/dist/portal/session/human/notes-ledger.js +55 -0
- package/dist/portal/session/human/review-store.d.ts +12 -0
- package/dist/portal/session/human/review-store.js +18 -10
- package/dist/portal/session/live-control-tools.d.ts +0 -13
- package/dist/portal/session/live-control-tools.js +28 -3
- package/dist/portal/session/no-session-diagnosis.d.ts +7 -0
- package/dist/portal/session/no-session-diagnosis.js +15 -0
- package/dist/portal/session/no-session-next-action.d.ts +11 -0
- package/dist/portal/session/no-session-next-action.js +31 -5
- package/dist/portal/session/no-session-watch.d.ts +14 -1
- package/dist/portal/session/no-session-watch.js +63 -10
- package/dist/portal/session/presence/session-mirror.js +3 -0
- package/dist/portal/session/serving-directory.d.ts +27 -0
- package/dist/portal/session/serving-directory.js +45 -0
- package/dist/portal/session/session-health.d.ts +7 -0
- package/dist/portal/session/session-health.js +6 -0
- package/dist/portal/session/session-info.d.ts +8 -1
- package/dist/portal/session/session-info.js +6 -0
- package/dist/portal/session/session-manager.d.ts +21 -0
- package/dist/portal/session/session-manager.js +44 -8
- package/dist/portal/session/session-reaper.js +4 -1
- package/dist/portal/session/session-successor.d.ts +5 -0
- package/dist/portal/session/session-tools.js +26 -3
- package/dist/portal/session/session.d.ts +12 -10
- package/dist/portal/session/session.js +30 -31
- package/dist/start-options.d.ts +6 -0
- package/dist/status-payload.d.ts +10 -0
- package/dist/status-payload.js +23 -0
- package/dist/surface/http-server.d.ts +1 -1
- package/dist/surface/http-server.js +15 -4
- package/dist/surface/mcp/mcp-proxy.d.ts +5 -0
- package/dist/surface/mcp/mcp-proxy.js +36 -5
- package/dist/surface/mcp/mcp.d.ts +11 -6
- package/dist/surface/mcp/mcp.js +28 -14
- package/dist/surface/mcp/proxy/proxy-log.js +3 -5
- package/dist/surface/mcp/server-instructions.d.ts +4 -2
- package/dist/surface/mcp/server-instructions.js +14 -4
- package/dist/surface/mcp/shared-params.js +2 -2
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
- package/dist/surface/tools/act/settle-in-flight.js +25 -3
- package/dist/surface/tools/act-sequence-tool.js +2 -2
- package/dist/surface/tools/act-tools.js +25 -9
- package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
- package/dist/surface/tools/assert/assert-verdict.js +17 -2
- package/dist/surface/tools/browser-tools.js +8 -1
- package/dist/surface/tools/chat-drives.d.ts +26 -0
- package/dist/surface/tools/chat-drives.js +165 -0
- package/dist/surface/tools/dynamic-tools.js +29 -2
- package/dist/surface/tools/empty-session-list.d.ts +41 -0
- package/dist/surface/tools/empty-session-list.js +80 -0
- package/dist/surface/tools/error-recovery.d.ts +6 -0
- package/dist/surface/tools/error-recovery.js +38 -6
- package/dist/surface/tools/explore-tools.d.ts +10 -1
- package/dist/surface/tools/explore-tools.js +82 -13
- package/dist/surface/tools/feedback-tools.js +14 -0
- package/dist/surface/tools/harness-explore.d.ts +96 -14
- package/dist/surface/tools/harness-explore.js +227 -202
- package/dist/surface/tools/harness-plan.d.ts +12 -0
- package/dist/surface/tools/harness-plan.js +31 -0
- package/dist/surface/tools/harness-script.d.ts +8 -0
- package/dist/surface/tools/harness-script.js +342 -0
- package/dist/surface/tools/harness-toolset.d.ts +14 -1
- package/dist/surface/tools/harness-toolset.js +77 -6
- package/dist/surface/tools/invoke-tool.js +64 -9
- package/dist/surface/tools/lease-seed.d.ts +29 -0
- package/dist/surface/tools/lease-seed.js +123 -0
- package/dist/surface/tools/lease-tools.d.ts +3 -23
- package/dist/surface/tools/lease-tools.js +30 -131
- package/dist/surface/tools/live-call-text.js +2 -2
- package/dist/surface/tools/next-step.d.ts +19 -0
- package/dist/surface/tools/next-step.js +159 -0
- package/dist/surface/tools/observe-tools.js +2 -4
- package/dist/surface/tools/platform-moment.d.ts +12 -0
- package/dist/surface/tools/platform-moment.js +168 -0
- package/dist/surface/tools/query-hint-schema.d.ts +7 -0
- package/dist/surface/tools/query-hint-schema.js +10 -0
- package/dist/surface/tools/read-tools.js +8 -2
- package/dist/surface/tools/real-input-attempt.js +96 -13
- package/dist/surface/tools/tool-kit.d.ts +25 -1
- package/dist/surface/tools/tool-kit.js +4 -6
- package/dist/surface/tools/tools.js +20 -48
- package/dist/telemetry/argument-shape.js +1 -1
- package/dist/telemetry/hud-metrics.d.ts +2 -0
- package/dist/telemetry/hud-metrics.js +17 -0
- package/dist/telemetry/onboarding-firsts.d.ts +2 -2
- package/dist/telemetry/onboarding-firsts.js +2 -2
- package/dist/telemetry/telemetry.d.ts +12 -0
- package/dist/telemetry/telemetry.js +43 -14
- package/dist/telemetry/verification-of.js +1 -0
- package/dist/wire-journal.js +4 -1
- package/docs/README.md +1 -1
- package/docs/actions.mdx +1 -2
- package/docs/agent-cheatsheet.md +1 -1
- package/docs/autodrive.md +29 -25
- package/docs/cli/cloud.mdx +6 -4
- package/docs/cli/doctor.mdx +6 -0
- package/docs/cli/drive.mdx +8 -2
- package/docs/cli/init.mdx +11 -13
- package/docs/cli/status.mdx +5 -1
- package/docs/cli/version.mdx +3 -3
- package/docs/cli.mdx +14 -8
- package/docs/desktop.mdx +5 -1
- package/docs/environment.mdx +3 -7
- package/docs/getting-started.md +14 -2
- package/docs/human-control.md +1 -2
- package/docs/index.mdx +4 -3
- package/docs/install-agentic.mdx +1 -1
- package/docs/install-manual.mdx +2 -2
- package/docs/packages/next.mdx +3 -0
- package/docs/packages/tauri.mdx +2 -2
- package/docs/packages/vite-plugin.mdx +24 -1
- package/docs/packages.mdx +1 -1
- package/docs/quickstart.mdx +23 -11
- package/docs/telemetry.md +1 -1
- package/docs/tools/act.mdx +1 -1
- package/docs/tools/session-and-feedback.mdx +9 -9
- package/docs/usage.md +5 -3
- package/docs/what-is-recorded.md +13 -3
- package/docs/what-is-reticle.mdx +3 -1
- package/package.json +8 -12
- package/dist/features/harness/driver.d.ts +0 -50
- package/dist/features/harness/driver.js +0 -236
- package/dist/features/harness/jev-driver.d.ts +0 -188
- package/dist/features/harness/jev-driver.js +0 -678
- package/dist/features/harness/openai-driver.d.ts +0 -46
- package/dist/features/harness/openai-driver.js +0 -194
- package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
- package/dist/memory/project/dir/fill-value-store.js +0 -88
- package/docs/local-registry.md +0 -143
|
@@ -252,7 +252,6 @@ export declare const IntentShardSchema: z.ZodObject<{
|
|
|
252
252
|
}>>;
|
|
253
253
|
}, "strip", z.ZodTypeAny, {
|
|
254
254
|
version: 1;
|
|
255
|
-
subject: string;
|
|
256
255
|
intents: Record<string, {
|
|
257
256
|
status: "proved" | "proposed" | "agreed" | "stale";
|
|
258
257
|
state: "proved" | "declared" | "bound";
|
|
@@ -279,9 +278,9 @@ export declare const IntentShardSchema: z.ZodObject<{
|
|
|
279
278
|
statement: string;
|
|
280
279
|
}[] | undefined;
|
|
281
280
|
}>;
|
|
281
|
+
subject: string;
|
|
282
282
|
}, {
|
|
283
283
|
version: 1;
|
|
284
|
-
subject: string;
|
|
285
284
|
intents: Record<string, {
|
|
286
285
|
status: "proved" | "proposed" | "agreed" | "stale";
|
|
287
286
|
state: "proved" | "declared" | "bound";
|
|
@@ -308,6 +307,7 @@ export declare const IntentShardSchema: z.ZodObject<{
|
|
|
308
307
|
statement: string;
|
|
309
308
|
}[] | undefined;
|
|
310
309
|
}>;
|
|
310
|
+
subject: string;
|
|
311
311
|
}>;
|
|
312
312
|
export type IntentShard = z.infer<typeof IntentShardSchema>;
|
|
313
313
|
export declare const IntentIndexSchema: z.ZodObject<{
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
1
3
|
import { z } from 'zod';
|
|
4
|
+
import { StatementSource, classifyStatement, splitStatements, } from '@reticlehq/core/artifacts';
|
|
5
|
+
import { redactFeedbackText } from '../../telemetry/feedback.js';
|
|
6
|
+
import { reticleDirPaths } from '../project/dir/reticle-dir.js';
|
|
2
7
|
import { IntentStore } from './intent-store.js';
|
|
3
8
|
import { IntentShardStore } from './intent-shard-store.js';
|
|
4
9
|
import { IntentStatus } from './intent-shard.js';
|
|
5
|
-
import { ReticleTool } from '@reticlehq/core';
|
|
10
|
+
import { ReticleDir, ReticleTool, apiKeyFrom } from '@reticlehq/core';
|
|
6
11
|
import { sessionIdShape } from '../../surface/tools/tool-kit.js';
|
|
7
12
|
import { PredicateSchema } from '@reticlehq/engine/question/predicate/predicate.js';
|
|
8
13
|
import { sessionRoot } from '../project/session-root.js';
|
|
@@ -32,7 +37,7 @@ const MIGRATE = 'migrate';
|
|
|
32
37
|
export const INTENT_TOOLS = [
|
|
33
38
|
{
|
|
34
39
|
name: ReticleTool.INTENT,
|
|
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.
|
|
40
|
+
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. Pass `request` (what the user asked, verbatim) once per task. Stored in .reticle/intent/, git-checked.',
|
|
36
41
|
example: {
|
|
37
42
|
action: DECLARE,
|
|
38
43
|
intents: [
|
|
@@ -70,8 +75,11 @@ export const INTENT_TOOLS = [
|
|
|
70
75
|
})
|
|
71
76
|
.optional(),
|
|
72
77
|
}))
|
|
78
|
+
// Non-empty in the schema too, so the advertised contract says what `declare` enforces.
|
|
79
|
+
.min(1)
|
|
73
80
|
.optional()
|
|
74
81
|
.describe('declare only. Batchable — declare every intent for a feature in one call.'),
|
|
82
|
+
request: z.string().optional().describe("declare: the user's words, verbatim."),
|
|
75
83
|
id: z.string().optional().describe('bind only: which intent the predicate proves.'),
|
|
76
84
|
/*
|
|
77
85
|
* The predicate schema, not `unknown`.
|
|
@@ -153,9 +161,18 @@ export const INTENT_TOOLS = [
|
|
|
153
161
|
return { intents: await store.open() };
|
|
154
162
|
}
|
|
155
163
|
const raw = args['intents'];
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
: [];
|
|
164
|
+
const request = asString(args['request']);
|
|
165
|
+
if (request !== undefined && 0 < request.trim().length) {
|
|
166
|
+
await recordRequest(deps, root, request, Array.isArray(raw) ? raw : []);
|
|
167
|
+
if (!Array.isArray(raw) || 0 === raw.length)
|
|
168
|
+
return { request: 'recorded', path: root };
|
|
169
|
+
}
|
|
170
|
+
// Refused, not read as an empty list: `declare` with nothing to declare stored nothing and
|
|
171
|
+
// answered `{ intents: [] }`, which an agent reads as a declaration that worked (#1118).
|
|
172
|
+
if (!Array.isArray(raw) || 0 === raw.length) {
|
|
173
|
+
throw new Error(`${ReticleTool.INTENT} declare: \`intents\` must be a non-empty array of { id, statement }, got ${raw === undefined ? 'nothing' : JSON.stringify(raw)} — nothing was stored`);
|
|
174
|
+
}
|
|
175
|
+
const entries = raw;
|
|
159
176
|
const declared = await store.declare(entries);
|
|
160
177
|
// Said, not swallowed: an agent that declared something and finds nothing stored would
|
|
161
178
|
// otherwise conclude the ledger lost it.
|
|
@@ -166,3 +183,69 @@ export const INTENT_TOOLS = [
|
|
|
166
183
|
},
|
|
167
184
|
},
|
|
168
185
|
];
|
|
186
|
+
const MAX_REQUEST = 20_000;
|
|
187
|
+
const MAX_STATEMENT = 500;
|
|
188
|
+
const MAX_STATEMENTS = 100;
|
|
189
|
+
const PROJECT_CONFIG = '.reticle.json';
|
|
190
|
+
/** Credentials and personal data out, length capped: the same rules feedback reports follow. */
|
|
191
|
+
function redactSecrets(text, max) {
|
|
192
|
+
return redactFeedbackText(text, max).text;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Whether the request goes to the platform with the runs that verify it.
|
|
196
|
+
*
|
|
197
|
+
* A LINKED project shares it unless `.reticle.json` says `"shareRequests": false`: the platform
|
|
198
|
+
* reads what each run was for, which is half of what a run means. An unlinked project has nowhere
|
|
199
|
+
* to send it, and `"shareRequests": true` still shares from one that links later.
|
|
200
|
+
*/
|
|
201
|
+
function sharesRequests(projectDir, reticleRoot) {
|
|
202
|
+
let setting;
|
|
203
|
+
try {
|
|
204
|
+
const config = JSON.parse(readFileSync(join(projectDir, PROJECT_CONFIG), 'utf8'));
|
|
205
|
+
setting = config?.shareRequests;
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
setting = undefined;
|
|
209
|
+
}
|
|
210
|
+
if (false === setting)
|
|
211
|
+
return false;
|
|
212
|
+
if (true === setting)
|
|
213
|
+
return true;
|
|
214
|
+
// Linked by `reticle connect` (cloud.json), or by a key in the environment, the way CI syncs.
|
|
215
|
+
return (existsSync(join(reticleRoot, ReticleDir.CLOUD_LINK_FILE)) ||
|
|
216
|
+
apiKeyFrom(process.env) !== undefined);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Keep the user's request, and every statement in it and in the declared intents, classified and
|
|
220
|
+
* attributed, for the runs that verify it. Secrets are redacted before anything is written.
|
|
221
|
+
*
|
|
222
|
+
* Shared with the platform from a linked project unless `.reticle.json` says `"shareRequests": false`.
|
|
223
|
+
*/
|
|
224
|
+
async function recordRequest(deps, root, request, declared) {
|
|
225
|
+
const text = redactSecrets(request, MAX_REQUEST);
|
|
226
|
+
const agentStatements = declared.flatMap((d) => {
|
|
227
|
+
const statement = d?.statement;
|
|
228
|
+
return 'string' === typeof statement ? [statement] : [];
|
|
229
|
+
});
|
|
230
|
+
const context = {
|
|
231
|
+
request: text,
|
|
232
|
+
statements: [
|
|
233
|
+
...splitStatements(text).map((t) => ({ text: t, source: StatementSource.USER })),
|
|
234
|
+
...agentStatements.map((t) => ({
|
|
235
|
+
text: redactSecrets(t, MAX_STATEMENT),
|
|
236
|
+
source: StatementSource.AGENT,
|
|
237
|
+
})),
|
|
238
|
+
]
|
|
239
|
+
.slice(0, MAX_STATEMENTS)
|
|
240
|
+
.map((s) => ({
|
|
241
|
+
...s,
|
|
242
|
+
text: s.text.slice(0, MAX_STATEMENT),
|
|
243
|
+
kind: classifyStatement(s.text),
|
|
244
|
+
})),
|
|
245
|
+
at: deps.now(),
|
|
246
|
+
shared: sharesRequests(dirname(root), root),
|
|
247
|
+
};
|
|
248
|
+
const path = reticleDirPaths(root).request;
|
|
249
|
+
await deps.fs.mkdir(dirname(path));
|
|
250
|
+
await deps.fs.writeFile(path, `${JSON.stringify(context, null, 2)}\n`);
|
|
251
|
+
}
|
|
@@ -101,50 +101,50 @@ export declare const RouteEnvelopeSchema: z.ZodObject<{
|
|
|
101
101
|
max: number;
|
|
102
102
|
}>;
|
|
103
103
|
}, "strip", z.ZodTypeAny, {
|
|
104
|
-
|
|
104
|
+
net: {
|
|
105
105
|
count: number;
|
|
106
106
|
mean: number;
|
|
107
107
|
m2: number;
|
|
108
108
|
max: number;
|
|
109
109
|
};
|
|
110
|
-
|
|
110
|
+
durationMs: {
|
|
111
111
|
count: number;
|
|
112
112
|
mean: number;
|
|
113
113
|
m2: number;
|
|
114
114
|
max: number;
|
|
115
115
|
};
|
|
116
|
-
|
|
116
|
+
consoleErrors: {
|
|
117
117
|
count: number;
|
|
118
118
|
mean: number;
|
|
119
119
|
m2: number;
|
|
120
120
|
max: number;
|
|
121
121
|
};
|
|
122
|
-
|
|
122
|
+
netErrors: {
|
|
123
123
|
count: number;
|
|
124
124
|
mean: number;
|
|
125
125
|
m2: number;
|
|
126
126
|
max: number;
|
|
127
127
|
};
|
|
128
128
|
}, {
|
|
129
|
-
|
|
129
|
+
net: {
|
|
130
130
|
count: number;
|
|
131
131
|
mean: number;
|
|
132
132
|
m2: number;
|
|
133
133
|
max: number;
|
|
134
134
|
};
|
|
135
|
-
|
|
135
|
+
durationMs: {
|
|
136
136
|
count: number;
|
|
137
137
|
mean: number;
|
|
138
138
|
m2: number;
|
|
139
139
|
max: number;
|
|
140
140
|
};
|
|
141
|
-
|
|
141
|
+
consoleErrors: {
|
|
142
142
|
count: number;
|
|
143
143
|
mean: number;
|
|
144
144
|
m2: number;
|
|
145
145
|
max: number;
|
|
146
146
|
};
|
|
147
|
-
|
|
147
|
+
netErrors: {
|
|
148
148
|
count: number;
|
|
149
149
|
mean: number;
|
|
150
150
|
m2: number;
|
|
@@ -155,25 +155,25 @@ export declare const RouteEnvelopeSchema: z.ZodObject<{
|
|
|
155
155
|
route: string;
|
|
156
156
|
samples: number;
|
|
157
157
|
stats: {
|
|
158
|
-
|
|
158
|
+
net: {
|
|
159
159
|
count: number;
|
|
160
160
|
mean: number;
|
|
161
161
|
m2: number;
|
|
162
162
|
max: number;
|
|
163
163
|
};
|
|
164
|
-
|
|
164
|
+
durationMs: {
|
|
165
165
|
count: number;
|
|
166
166
|
mean: number;
|
|
167
167
|
m2: number;
|
|
168
168
|
max: number;
|
|
169
169
|
};
|
|
170
|
-
|
|
170
|
+
consoleErrors: {
|
|
171
171
|
count: number;
|
|
172
172
|
mean: number;
|
|
173
173
|
m2: number;
|
|
174
174
|
max: number;
|
|
175
175
|
};
|
|
176
|
-
|
|
176
|
+
netErrors: {
|
|
177
177
|
count: number;
|
|
178
178
|
mean: number;
|
|
179
179
|
m2: number;
|
|
@@ -184,25 +184,25 @@ export declare const RouteEnvelopeSchema: z.ZodObject<{
|
|
|
184
184
|
route: string;
|
|
185
185
|
samples: number;
|
|
186
186
|
stats: {
|
|
187
|
-
|
|
187
|
+
net: {
|
|
188
188
|
count: number;
|
|
189
189
|
mean: number;
|
|
190
190
|
m2: number;
|
|
191
191
|
max: number;
|
|
192
192
|
};
|
|
193
|
-
|
|
193
|
+
durationMs: {
|
|
194
194
|
count: number;
|
|
195
195
|
mean: number;
|
|
196
196
|
m2: number;
|
|
197
197
|
max: number;
|
|
198
198
|
};
|
|
199
|
-
|
|
199
|
+
consoleErrors: {
|
|
200
200
|
count: number;
|
|
201
201
|
mean: number;
|
|
202
202
|
m2: number;
|
|
203
203
|
max: number;
|
|
204
204
|
};
|
|
205
|
-
|
|
205
|
+
netErrors: {
|
|
206
206
|
count: number;
|
|
207
207
|
mean: number;
|
|
208
208
|
m2: number;
|
|
@@ -62,5 +62,19 @@ export declare function readQueryEvents(reader: JournalReader | undefined, buffe
|
|
|
62
62
|
* "nothing was lost" — see `JournalReader.readWriteLoss`.
|
|
63
63
|
*/
|
|
64
64
|
export declare function readJournalWriteLoss(reader: JournalReader | undefined, buffer: QueryBuffer): Promise<JournalWriteLoss | undefined>;
|
|
65
|
+
/** The slice of the ring buffer `windowLost` reads. `RingBuffer` satisfies it structurally. */
|
|
66
|
+
export interface LossBuffer {
|
|
67
|
+
lostSince(cursor: number): boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Did the EVENT STORE lose scarce evidence from a window opened at `cursor`? The input to whether a
|
|
71
|
+
* verdict's capture was clean — see `RingBuffer.lostSince`, and never the raw drop counter, which
|
|
72
|
+
* moves for the age and churn evictions that every live page produces continuously. The journal is
|
|
73
|
+
* the other half of that store, so a durable read that could not reach back to `cursor` lost
|
|
74
|
+
* exactly what an eviction would have. Both boundaries are INCLUSIVE (`t` is a millisecond many
|
|
75
|
+
* records share) and an absent `lostThroughT` impeaches every window rather than none — the
|
|
76
|
+
* conservative direction, both times.
|
|
77
|
+
*/
|
|
78
|
+
export declare function windowLost(reader: JournalReader | undefined, buffer: LossBuffer, cursor: number): boolean;
|
|
65
79
|
/** Apply since/until/actionId bounds to an event list. */
|
|
66
80
|
export declare function filterEvents(events: readonly ReticleEvent[], options: EventQueryOptions): ReticleEvent[];
|
|
@@ -90,6 +90,21 @@ export async function readJournalWriteLoss(reader, buffer) {
|
|
|
90
90
|
return undefined;
|
|
91
91
|
return (await reader?.readWriteLoss?.()) ?? undefined;
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Did the EVENT STORE lose scarce evidence from a window opened at `cursor`? The input to whether a
|
|
95
|
+
* verdict's capture was clean — see `RingBuffer.lostSince`, and never the raw drop counter, which
|
|
96
|
+
* moves for the age and churn evictions that every live page produces continuously. The journal is
|
|
97
|
+
* the other half of that store, so a durable read that could not reach back to `cursor` lost
|
|
98
|
+
* exactly what an eviction would have. Both boundaries are INCLUSIVE (`t` is a millisecond many
|
|
99
|
+
* records share) and an absent `lostThroughT` impeaches every window rather than none — the
|
|
100
|
+
* conservative direction, both times.
|
|
101
|
+
*/
|
|
102
|
+
export function windowLost(reader, buffer, cursor) {
|
|
103
|
+
if (buffer.lostSince(cursor))
|
|
104
|
+
return true;
|
|
105
|
+
const lost = reader?.readLoss?.();
|
|
106
|
+
return lost !== undefined && (lost.lostThroughT === undefined || lost.lostThroughT >= cursor);
|
|
107
|
+
}
|
|
93
108
|
/** Apply since/until/actionId bounds to an event list. */
|
|
94
109
|
export function filterEvents(events, options) {
|
|
95
110
|
return events.filter((event) => (options.since === undefined || event.t >= options.since) &&
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EventAttribution, JOURNAL_FILE_VERSION, } from '@reticlehq/core';
|
|
2
2
|
import { isSelfObservation } from './self-observation.js';
|
|
3
|
+
import { currentDrivenBy } from '../../hooks/driven-by.js';
|
|
3
4
|
import { log } from '../../log.js';
|
|
4
5
|
/**
|
|
5
6
|
* Logged the FIRST time a journal write is lost, and never again for that recorder.
|
|
@@ -65,7 +66,7 @@ export class JournalRecorder {
|
|
|
65
66
|
}
|
|
66
67
|
/** Open an attribution window. One action is active at a time (the agent drives sequentially). */
|
|
67
68
|
beginAction(actionId, tool, args) {
|
|
68
|
-
this.#active = { actionId, tool, args, tStart: this.#now() };
|
|
69
|
+
this.#active = { actionId, tool, args, tStart: this.#now(), drivenBy: currentDrivenBy() };
|
|
69
70
|
}
|
|
70
71
|
/** Close the active window: persist its buffered events, then the action record. No-op if none active. */
|
|
71
72
|
finishAction(effect, settled, settledInMs) {
|
|
@@ -86,6 +87,7 @@ export class JournalRecorder {
|
|
|
86
87
|
: { from: active.seqFrom, to: active.seqTo },
|
|
87
88
|
tRange: { from: active.tStart, to: this.#now() },
|
|
88
89
|
at: active.tStart,
|
|
90
|
+
...(active.drivenBy === undefined ? {} : { drivenBy: active.drivenBy }),
|
|
89
91
|
};
|
|
90
92
|
this.#enqueueFlush();
|
|
91
93
|
this.#chain = this.#chain
|
|
@@ -123,6 +125,10 @@ export class JournalRecorder {
|
|
|
123
125
|
// of zero, which is exactly how much time this action attributed events over.
|
|
124
126
|
tRange: { from: at, to: at },
|
|
125
127
|
at,
|
|
128
|
+
...(() => {
|
|
129
|
+
const by = currentDrivenBy();
|
|
130
|
+
return by === undefined ? {} : { drivenBy: by };
|
|
131
|
+
})(),
|
|
126
132
|
};
|
|
127
133
|
this.#enqueueFlush();
|
|
128
134
|
this.#chain = this.#chain
|
|
@@ -11,6 +11,8 @@ export declare const DEFAULT_DIFF_RETENTION = 10;
|
|
|
11
11
|
* for the one case where delivery was refused and somebody has to file the report by hand.
|
|
12
12
|
*/
|
|
13
13
|
export declare const DEFAULT_FEEDBACK_RETENTION = 20;
|
|
14
|
+
/** Harness plans kept on disk: the platform keeps every one, this machine the recent ones. */
|
|
15
|
+
export declare const DEFAULT_PLAN_RETENTION = 50;
|
|
14
16
|
/**
|
|
15
17
|
* The TOTAL the evidence tier of one `.reticle/` may occupy, across sessions, runs, overlay diffs
|
|
16
18
|
* and feedback copies together.
|
|
@@ -141,5 +143,6 @@ export declare function pruneEvidenceBudget(fs: FileSystemPort, root: string, bu
|
|
|
141
143
|
* Capped from here rather than from the writer, which lives in an area this file does not own. A
|
|
142
144
|
* retention rule is the same rule whether the directory holds journals, diffs or reports.
|
|
143
145
|
*/
|
|
146
|
+
export declare function prunePlans(fs: FileSystemPort, root: string, retention?: number): Promise<void>;
|
|
144
147
|
export declare function pruneFeedback(fs: FileSystemPort, root: string, retention?: number): Promise<void>;
|
|
145
148
|
export {};
|
|
@@ -14,6 +14,8 @@ export const DEFAULT_DIFF_RETENTION = 10;
|
|
|
14
14
|
* for the one case where delivery was refused and somebody has to file the report by hand.
|
|
15
15
|
*/
|
|
16
16
|
export const DEFAULT_FEEDBACK_RETENTION = 20;
|
|
17
|
+
/** Harness plans kept on disk: the platform keeps every one, this machine the recent ones. */
|
|
18
|
+
export const DEFAULT_PLAN_RETENTION = 50;
|
|
17
19
|
const DIFF_SUFFIX = '.diff.png';
|
|
18
20
|
const PNG_SUFFIX = '.png';
|
|
19
21
|
/**
|
|
@@ -287,6 +289,9 @@ export async function pruneEvidenceBudget(fs, root, budgetBytes = DEFAULT_EVIDEN
|
|
|
287
289
|
* Capped from here rather than from the writer, which lives in an area this file does not own. A
|
|
288
290
|
* retention rule is the same rule whether the directory holds journals, diffs or reports.
|
|
289
291
|
*/
|
|
292
|
+
export async function prunePlans(fs, root, retention = DEFAULT_PLAN_RETENTION) {
|
|
293
|
+
await pruneByRecency(fs, join(root, ReticleDir.PLANS_SUBDIR), retention);
|
|
294
|
+
}
|
|
290
295
|
export async function pruneFeedback(fs, root, retention = DEFAULT_FEEDBACK_RETENTION) {
|
|
291
296
|
await pruneByRecency(fs, join(root, ReticleDir.FEEDBACK_SUBDIR), retention);
|
|
292
297
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { pruneEvidenceBudget, pruneFeedback, pruneSessions, pruneVisualDiffs, } from './retention.js';
|
|
1
|
+
import { pruneEvidenceBudget, pruneFeedback, prunePlans, pruneSessions, pruneVisualDiffs, } from './retention.js';
|
|
2
2
|
import { DEFAULT_RETAIN } from './retain-policy.js';
|
|
3
3
|
export async function pruneWorkspace(fs, root, live, options = {}) {
|
|
4
4
|
const retain = { ...DEFAULT_RETAIN, ...options };
|
|
@@ -9,6 +9,8 @@ export async function pruneWorkspace(fs, root, live, options = {}) {
|
|
|
9
9
|
await pruneVisualDiffs(fs, root, retain.visual);
|
|
10
10
|
// Write-only local copies of reports the outbox already carries.
|
|
11
11
|
await pruneFeedback(fs, root, retain.feedback);
|
|
12
|
+
// The recent plans are what somebody reads back; the platform holds every one.
|
|
13
|
+
await prunePlans(fs, root);
|
|
12
14
|
// LAST, and the one that was missing: the only bound that limits SIZE rather than count.
|
|
13
15
|
await pruneEvidenceBudget(fs, root, retain.budgetBytes, live);
|
|
14
16
|
}
|
|
@@ -45,6 +45,8 @@ export const WORKSPACE_TIERS = {
|
|
|
45
45
|
[ReticleDir.VISUAL_SUBDIR]: localDir,
|
|
46
46
|
// Write-only: a local copy of what was already sent. The outbox is the record.
|
|
47
47
|
[ReticleDir.FEEDBACK_SUBDIR]: localDir,
|
|
48
|
+
// What the Harness planned on this machine, and how it went. The platform keeps the team's copy.
|
|
49
|
+
[ReticleDir.PLANS_SUBDIR]: localDir,
|
|
48
50
|
[ReticleDir.PROJECT_FILE]: localFile,
|
|
49
51
|
[ReticleDir.AMBIENT_FILE]: localFile,
|
|
50
52
|
[ReticleDir.ENVELOPES_FILE]: localFile,
|
|
@@ -52,6 +54,11 @@ export const WORKSPACE_TIERS = {
|
|
|
52
54
|
// What THIS machine's drives covered, and the best each level reached — the gate's ratchet.
|
|
53
55
|
[ReticleDir.COVERAGE_FILE]: localFile,
|
|
54
56
|
[ReticleDir.TIERS_FILE]: localFile,
|
|
57
|
+
// The user's request in their own words: it leaves only with `shareRequests`, never by git push.
|
|
58
|
+
[ReticleDir.REQUEST_FILE]: localFile,
|
|
59
|
+
[ReticleDir.PLATFORM_MOMENTS_FILE]: localFile,
|
|
60
|
+
// Notes a human pinned in the HUD: free text about the page. The team reads them on the platform.
|
|
61
|
+
[ReticleDir.NOTES_FILE]: localFile,
|
|
55
62
|
// The user's own record of what Reticle did for them, on THIS machine.
|
|
56
63
|
[ReticleDir.IMPACT_FILE]: localFile,
|
|
57
64
|
// This machine's conversation with the server. Its own doc comment says why committing it is
|
|
@@ -72,10 +79,6 @@ export const WORKSPACE_TIERS = {
|
|
|
72
79
|
// credential, so it is safe to commit — the same reasoning that puts `cloud.json` here while its
|
|
73
80
|
// API key stays in ~/.reticle.
|
|
74
81
|
[ReticleDir.HOOKS_FILE]: sharedFile,
|
|
75
|
-
// What a drive types into each labelled field. Committed for two reasons: a replay must send
|
|
76
|
-
// exactly what the recording sent or it is not a replay, and a value a model wrote once should be
|
|
77
|
-
// reviewable and editable by the team rather than regenerated differently on every machine.
|
|
78
|
-
[ReticleDir.FILL_VALUES_FILE]: sharedFile,
|
|
79
82
|
};
|
|
80
83
|
function namesWhere(match) {
|
|
81
84
|
return Object.entries(WORKSPACE_TIERS)
|
|
@@ -13,7 +13,7 @@ import { AmbientStore } from './ambient-store.js';
|
|
|
13
13
|
import { subjectOf } from '@reticlehq/core';
|
|
14
14
|
import { pruneWorkspace } from './on-disk/startup-maintenance.js';
|
|
15
15
|
import { buildVerificationRun } from '../../judgement/runs/artifact/build-verification-run.js';
|
|
16
|
-
import {
|
|
16
|
+
import { driveRunId, driveRunsFrom } from '../../judgement/runs/drive-run.js';
|
|
17
17
|
import { RunStore } from '../../judgement/runs/artifact/run-store.js';
|
|
18
18
|
/**
|
|
19
19
|
* Build the teardown handler the bridge fires when a session is removed. Flushes the journal first (so no
|
|
@@ -173,7 +173,7 @@ export async function recordDriveRun(deps, session) {
|
|
|
173
173
|
if (session.readJournalActions === undefined)
|
|
174
174
|
return;
|
|
175
175
|
const actions = await session.readJournalActions();
|
|
176
|
-
const
|
|
176
|
+
const inputs = driveRunsFrom(actions, {
|
|
177
177
|
// Derived from the session, NOT random. Teardown fires on every socket close, and a reconnecting
|
|
178
178
|
// tab keeps its session id and appends to the same ledger — so a drive across two page reloads
|
|
179
179
|
// would fold the whole ledger twice and publish two overlapping rows, the second a superset of
|
|
@@ -182,7 +182,7 @@ export async function recordDriveRun(deps, session) {
|
|
|
182
182
|
runId: driveRunId(session.id),
|
|
183
183
|
...(session.projectId === undefined ? {} : { projectId: session.projectId }),
|
|
184
184
|
});
|
|
185
|
-
if (
|
|
185
|
+
if (0 === inputs.length)
|
|
186
186
|
return;
|
|
187
187
|
// The protocol reaching the artifact a person actually reads. Only when the session could say
|
|
188
188
|
// where it was: a subject with no locator is not a weaker subject, it is a guess, and the
|
|
@@ -201,7 +201,9 @@ export async function recordDriveRun(deps, session) {
|
|
|
201
201
|
// used to write this artifact with no callback at all, so the evidence from a whole session sat
|
|
202
202
|
// on disk until a timer noticed — which, for the last session of the day, could be never.
|
|
203
203
|
deps.onRunPersisted === undefined ? undefined : { onWrote: deps.onRunPersisted });
|
|
204
|
-
|
|
204
|
+
for (const input of inputs) {
|
|
205
|
+
await store.write(buildVerificationRun({ ...input, ...(subject === undefined ? {} : { subject }) }, deps.now ?? (() => Date.now())));
|
|
206
|
+
}
|
|
205
207
|
}
|
|
206
208
|
/** Persist what this session drove as a replayable flow, when it declared anything provable. */
|
|
207
209
|
async function saveDrivenFlow(deps, session) {
|
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
import { type ProjectCandidate } from '@reticlehq/core/artifacts';
|
|
1
2
|
import { type ProjectId } from '@reticlehq/core';
|
|
2
3
|
import { type ArtifactRoot } from './artifact-root.js';
|
|
3
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Every project this machine knows the directory of: discovered `.reticle.json` files first, then
|
|
6
|
+
* the user-level registry, then the dev servers the build plugin announced. Read on each call, since
|
|
7
|
+
* `init` can run in another terminal while the daemon is up.
|
|
8
|
+
*
|
|
9
|
+
* Exported because sync must cover exactly the projects runs are written into. It kept its own list
|
|
10
|
+
* without the announced dev servers, so a project known only through its running dev server had its
|
|
11
|
+
* runs written to its `.reticle/runs/` and never sent, with nothing reporting a problem.
|
|
12
|
+
*/
|
|
13
|
+
export declare function knownProjectCandidates(): ProjectCandidate[];
|
|
14
|
+
/**
|
|
15
|
+
* The directory of the project a page announced, or undefined when this machine does not know it.
|
|
16
|
+
*
|
|
17
|
+
* A daemon is shared: started from `$HOME`, a monorepo root, or another project's MCP client, its
|
|
18
|
+
* cwd is often not the app that sent the HELLO. The version-skew remedy read `package.json` from
|
|
19
|
+
* cwd anyway, so it fell back to the generic sensor package and told a Next.js project to install
|
|
20
|
+
* `@reticlehq/browser` (#1135). This is the same lookup the artifact root uses, keyed by the page's
|
|
21
|
+
* own project id.
|
|
22
|
+
*/
|
|
23
|
+
export declare function projectDirectoryFor(projectId: string | undefined): string | undefined;
|
|
24
|
+
/** Where this resolver gets its IO answers. The defaults are the production ones. */
|
|
25
|
+
export interface ArtifactRootResolverDeps {
|
|
26
|
+
/** Every project this machine knows about. Defaults to discovery + the user registry. */
|
|
27
|
+
candidates?: () => ProjectCandidate[];
|
|
28
|
+
/** Whether the daemon's own directory is a Reticle project. Defaults to looking at disk. */
|
|
29
|
+
daemonIsProject?: (daemonRoot: string) => boolean;
|
|
30
|
+
/**
|
|
31
|
+
* The directory of the dev server that served a page origin, or undefined when unobservable.
|
|
32
|
+
* Required, not defaulted: the production answer reads daemon state and shells out, which is the
|
|
33
|
+
* wiring layer's business (`portal/session/serving-directory.ts`), and a resolver built without it
|
|
34
|
+
* would silently keep sending every worktree's artifacts to the primary checkout.
|
|
35
|
+
*/
|
|
36
|
+
servingDirectory: (origin: string) => string | undefined;
|
|
37
|
+
}
|
|
38
|
+
export declare function artifactRootResolver(daemonRoot: string, deps: ArtifactRootResolverDeps): (projectId: ProjectId | undefined, origin?: string) => ArtifactRoot;
|