@north-light/crouter 0.3.227 → 0.3.229
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/dist/api/client.d.ts +5 -5
- package/dist/api/client.js +3 -3
- package/dist/api/dto/broker-ops.d.ts +8 -0
- package/dist/api/dto/memory.d.ts +8 -7
- package/dist/api/dto/memory.js +2 -2
- package/dist/builtin-memory/04-base-worker.md +1 -1
- package/dist/builtin-memory/insights/init.md +5 -5
- package/dist/builtin-memory/internal/INDEX.md +1 -1
- package/dist/builtin-memory/internal/agent-shaping.md +11 -11
- package/dist/builtin-memory/internal/examples/INDEX.md +1 -1
- package/dist/builtin-memory/internal/memory-loading.md +6 -6
- package/dist/builtin-memory/internal/plugins.md +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +50 -37
- package/dist/clients/attach/__tests__/pane-tag-successor.test.js +56 -0
- package/dist/clients/attach/__tests__/profile-files.test.js +21 -0
- package/dist/clients/attach/chrome/inbox-strip.js +11 -7
- package/dist/clients/attach/session/pane-tag.d.ts +28 -2
- package/dist/clients/attach/session/pane-tag.js +48 -22
- package/dist/clients/attach/session/profile-files.d.ts +6 -0
- package/dist/clients/attach/session/profile-files.js +44 -11
- package/dist/clients/attach/slash/dispatch.js +4 -7
- package/dist/clients/attach/viewer.js +588 -596
- package/dist/commands/__tests__/surface-reload-target.test.js +21 -0
- package/dist/commands/api-client.d.ts +3 -7
- package/dist/commands/api-client.js +7 -12
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +292 -0
- package/dist/commands/memory/__tests__/repository-root-lint.test.js +146 -0
- package/dist/commands/memory/delete.js +51 -24
- package/dist/commands/memory/edit.js +50 -10
- package/dist/commands/memory/find.js +105 -56
- package/dist/commands/memory/history.js +51 -31
- package/dist/commands/memory/lint.d.ts +0 -9
- package/dist/commands/memory/lint.js +78 -322
- package/dist/commands/memory/list.d.ts +12 -4
- package/dist/commands/memory/list.js +64 -25
- package/dist/commands/memory/move.js +103 -73
- package/dist/commands/memory/origin.js +35 -5
- package/dist/commands/memory/read.d.ts +4 -0
- package/dist/commands/memory/read.js +132 -80
- package/dist/commands/memory/shared.d.ts +115 -25
- package/dist/commands/memory/shared.js +331 -74
- package/dist/commands/memory/write.js +72 -21
- package/dist/commands/memory.js +2 -2
- package/dist/commands/node/create.d.ts +1 -1
- package/dist/commands/node/create.js +1 -1
- package/dist/commands/node/inspect.js +1 -1
- package/dist/commands/node/lifecycle.js +5 -5
- package/dist/commands/pkg/market-manage.js +25 -24
- package/dist/commands/pkg/plugin-manage.d.ts +22 -6
- package/dist/commands/pkg/plugin-manage.js +118 -25
- package/dist/commands/pkg/shared.d.ts +8 -0
- package/dist/commands/pkg/shared.js +23 -20
- package/dist/commands/surface-reload.d.ts +5 -0
- package/dist/commands/surface-reload.js +9 -1
- package/dist/commands/sys/__tests__/migrate.test.js +1140 -22
- package/dist/commands/sys/__tests__/sync-project-guidance.test.js +218 -0
- package/dist/commands/sys/migrate.js +126 -140
- package/dist/commands/sys/panels/profiles-panel.d.ts +66 -0
- package/dist/commands/sys/panels/profiles-panel.js +599 -0
- package/dist/commands/sys/settings-shell.d.ts +4 -2
- package/dist/commands/sys/settings-shell.js +35 -4
- package/dist/commands/sys/settings.js +21 -5
- package/dist/commands/sys/sync-deps.d.ts +2 -0
- package/dist/commands/sys/sync-deps.js +26 -15
- package/dist/commands/sys/sync-project-guidance.js +228 -145
- package/dist/commands/sys/sync-skills.js +28 -17
- package/dist/commands/sys/update.js +11 -3
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +15 -2
- package/dist/core/__tests__/config-change-delta.test.js +106 -0
- package/dist/core/__tests__/context-intro.test.js +13 -9
- package/dist/core/__tests__/daemon-boot.test.js +22 -16
- package/dist/core/__tests__/fixtures/memory-slash-live-probe.js +5 -1
- package/dist/core/__tests__/human-deliver.test.js +19 -0
- package/dist/core/__tests__/inline-memory-refs.test.js +50 -46
- package/dist/core/__tests__/{serial → integration}/broker-fork-seam.test.js +1 -1
- package/dist/core/__tests__/{serial → integration}/broker-sdk-wiring.test.js +1 -1
- package/dist/core/__tests__/{serial → integration}/broker-snapshot-history.test.js +1 -1
- package/dist/core/__tests__/{serial → integration}/command-plugins.test.js +94 -3
- package/dist/core/__tests__/{serial → integration}/deferred-no-wake.test.js +1 -1
- package/dist/core/__tests__/{serial → integration}/flagship-lifecycle.test.js +13 -27
- package/dist/core/__tests__/{serial → integration}/host-teardown-process-group.test.js +1 -1
- package/dist/core/__tests__/{serial → integration}/human-deliver-e2e.test.js +1 -1
- package/dist/core/__tests__/{live-mutation-verbs.test.js → integration/live-mutation-verbs.test.js} +22 -33
- package/dist/core/__tests__/{serial → integration}/live-mutation.test.js +21 -41
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.d.ts +1 -0
- package/dist/core/__tests__/{serial → integration}/refresh-stall-recycle.test.js +1 -1
- package/dist/core/__tests__/integration/revive.test.d.ts +1 -0
- package/dist/core/__tests__/{serial → integration}/revive.test.js +38 -19
- package/dist/core/__tests__/integration/spawn-root.test.d.ts +1 -0
- package/dist/core/__tests__/{serial → integration}/spawn-root.test.js +104 -1
- package/dist/core/__tests__/integration/subscription-delivery.test.d.ts +1 -0
- package/dist/core/__tests__/{serial → integration}/subscription-delivery.test.js +1 -1
- package/dist/core/__tests__/integration/tmux-surface.test.d.ts +1 -0
- package/dist/core/__tests__/{serial → integration}/tmux-surface.test.js +1 -1
- package/dist/core/__tests__/integration/worktree-land.test.d.ts +1 -0
- package/dist/core/__tests__/integration/worktree-land.test.js +400 -0
- package/dist/core/__tests__/integration/worktree-reap.test.d.ts +1 -0
- package/dist/core/__tests__/{serial/worktree.test.js → integration/worktree-reap.test.js} +6 -338
- package/dist/core/__tests__/kickoff.test.js +16 -5
- package/dist/core/__tests__/memory-resolver-precedence.test.js +122 -91
- package/dist/core/__tests__/nested-store-discovery.test.js +5 -3
- package/dist/core/__tests__/on-read-crouter-home-fence.test.js +2 -1
- package/dist/core/__tests__/on-read-dedup-resume.test.js +39 -27
- package/dist/core/__tests__/on-read-nested-store.test.js +19 -13
- package/dist/core/__tests__/profile-project-memory-delivery.test.js +138 -44
- package/dist/core/__tests__/repository-association.test.d.ts +1 -0
- package/dist/core/__tests__/repository-association.test.js +153 -0
- package/dist/core/__tests__/repository-root-identity.test.d.ts +1 -0
- package/dist/core/__tests__/repository-root-identity.test.js +219 -0
- package/dist/core/__tests__/review-model-floor.test.js +12 -4
- package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.js +27 -11
- package/dist/core/__tests__/warm-claim-preference-snapshot.test.d.ts +1 -0
- package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +40 -0
- package/dist/core/canvas/canvas.d.ts +3 -0
- package/dist/core/canvas/canvas.js +30 -10
- package/dist/core/canvas/db.js +28 -1
- package/dist/core/canvas/paths.d.ts +4 -6
- package/dist/core/canvas/paths.js +8 -6
- package/dist/core/canvas/render-source.js +2 -2
- package/dist/core/canvas/types.d.ts +9 -13
- package/dist/core/config.d.ts +3 -3
- package/dist/core/config.js +3 -3
- package/dist/core/exclusive-lock.d.ts +2 -0
- package/dist/core/exclusive-lock.js +21 -0
- package/dist/core/git.d.ts +0 -1
- package/dist/core/git.js +0 -3
- package/dist/core/human/__tests__/integration/inbox-core.test.d.ts +1 -0
- package/dist/core/human/feedback-companion.js +3 -0
- package/dist/core/human/scan.js +8 -1
- package/dist/core/keybindings/catalog.d.ts +2 -2
- package/dist/core/keybindings/catalog.js +2 -1
- package/dist/core/memory/doc-link-grammar.js +2 -2
- package/dist/core/memory/history.d.ts +24 -0
- package/dist/core/memory/history.js +66 -1
- package/dist/core/memory/identity.d.ts +65 -0
- package/dist/core/memory/identity.js +185 -0
- package/dist/core/memory/inline-ref-guidance.d.ts +1 -1
- package/dist/core/memory/inline-ref-guidance.js +1 -1
- package/dist/core/memory/inline-ref-inventory.d.ts +3 -10
- package/dist/core/memory/inline-ref-inventory.js +30 -62
- package/dist/core/memory/lint.d.ts +129 -0
- package/dist/core/memory/lint.js +517 -0
- package/dist/core/memory/project-namespace.d.ts +31 -0
- package/dist/core/memory/project-namespace.js +85 -0
- package/dist/core/memory/repository-association.d.ts +31 -0
- package/dist/core/memory/repository-association.js +129 -0
- package/dist/core/memory/tree.d.ts +39 -0
- package/dist/core/memory/tree.js +93 -0
- package/dist/core/memory-resolver.d.ts +193 -90
- package/dist/core/memory-resolver.js +461 -375
- package/dist/core/nested-stores.js +6 -13
- package/dist/core/profiles/select.d.ts +4 -1
- package/dist/core/profiles/select.js +108 -48
- package/dist/core/review/__tests__/capture-origin.test.js +2 -2
- package/dist/core/review/__tests__/stage-identity.test.js +2 -2
- package/dist/core/review/companion.js +11 -2
- package/dist/core/runtime/bearings.d.ts +2 -2
- package/dist/core/runtime/bearings.js +3 -3
- package/dist/core/runtime/broker/daemon-ops.d.ts +2 -2
- package/dist/core/runtime/broker/rebind.js +5 -0
- package/dist/core/runtime/broker-extension-render.d.ts +7 -3
- package/dist/core/runtime/broker-extension-render.js +10 -5
- package/dist/core/runtime/broker-persona-guidance.d.ts +19 -5
- package/dist/core/runtime/broker-persona-guidance.js +122 -27
- package/dist/core/runtime/deliver-live.d.ts +16 -4
- package/dist/core/runtime/deliver-live.js +29 -15
- package/dist/core/runtime/kickoff.d.ts +3 -3
- package/dist/core/runtime/kickoff.js +8 -16
- package/dist/core/runtime/launch.js +1 -1
- package/dist/core/runtime/lifecycle.js +2 -3
- package/dist/core/runtime/nodes.d.ts +3 -4
- package/dist/core/runtime/nodes.js +3 -4
- package/dist/core/runtime/persona.d.ts +8 -12
- package/dist/core/runtime/persona.js +24 -96
- package/dist/core/runtime/promote.d.ts +2 -2
- package/dist/core/runtime/promote.js +8 -21
- package/dist/core/runtime/revive.js +20 -17
- package/dist/core/runtime/spawn.js +18 -7
- package/dist/core/runtime/tmux-bindings.js +2 -3
- package/dist/core/runtime/warm-pool.js +3 -4
- package/dist/core/scope.js +2 -0
- package/dist/core/self-update.d.ts +0 -2
- package/dist/core/self-update.js +2 -35
- package/dist/core/substrate/__tests__/surface-match-memory-read.test.d.ts +1 -0
- package/dist/core/substrate/__tests__/surface-match-memory-read.test.js +28 -0
- package/dist/core/substrate/index.d.ts +2 -2
- package/dist/core/substrate/index.js +1 -1
- package/dist/core/substrate/injected-store.d.ts +43 -27
- package/dist/core/substrate/injected-store.js +208 -104
- package/dist/core/substrate/listings.d.ts +19 -12
- package/dist/core/substrate/listings.js +75 -52
- package/dist/core/substrate/on-read-node.d.ts +4 -7
- package/dist/core/substrate/on-read-node.js +6 -8
- package/dist/core/substrate/on-read.d.ts +22 -25
- package/dist/core/substrate/on-read.js +103 -147
- package/dist/core/substrate/render-node.d.ts +4 -7
- package/dist/core/substrate/render-node.js +5 -7
- package/dist/core/substrate/render.d.ts +21 -3
- package/dist/core/substrate/render.js +291 -223
- package/dist/core/substrate/schema.d.ts +1 -13
- package/dist/core/substrate/schema.js +5 -40
- package/dist/core/substrate/session-cache.d.ts +14 -4
- package/dist/core/substrate/session-cache.js +40 -22
- package/dist/core/substrate/surface-match.d.ts +9 -7
- package/dist/core/substrate/surface-match.js +26 -25
- package/dist/daemon/__tests__/helpers/source-daemon.d.ts +30 -0
- package/dist/daemon/__tests__/helpers/source-daemon.js +174 -0
- package/dist/daemon/__tests__/integration/migration-startup.test.d.ts +1 -0
- package/dist/daemon/__tests__/integration/migration-startup.test.js +97 -0
- package/dist/daemon/api/__tests__/bridge-heartbeat.test.js +21 -5
- package/dist/daemon/api/handlers/broker-ops.js +21 -16
- package/dist/daemon/api/handlers/memory.js +2 -0
- package/dist/daemon/crtrd.js +2 -0
- package/dist/daemon/human/finish.js +8 -1
- package/dist/daemon/manage.d.ts +0 -1
- package/dist/daemon/manage.js +7 -16
- package/dist/daemon/startup-policy.d.ts +1 -0
- package/dist/daemon/startup-policy.js +1 -0
- package/dist/migrations/001-surfaces-frontmatter.js +21 -109
- package/dist/migrations/002-profile-project-memory.js +1 -0
- package/dist/migrations/003-repository-root-memory-identity/front-door.d.ts +26 -0
- package/dist/migrations/003-repository-root-memory-identity/front-door.js +231 -0
- package/dist/migrations/003-repository-root-memory-identity/index.d.ts +2 -0
- package/dist/migrations/003-repository-root-memory-identity/index.js +513 -0
- package/dist/migrations/003-repository-root-memory-identity/references.d.ts +95 -0
- package/dist/migrations/003-repository-root-memory-identity/references.js +469 -0
- package/dist/migrations/003-repository-root-memory-identity/repository-facts.d.ts +39 -0
- package/dist/migrations/003-repository-root-memory-identity/repository-facts.js +349 -0
- package/dist/migrations/__tests__/activation-concurrency.test.d.ts +1 -0
- package/dist/migrations/__tests__/activation-concurrency.test.js +145 -0
- package/dist/migrations/__tests__/activation.test.d.ts +1 -0
- package/dist/migrations/__tests__/activation.test.js +149 -0
- package/dist/migrations/__tests__/deletion-and-root-declaration.test.d.ts +1 -0
- package/dist/migrations/__tests__/deletion-and-root-declaration.test.js +149 -0
- package/dist/migrations/activation.d.ts +16 -0
- package/dist/migrations/activation.js +78 -0
- package/dist/migrations/convergent.d.ts +14 -3
- package/dist/migrations/convergent.js +21 -10
- package/dist/migrations/corpus.d.ts +78 -0
- package/dist/migrations/corpus.js +497 -0
- package/dist/migrations/frontmatter-splice.d.ts +15 -0
- package/dist/migrations/frontmatter-splice.js +176 -0
- package/dist/migrations/registry.d.ts +6 -1
- package/dist/migrations/registry.js +7 -2
- package/dist/migrations/runner.d.ts +41 -0
- package/dist/migrations/runner.js +81 -0
- package/dist/migrations/types.d.ts +148 -9
- package/dist/migrations/types.js +9 -2
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +225 -17
- package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +11 -3
- package/dist/pi-extensions/canvas-context-intro.d.ts +3 -5
- package/dist/pi-extensions/canvas-context-intro.js +50 -46
- package/dist/pi-extensions/canvas-doc-substrate.d.ts +1 -8
- package/dist/pi-extensions/canvas-doc-substrate.js +55 -122
- package/dist/pi-extensions/canvas-stophook.js +6 -13
- package/dist/shared/generated-context.d.ts +0 -3
- package/dist/shared/generated-context.js +0 -57
- package/dist/shared/tool-groups.js +2 -3
- package/dist/types.d.ts +8 -11
- package/dist/types.js +4 -31
- package/package.json +5 -4
- package/runtime.lock.json +2 -2
- package/dist/builtin-memory/05-kinds/design/00-base.md +0 -17
- package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +0 -15
- package/dist/builtin-memory/05-kinds/design/design-contract.md +0 -19
- package/dist/builtin-memory/05-kinds/developer/00-base.md +0 -17
- package/dist/builtin-memory/05-kinds/developer/01-orchestrator.md +0 -15
- package/dist/builtin-memory/05-kinds/plan/00-base.md +0 -17
- package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +0 -17
- package/dist/builtin-memory/05-kinds/plan/plan-contract.md +0 -28
- package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +0 -15
- package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +0 -15
- package/dist/builtin-memory/05-kinds/plan/reviewers/lens-contract.md +0 -13
- package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +0 -17
- package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +0 -17
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +0 -17
- package/dist/builtin-memory/05-kinds/spec/00-base.md +0 -17
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +0 -15
- package/dist/builtin-memory/05-kinds/spec/requirements.md +0 -15
- package/dist/builtin-memory/design/guide.md +0 -35
- package/dist/builtin-memory/design/roadmap.md +0 -21
- package/dist/builtin-memory/development.md +0 -113
- package/dist/builtin-memory/plan/roadmap.md +0 -25
- package/dist/builtin-memory/spec/guide.md +0 -53
- package/dist/builtin-memory/spec/requirements.md +0 -29
- package/dist/builtin-memory/spec/roadmap.md +0 -36
- package/dist/builtin-memory/testing.md +0 -39
- /package/dist/api/__tests__/{serial → integration}/client.test.d.ts +0 -0
- /package/dist/api/__tests__/{serial → integration}/client.test.js +0 -0
- /package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/{serial → integration}/provider-rotation.test.ts +0 -0
- /package/dist/clients/{inbox/__tests__/serial/inbox-controller.test.d.ts → attach/__tests__/pane-tag-successor.test.d.ts} +0 -0
- /package/dist/clients/{inbox/__tests__/serial/mount-panel.test.d.ts → attach/__tests__/profile-files.test.d.ts} +0 -0
- /package/dist/{core/__tests__/live-mutation-verbs.test.d.ts → clients/inbox/__tests__/integration/inbox-controller.test.d.ts} +0 -0
- /package/dist/clients/inbox/__tests__/{serial → integration}/inbox-controller.test.js +0 -0
- /package/dist/{core/__tests__/serial/broker-fork-seam.test.d.ts → clients/inbox/__tests__/integration/mount-panel.test.d.ts} +0 -0
- /package/dist/clients/inbox/__tests__/{serial → integration}/mount-panel.test.js +0 -0
- /package/dist/{core/__tests__/serial/broker-sdk-wiring.test.d.ts → commands/__tests__/surface-reload-target.test.d.ts} +0 -0
- /package/dist/{core/__tests__/serial/broker-snapshot-history.test.d.ts → commands/memory/__tests__/command-selector-and-mutation-guards.test.d.ts} +0 -0
- /package/dist/{core/__tests__/serial/command-plugins.test.d.ts → commands/memory/__tests__/repository-root-lint.test.d.ts} +0 -0
- /package/dist/{core/__tests__/serial/deferred-no-wake.test.d.ts → commands/sys/__tests__/sync-project-guidance.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/flagship-lifecycle.test.d.ts → config-change-delta.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/host-teardown-process-group.test.d.ts → integration/broker-fork-seam.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/human-deliver-e2e.test.d.ts → integration/broker-sdk-wiring.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/live-mutation.test.d.ts → integration/broker-snapshot-history.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/refresh-stall-recycle.test.d.ts → integration/command-plugins.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/revive.test.d.ts → integration/deferred-no-wake.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/spawn-root.test.d.ts → integration/flagship-lifecycle.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/subscription-delivery.test.d.ts → integration/host-teardown-process-group.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/tmux-surface.test.d.ts → integration/human-deliver-e2e.test.d.ts} +0 -0
- /package/dist/core/__tests__/{serial/worktree.test.d.ts → integration/live-mutation-verbs.test.d.ts} +0 -0
- /package/dist/core/{human/__tests__/serial/inbox-core.test.d.ts → __tests__/integration/live-mutation.test.d.ts} +0 -0
- /package/dist/core/human/__tests__/{serial → integration}/inbox-core.test.js +0 -0
package/dist/api/client.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ import type { CancelInboxTicketRequest, CanceledTicketResultDTO, InboxListDTO, I
|
|
|
21
21
|
import type { CreateHumanRequestDTO, CreateHumanRequestRequest, HumanRequestDTO, HumanRequestIdDTO, ReplaceHumanRequestRequest, RespondHumanRequestRequest, SettleHumanRequestRequest } from './dto/human-requests.js';
|
|
22
22
|
import type { AttentionCountsDTO, AttentionDTO, DashboardDTO, DashboardQuery, HistoryGrepQuery, HistoryGrepResultDTO, HistoryReadQuery, HistoryReadResultDTO, HistorySearchQuery, HistorySearchResultDTO, PruneRequest, PruneResultDTO, RebuildIndexResultDTO, RosterDTO, SnapshotDTO } from './dto/canvas.js';
|
|
23
23
|
import type { CloseWorktreeResultDTO } from './dto/worktree.js';
|
|
24
|
-
import type { BrokerExtensionStateDTO, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerInboxCursorDirective, BrokerInboxCursorRequest, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerPersonaAckRequest, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest } from './dto/broker-ops.js';
|
|
24
|
+
import type { BrokerExtensionStateDTO, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerInboxCursorDirective, BrokerInboxCursorRequest, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerPersonaAckRequest, BrokerPersonaAckResultDTO, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest } from './dto/broker-ops.js';
|
|
25
25
|
export interface CrtrClientOptions {
|
|
26
26
|
/** Unix socket path (default local transport). Exactly one of socketPath|baseUrl. */
|
|
27
27
|
socketPath?: string;
|
|
@@ -101,7 +101,7 @@ export declare class CrtrClient {
|
|
|
101
101
|
commitBrokerModel(id: string, req: BrokerModelCommitRequest): Promise<BrokerModelCommitResultDTO>;
|
|
102
102
|
brokerExtensionState(id: string): Promise<BrokerExtensionStateDTO>;
|
|
103
103
|
commitBrokerGeneratedName(id: string, req: BrokerGeneratedNameRequest): Promise<BrokerGeneratedNameResultDTO>;
|
|
104
|
-
commitBrokerPersonaAck(id: string, req: BrokerPersonaAckRequest): Promise<
|
|
104
|
+
commitBrokerPersonaAck(id: string, req: BrokerPersonaAckRequest): Promise<BrokerPersonaAckResultDTO>;
|
|
105
105
|
closeNode(id: string, req?: CloseRequest): Promise<CloseResultDTO>;
|
|
106
106
|
recycleNode(id: string): Promise<NodeDetailDTO>;
|
|
107
107
|
demoteNode(id: string): Promise<NodeDetailDTO>;
|
|
@@ -164,9 +164,9 @@ export declare class CrtrClient {
|
|
|
164
164
|
/** Read an absolute host path as UTF-8 (capped, `truncated` when clipped) for
|
|
165
165
|
* the browser file-peek panel. */
|
|
166
166
|
peekFile(path: string): Promise<FilePeekDTO>;
|
|
167
|
-
/** Resolve
|
|
168
|
-
*
|
|
169
|
-
* Pair with `peekFile` to render the document. */
|
|
167
|
+
/** Resolve an exact canonical `[[name]]` memory-document link to the winning
|
|
168
|
+
* document's physical origin for the given node — the node's own precedence
|
|
169
|
+
* chain, not this process's. Pair with `peekFile` to render the document. */
|
|
170
170
|
resolveMemoryDoc(name: string, nodeId: string): Promise<MemoryDocRefDTO>;
|
|
171
171
|
/** Create-or-return by name. Supplied `projects` are shape-checked even when
|
|
172
172
|
* the profile already exists; their directories are only required to exist
|
package/dist/api/client.js
CHANGED
|
@@ -290,9 +290,9 @@ export class CrtrClient {
|
|
|
290
290
|
return this.request('GET', withQuery(routes.filePeek(), { path }));
|
|
291
291
|
}
|
|
292
292
|
// ---- Memory documents --------------------------------------------------
|
|
293
|
-
/** Resolve
|
|
294
|
-
*
|
|
295
|
-
* Pair with `peekFile` to render the document. */
|
|
293
|
+
/** Resolve an exact canonical `[[name]]` memory-document link to the winning
|
|
294
|
+
* document's physical origin for the given node — the node's own precedence
|
|
295
|
+
* chain, not this process's. Pair with `peekFile` to render the document. */
|
|
296
296
|
resolveMemoryDoc(name, nodeId) {
|
|
297
297
|
return this.request('GET', withQuery(routes.memoryResolve(), { name, node: nodeId }));
|
|
298
298
|
}
|
|
@@ -90,7 +90,10 @@ export interface BrokerExtensionNodeDTO {
|
|
|
90
90
|
target_file: string;
|
|
91
91
|
} | null;
|
|
92
92
|
intent: ExitIntentDTO;
|
|
93
|
+
/** `kind` is absent on rows written before kind joined the drift key; a read
|
|
94
|
+
* resolves it to the node's current kind. */
|
|
93
95
|
persona_ack?: {
|
|
96
|
+
kind?: string;
|
|
94
97
|
mode: 'base' | 'orchestrator';
|
|
95
98
|
lifecycle: 'terminal' | 'resident';
|
|
96
99
|
};
|
|
@@ -145,11 +148,16 @@ export interface BrokerGeneratedNameResultDTO {
|
|
|
145
148
|
}
|
|
146
149
|
export interface BrokerPersonaAckRequest {
|
|
147
150
|
from: {
|
|
151
|
+
kind: string;
|
|
148
152
|
mode: 'base' | 'orchestrator';
|
|
149
153
|
lifecycle: 'terminal' | 'resident';
|
|
150
154
|
};
|
|
151
155
|
to: {
|
|
156
|
+
kind: string;
|
|
152
157
|
mode: 'base' | 'orchestrator';
|
|
153
158
|
lifecycle: 'terminal' | 'resident';
|
|
154
159
|
};
|
|
155
160
|
}
|
|
161
|
+
export interface BrokerPersonaAckResultDTO {
|
|
162
|
+
applied: boolean;
|
|
163
|
+
}
|
package/dist/api/dto/memory.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
/** `GET /v1/memory/resolve?name=<name>&node=<id>` result
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* the same name can answer with different documents for different nodes. */
|
|
1
|
+
/** `GET /v1/memory/resolve?name=<name>&node=<id>` result. Resolution runs the
|
|
2
|
+
* node's own precedence chain (its context store, its project stack, its
|
|
3
|
+
* profile, user, builtin) and returns the winner for the exact canonical name. */
|
|
5
4
|
export interface MemoryDocRefDTO {
|
|
6
|
-
/** The
|
|
7
|
-
* path-derived name) — which may differ from the queried name when the query
|
|
8
|
-
* was a bare leaf or a directory whose INDEX resolved. */
|
|
5
|
+
/** The winner's canonical identity for the exact resolved query. */
|
|
9
6
|
name: string;
|
|
10
7
|
/** Which store it came from: node | project | profile | user | builtin. */
|
|
11
8
|
scope: string;
|
|
12
9
|
/** Absolute path to the `.md` file. */
|
|
13
10
|
path: string;
|
|
11
|
+
/** Absolute path to the physical memory store root. */
|
|
12
|
+
store_root: string;
|
|
13
|
+
/** Store-relative markdown path of the winning document. */
|
|
14
|
+
physical_relative_path: string;
|
|
14
15
|
/** The owning plugin's name when the doc is mounted from an installed plugin,
|
|
15
16
|
* absent for a native scope doc. */
|
|
16
17
|
plugin?: string;
|
package/dist/api/dto/memory.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Memory-document resolution DTO. Backs `GET /v1/memory/resolve` — a client
|
|
2
|
-
// holding a `[[name]]` link out of a node's transcript
|
|
3
|
-
//
|
|
2
|
+
// holding a canonical `[[name]]` link out of a node's transcript gets the
|
|
3
|
+
// winning document's canonical identity and physical origin.
|
|
4
4
|
//
|
|
5
5
|
// PURITY (spec §3.1): Node built-ins + `src/api/*` only.
|
|
6
6
|
export {};
|
|
@@ -3,7 +3,7 @@ kind: preference
|
|
|
3
3
|
when-and-why-to-read: When a node runs in base mode, this preference should be read so bounded work completes hands-on instead of recursing through a chain of delegates.
|
|
4
4
|
gate: {mode: base}
|
|
5
5
|
rationale: >-
|
|
6
|
-
A base security reviewer handed its entire assignment to another base security reviewer, which repeated the move through a 35-node chain in under five minutes. The universal prompt had said to delegate any self-contained work while no base-mode layer told sub-kinds to work hands-on; exact sub-kind gating also meant
|
|
6
|
+
A base security reviewer handed its entire assignment to another base security reviewer, which repeated the move through a 35-node chain in under five minutes. The universal prompt had said to delegate any self-contained work while no base-mode layer told sub-kinds to work hands-on; exact sub-kind gating also meant the reviewer did not inherit its parent kind's base layer.
|
|
7
7
|
|
|
8
8
|
The scout section exists because the kernel's "understand before you delegate" line is orchestrator-gated, so base workers had no counterweight to mapping unfamiliar code in their own window: they spent a strong-model context on read-only exploration and yielded before the real work. Explore defaults to a light tier, which is the mechanism the section leans on.
|
|
9
9
|
surfaces:
|
|
@@ -28,11 +28,11 @@ Choose the narrowest durable scope that reaches every future conversation where
|
|
|
28
28
|
|
|
29
29
|
Infer the scope from the request and current workspace. Ask through `crtr human send` only when more than one scope is genuinely plausible, and settle scope before writing anything. Never use node scope for an ongoing listener.
|
|
30
30
|
|
|
31
|
-
Search the chosen scope before creating.
|
|
31
|
+
Search the chosen scope before creating. Use `<namespace>/insights/<topic>` for project scope and `insights/<topic>` for profile or user scope; if that canonical address already represents the same domain, refine that listener rather than creating an overlapping directory.
|
|
32
32
|
|
|
33
33
|
## Create the listener
|
|
34
34
|
|
|
35
|
-
Run `crtr memory write -h`, then create `insights/<topic
|
|
35
|
+
Run `crtr memory write -h`, then create the directory document at the chosen scope under its canonical address: `<namespace>/insights/<topic>` for project scope and `insights/<topic>` for profile or user scope, as a preference surfaced `{on: boot, at: preview}`. Its physical front door remains `insights/<topic>/INDEX.md`.
|
|
36
36
|
|
|
37
37
|
Its routing line must name the actual domain trigger: when user-supplied information, a correction, or a user response relates to this domain, read the preference because recognizing the underlying principle preserves knowledge future decisions can use.
|
|
38
38
|
|
|
@@ -52,7 +52,7 @@ When `--active` is present, do not stop after creating the listener. After initi
|
|
|
52
52
|
|
|
53
53
|
### 1. Create the listener first
|
|
54
54
|
|
|
55
|
-
Follow the passive mode steps above through "Initialization is complete." The listener
|
|
55
|
+
Follow the passive mode steps above through "Initialization is complete." The listener directory document must exist before spawning the explorer.
|
|
56
56
|
|
|
57
57
|
### 2. Spawn the explorer child
|
|
58
58
|
|
|
@@ -81,8 +81,8 @@ When the explorer reports, share its claims with the user. For each claim, ask:
|
|
|
81
81
|
- Is it incomplete or wrong?
|
|
82
82
|
- What's the actual principle?
|
|
83
83
|
|
|
84
|
-
For each user response, use [[insights/capture]] to extract and review the insight. Apply approved insights directly to the listener
|
|
84
|
+
For each user response, use [[insights/capture]] to extract and review the insight. Apply approved insights directly to the listener directory document's `Approved insights` section.
|
|
85
85
|
|
|
86
86
|
### 4. Report completion
|
|
87
87
|
|
|
88
|
-
Once claims have been surfaced and user guidance has generated approved insights, report that active initialization is complete. The listener
|
|
88
|
+
Once claims have been surfaced and user guidance has generated approved insights, report that active initialization is complete. The listener directory document now passively captures this domain as new user material emerges.
|
|
@@ -25,4 +25,4 @@ Adjacent, outside this dir: authoring memory documents (kind, surfaces routing,
|
|
|
25
25
|
|
|
26
26
|
Briefly: **plugins** package docs and commands, with command execution selected by `plugin.json.transport` (`exec` for a trusted local executable or `http` for a fetched remote REST manifest); **marketplaces** index and distribute plugins. Plugin commands enter the **external-command** fallthrough, leaving the core fast-path untouched.
|
|
27
27
|
|
|
28
|
-
The individual files surface at
|
|
28
|
+
The individual files surface at their canonical names (open the one the situation calls for); this directory document surfaces at `internal` at `preview`, and `crtr memory read internal` returns its body followed by the directory's immediate listing.
|
|
@@ -23,7 +23,7 @@ A fifth axis, **lifecycle** (`terminal` vs `resident`), is orthogonal too but be
|
|
|
23
23
|
|
|
24
24
|
## Kinds — role, model tier, and tools
|
|
25
25
|
|
|
26
|
-
A kind
|
|
26
|
+
A kind starts with a **`KindConfig`** in the launch registry: its one-line `whenToUse`, default model tier, tools and extensions, and which sub-personas it may spawn. Core or an enabled plugin can add role guidance with ordinary memory documents gated by `{kind, mode}`. Set the kind at spawn with `crtr node new --kind`, or change it live with `crtr node config --kind` / `crtr node promote --kind`.
|
|
27
27
|
|
|
28
28
|
**Why kinds exist at all.** Two payoffs a per-task instruction can't buy. First, **model-tier economics ride the kind boundary**: `explore` defaults to a fast/cheap model (right for mapping and summarization, wrong for judgment); `advisor` defaults to the slow, expensive think-y tier (right for debugging and tradeoffs). Fencing the tier into the kind is what stops an orchestrator from delegating debugging to a cheap explore scout. Second, a kind is **standing role discipline** that survives across every task of that type — the reviewer's neutral priming, the developer's done-bar, the planner's decision-resolution — rather than prose you must restate and that erodes each spawn.
|
|
29
29
|
|
|
@@ -31,20 +31,20 @@ A kind is a **persona** (gated memory docs at `kinds/<kind>/00-base.md` and `01-
|
|
|
31
31
|
|
|
32
32
|
| kind | what it's for | reach for it when |
|
|
33
33
|
|---|---|---|
|
|
34
|
-
| **general** | catch-all worker
|
|
35
|
-
| **explore** | read-only
|
|
36
|
-
| **advisor** | diagnosis, debugging, tradeoff analysis, engineering second opinions
|
|
37
|
-
| **spec** |
|
|
38
|
-
| **design** |
|
|
39
|
-
| **plan** |
|
|
40
|
-
| **developer** | implement a change
|
|
41
|
-
| **review** | critique code
|
|
34
|
+
| **general** | catch-all worker | no specialist role fits |
|
|
35
|
+
| **explore** | read-only current-state and code-path mapping | you need evidence about unfamiliar code or architecture, not diagnosis or recommendations |
|
|
36
|
+
| **advisor** | diagnosis, debugging, tradeoff analysis, and engineering second opinions | you need to explain a failure or judge a consequential call |
|
|
37
|
+
| **spec** | define what outcome and behavior to build | the requirement itself is unsettled |
|
|
38
|
+
| **design** | decide the structural shape of a solution | the implementation has consequential architectural choices |
|
|
39
|
+
| **plan** | sequence implementation of an approved specification or design | the outcome and structure are settled but the build path is not |
|
|
40
|
+
| **developer** | implement a change | you are building the feature or fix |
|
|
41
|
+
| **review** | independently critique code or an artifact | substantive work needs a severity-rated verdict |
|
|
42
42
|
|
|
43
|
-
The discriminators that get missed
|
|
43
|
+
The discriminators that get missed are **explore vs advisor** (mapping vs judgment), **spec vs design** (what to build vs how it is structured), and **design vs plan** (decide the shape vs sequence a decided shape).
|
|
44
44
|
|
|
45
45
|
### Sub-kinds
|
|
46
46
|
|
|
47
|
-
Specialist sub-personas hang off a parent kind
|
|
47
|
+
Specialist sub-personas hang off a parent kind. They are not in the top-level `--kind` list but are valid by exact registered path. Use one for a narrowly targeted assignment, not as a mandatory roster; discover the roles available from a kind with `crtr sys prompt-review --list --kind <kind>`. Core and plugins register sub-kinds through the same launch registry.
|
|
48
48
|
|
|
49
49
|
### Custom personas
|
|
50
50
|
|
|
@@ -13,4 +13,4 @@ The other internal/ docs explain the primitives one at a time; this dir shows th
|
|
|
13
13
|
|
|
14
14
|
- **imessage-assistant** — an OpenClaw-style always-on assistant: resident root node with its own dir and persona, woken event-style by a launchd watcher via `node message send`, reading `chat.db` (with the attributedBody gotcha), replying via osascript, remembering people through project-scope memory.
|
|
15
15
|
|
|
16
|
-
Add an example here when a composition was non-obvious enough that the next builder shouldn't have to re-derive it.
|
|
16
|
+
Add an example here when a composition was non-obvious enough that the next builder shouldn't have to re-derive it. Read `internal/examples` for this overview and its immediate example listing; the physical front door remains `INDEX.md`, but `INDEX` is not part of the canonical address.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
kind: knowledge
|
|
3
3
|
when-and-why-to-read: When you need to know why a memory doc did or didn't load — or are deciding how a new doc should surface — this reference should be read because it names the event, rung, gate, and ordering that produced the behavior, so you fix loading by turning the right dial instead of guessing at frontmatter.
|
|
4
|
-
short-form: The complete load model — the five surface events, the rung ladder, gates, listings,
|
|
4
|
+
short-form: The complete load model — the five surface events, the rung ladder, gates, listings, context exposure, boot-render ordering, and store mounting/precedence.
|
|
5
5
|
surfaces:
|
|
6
6
|
- on: boot
|
|
7
7
|
at: name
|
|
@@ -15,10 +15,10 @@ Every memory doc declares its own delivery in frontmatter `surfaces` entries; th
|
|
|
15
15
|
|
|
16
16
|
A doc with no `surfaces` does exactly one thing: appears in its directory's listing. Everything beyond that is an explicit entry — `{on: <event>, match?, match-frontmatter?, gate?, at: <rung>}`. An entry's event constraints and optional node-config `gate` must both match; participating entries OR across and fold to their highest rung (`content` > `preview` > `name`), with no cross-entry deny precedence. Multiple entries per event are legal. The events:
|
|
17
17
|
|
|
18
|
-
- **boot** — the
|
|
18
|
+
- **boot** — the frozen preference system snapshot and first-message knowledge catalog assembled when a context begins. No match; the entry's presence is the match.
|
|
19
19
|
- **workspace-open** — first-message context when cwd/profile mounts the doc's project store. Project stores only.
|
|
20
20
|
- **read** — a `read` tool call returned a matching file: path globs vs the file's absolute path and basename, `./`-anchored globs vs its path relative to the store's owning repo dir, `match-frontmatter` predicates over the read file's own YAML frontmatter.
|
|
21
|
-
- **memory-read** — a `crtr memory read` resolved a matching doc: name globs vs its canonical name, `./` anchored to this doc's own name
|
|
21
|
+
- **memory-read** — a `crtr memory read` resolved a matching doc: name globs vs its canonical name, `./` anchored to this doc's canonical routing anchor (a collapsed directory document anchors at its own directory name).
|
|
22
22
|
- **command** — a matching shell command ran: globs vs the whole command string, `*` crossing `/`. Delivery is post-execution — right for "you are now in this territory," never for "don't run this at all."
|
|
23
23
|
|
|
24
24
|
Nothing positional fires from where a doc happens to sit on disk — only from its declared entries and its listing.
|
|
@@ -39,9 +39,9 @@ A document-level `gate` is the hard eligibility predicate over the node's own co
|
|
|
39
39
|
|
|
40
40
|
## Listings and dedup
|
|
41
41
|
|
|
42
|
-
Reading a doc discloses where it sits: `crtr memory read <doc>` also renders, once per
|
|
42
|
+
Reading a doc discloses where it sits: `crtr memory read <doc>` also renders, once per loaded context, the listing of the doc's directory and each ancestor — one routing line per member doc, one bare name per subdirectory. A directory document owns its canonical directory node, so `crtr memory read <dir>` (or a bare-dir `[[ref]]`) returns that document's body followed by the directory's immediate listing without repeating the document; a directory without a document returns its listing. `unlisted: true` suppresses a doc from every listing. Store roots are never auto-listed — `crtr memory list` is the deliberate root browse.
|
|
43
43
|
|
|
44
|
-
Every delivery
|
|
44
|
+
Every delivery registers its document or listing identity and rung in the loaded context's exposure ledger. System and transcript ranks max-fold, so a higher rung pierces a lower one while a content delivery silences later lower-rung deliveries. A strict resume preserves that ledger and the byte-stable preference snapshot; yield or another new-context boundary replaces them with exactly the new system and first-message snapshots.
|
|
45
45
|
|
|
46
46
|
## Store mounting and precedence
|
|
47
47
|
|
|
@@ -53,7 +53,7 @@ The maximum reaches those two events and nothing else. Read, memory-read, and co
|
|
|
53
53
|
|
|
54
54
|
A workspace's front door is an ordinary doc carrying the entry pair `{on: workspace-open, at: content}` + `{on: read, match: "./**", at: content}` — the operating guide loads when that workspace mounts or its files are read, not in every boot catalog. `crtr memory lint` requires exactly one workspace-open content doc per profile-managed project store. Multiple mounted roots render broad-to-specific.
|
|
55
55
|
|
|
56
|
-
A `.crouter/memory/` store nested BELOW a mounted root (a package or subsystem dir) is delivered by the read path, not by boot: reading any file beneath its owning dir surfaces its read-routed docs,
|
|
56
|
+
A `.crouter/memory/` store nested BELOW a mounted root (a package or subsystem dir) is delivered by the read path, not by boot: reading any file beneath its owning dir surfaces its read-routed docs, filtered against what the loaded context already contains. Addressability is separate — the `crtr memory` leaves (list/read/find/lint/delete/origin) discover nested stores through a bounded walk (git-aware, depth- and time-capped), while the boot catalog stays ancestor+profile only, which is why a nested doc's boot entries are inert (lint warns; drop them).
|
|
57
57
|
|
|
58
58
|
## Ordering
|
|
59
59
|
|
|
@@ -33,7 +33,7 @@ If it's a one-off note for yourself, scope-owned memory docs are simpler. Promot
|
|
|
33
33
|
└── memory/
|
|
34
34
|
├── <name>.md # a kind:knowledge or kind:preference doc
|
|
35
35
|
└── <area>/
|
|
36
|
-
├── INDEX.md # optional
|
|
36
|
+
├── INDEX.md # optional physical front door; its canonical address is the directory and read combines body + immediate listing
|
|
37
37
|
└── <name>.md
|
|
38
38
|
```
|
|
39
39
|
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { listMemoryDocs } from "../../../commands/memory/list.js";
|
|
3
2
|
import { createMemoryDocSnapshot, readMemoryDocContent } from "../../../commands/memory/read.js";
|
|
3
|
+
import { parseSubstrateDoc } from "../../../core/substrate/schema.js";
|
|
4
4
|
import {
|
|
5
5
|
expandDeterministicCommand,
|
|
6
6
|
type DeterministicCommandExpansion,
|
|
7
7
|
} from "../../../core/runtime/command-expansion.js";
|
|
8
8
|
import { expandShellBlocks, hasShellBlocks, DEFAULT_SHELL_TIMEOUT_MS } from "../../../core/runtime/shell-expansion.js";
|
|
9
9
|
import type { ChatCommandMetadata } from "../../../core/runtime/command-surface.js";
|
|
10
|
+
import {
|
|
11
|
+
exposureTarget,
|
|
12
|
+
loadContextExposureState,
|
|
13
|
+
mergeContextExposureState,
|
|
14
|
+
registerDocumentExposure,
|
|
15
|
+
saveContextExposureState,
|
|
16
|
+
sharedContextExposureState,
|
|
17
|
+
} from "../../../core/substrate/injected-store.js";
|
|
10
18
|
import { piShellRunner } from "./pi-shell-runner.js";
|
|
11
19
|
|
|
12
20
|
// ---------------------------------------------------------------------------
|
|
@@ -16,57 +24,50 @@ import { piShellRunner } from "./pi-shell-runner.js";
|
|
|
16
24
|
// the doc body (plus the user's free-text args) as a normal turn instead of
|
|
17
25
|
// requiring a separate skill-invocation mechanism.
|
|
18
26
|
//
|
|
19
|
-
// Discovery uses
|
|
20
|
-
// snapshot
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
// scope-precedence sorted (see `scopeRank` in crouter's memory/shared.ts), so
|
|
24
|
-
// first-occurrence-wins per doc name reproduces the resolver's identity
|
|
25
|
-
// precedence for free. The inventory carries parsed `slash` flags and resolved
|
|
26
|
-
// paths for command bodies.
|
|
27
|
+
// Discovery uses one in-process target snapshot for both listing and body
|
|
28
|
+
// resolution. The snapshot already resolves exact canonical identities in
|
|
29
|
+
// source precedence; this file does not walk memory directories or reimplement
|
|
30
|
+
// scope resolution.
|
|
27
31
|
// ---------------------------------------------------------------------------
|
|
28
32
|
|
|
29
33
|
interface MemoryListItem {
|
|
30
34
|
name: string;
|
|
31
|
-
path: string;
|
|
32
35
|
short_form: string;
|
|
33
36
|
slash: boolean;
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
export interface SlashDoc {
|
|
37
|
-
/**
|
|
38
|
-
* `crtr memory read` resolves. */
|
|
40
|
+
/** Canonical name resolved by `crtr memory read`. */
|
|
39
41
|
name: string;
|
|
40
|
-
/**
|
|
41
|
-
* unchanged). */
|
|
42
|
+
/** Canonical `/` segments rendered as ordinary `:` command segments. */
|
|
42
43
|
commandName: string;
|
|
43
44
|
/** The memory document's short-form description, shown in the slash menu. */
|
|
44
45
|
description: string;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
//
|
|
48
|
-
//
|
|
48
|
+
// Keep each canonical winner's body and path for disclosure classification and
|
|
49
|
+
// the existing execution read.
|
|
49
50
|
const resolvedMemoryDocs = new Map<string, { path: string; canonicalBody: string }>();
|
|
50
51
|
|
|
51
52
|
async function defaultListMemoryDocs(): Promise<MemoryListItem[]> {
|
|
52
53
|
const snapshot = createMemoryDocSnapshot();
|
|
53
|
-
const items =
|
|
54
|
-
name: doc.name,
|
|
55
|
-
path: doc.path,
|
|
56
|
-
short_form: doc.shortForm,
|
|
57
|
-
slash: doc.slash,
|
|
58
|
-
}));
|
|
59
|
-
|
|
60
|
-
// Slash eligibility follows the list identity, while the body follows the
|
|
61
|
-
// separate `memory read <name>` resolver contract (including direct-path
|
|
62
|
-
// precedence). Resolve all eligible names against one source snapshot.
|
|
54
|
+
const items: MemoryListItem[] = [];
|
|
63
55
|
const seen = new Set<string>();
|
|
64
|
-
const
|
|
65
|
-
if (seen.has(
|
|
66
|
-
seen.add(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
for (const memoryDoc of snapshot.docs) {
|
|
57
|
+
if (seen.has(memoryDoc.name)) continue;
|
|
58
|
+
seen.add(memoryDoc.name);
|
|
59
|
+
const doc = parseSubstrateDoc(memoryDoc);
|
|
60
|
+
if (doc === null) continue;
|
|
61
|
+
items.push({
|
|
62
|
+
name: memoryDoc.name,
|
|
63
|
+
short_form: doc.shortForm,
|
|
64
|
+
slash: doc.slash,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Resolve eligible canonical names against the same target snapshot that
|
|
69
|
+
// supplied the list rows.
|
|
70
|
+
const resolved = snapshot.resolve(items.filter((item) => item.slash).map((item) => item.name));
|
|
70
71
|
resolvedMemoryDocs.clear();
|
|
71
72
|
for (const [name, doc] of resolved) {
|
|
72
73
|
resolvedMemoryDocs.set(name, { path: doc.path, canonicalBody: doc.body });
|
|
@@ -74,27 +75,36 @@ async function defaultListMemoryDocs(): Promise<MemoryListItem[]> {
|
|
|
74
75
|
return items;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
function defaultReadMemoryDoc(name: string): { canonicalBody: string; executionBody: string } {
|
|
78
|
+
function defaultReadMemoryDoc(name: string): { path: string; canonicalBody: string; executionBody: string } {
|
|
78
79
|
const resolved = resolvedMemoryDocs.get(name);
|
|
79
80
|
if (resolved === undefined) throw new Error(`memory slash document was not resolved: ${name}`);
|
|
80
81
|
return {
|
|
82
|
+
path: resolved.path,
|
|
81
83
|
canonicalBody: resolved.canonicalBody,
|
|
82
84
|
executionBody: readMemoryDocContent(resolved.path),
|
|
83
85
|
};
|
|
84
86
|
}
|
|
85
87
|
|
|
88
|
+
function registerSlashExposure(path: string, body: string): void {
|
|
89
|
+
const nodeId = process.env["CRTR_NODE_ID"];
|
|
90
|
+
if (nodeId === undefined || nodeId === "") return;
|
|
91
|
+
const state = sharedContextExposureState(nodeId);
|
|
92
|
+
mergeContextExposureState(state, loadContextExposureState(nodeId));
|
|
93
|
+
registerDocumentExposure(exposureTarget(state, "transcript"), path, body, "content");
|
|
94
|
+
saveContextExposureState(nodeId, state);
|
|
95
|
+
}
|
|
96
|
+
|
|
86
97
|
function hasNodeRelativeExpansion(body: string): boolean {
|
|
87
98
|
return body.includes("$CRTR_CONTEXT_DIR") || body.includes("$CRTR_NODE_ID");
|
|
88
99
|
}
|
|
89
100
|
|
|
90
|
-
/**
|
|
101
|
+
/** Canonical name -> the registered slash-command name. */
|
|
91
102
|
export function slashCommandName(docName: string): string {
|
|
92
103
|
return docName.split("/").join(":");
|
|
93
104
|
}
|
|
94
105
|
|
|
95
|
-
/** Every `slash: true`
|
|
96
|
-
*
|
|
97
|
-
* without `slash` (or `slash: false`) is silently excluded. */
|
|
106
|
+
/** Every `slash: true` canonical winner, scope-precedence-deduped by name. A
|
|
107
|
+
* doc without `slash` (or `slash: false`) is silently excluded. */
|
|
98
108
|
export async function discoverSlashDocs(): Promise<SlashDoc[]> {
|
|
99
109
|
let items: MemoryListItem[];
|
|
100
110
|
try {
|
|
@@ -118,6 +128,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
118
128
|
const docs = await discoverSlashDocs();
|
|
119
129
|
for (const doc of docs) {
|
|
120
130
|
let expansion: DeterministicCommandExpansion | undefined;
|
|
131
|
+
let exposure: { path: string; body: string } | undefined;
|
|
121
132
|
let discloseExpansion = false;
|
|
122
133
|
let loadError: unknown;
|
|
123
134
|
try {
|
|
@@ -127,6 +138,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
127
138
|
commandName: doc.commandName,
|
|
128
139
|
body: body.executionBody,
|
|
129
140
|
};
|
|
141
|
+
exposure = { path: body.path, body: body.canonicalBody };
|
|
130
142
|
discloseExpansion = !hasNodeRelativeExpansion(body.canonicalBody);
|
|
131
143
|
} catch (err) {
|
|
132
144
|
loadError = err;
|
|
@@ -174,6 +186,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
174
186
|
},
|
|
175
187
|
{ triggerTurn: true },
|
|
176
188
|
);
|
|
189
|
+
if (exposure !== undefined) registerSlashExposure(exposure.path, exposure.body);
|
|
177
190
|
},
|
|
178
191
|
} as Parameters<ExtensionAPI["registerCommand"]>[1] & { expansion?: DeterministicCommandExpansion } & ChatCommandMetadata);
|
|
179
192
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Regression: a viewer pane lost `@crtr_node` and `@crtr_attach` while a live
|
|
2
|
+
// viewer was running in it, so `surface reload` and viewer focus refused the
|
|
3
|
+
// pane (`no_viewer`, exit 2) until it was re-tagged by hand.
|
|
4
|
+
//
|
|
5
|
+
// tmux `respawn-pane -k` SIGHUPs the outgoing viewer and starts the replacement
|
|
6
|
+
// ~50ms later without waiting for it. Measured on this machine: SIGHUP at t+0,
|
|
7
|
+
// successor running at t+49ms. An outgoing viewer whose event loop was busy
|
|
8
|
+
// when the signal landed therefore ran its teardown AFTER the successor had
|
|
9
|
+
// claimed the pane, and cleared the successor's tags.
|
|
10
|
+
// Run with: node --conditions=crtr-src --import tsx/esm --test 'src/clients/attach/__tests__/pane-tag-successor.test.ts'
|
|
11
|
+
import { test } from 'node:test';
|
|
12
|
+
import assert from 'node:assert/strict';
|
|
13
|
+
import { createPaneTag } from '../session/pane-tag.js';
|
|
14
|
+
const PANE = '%474';
|
|
15
|
+
const NODE = '3zl47w7d-mt0chixr-cd2fc29b';
|
|
16
|
+
function fakeTmux() {
|
|
17
|
+
const options = new Map();
|
|
18
|
+
let stampCounter = 1_000;
|
|
19
|
+
const io = (pid) => ({
|
|
20
|
+
readOption: (_pane, name) => options.get(name) ?? '',
|
|
21
|
+
writeOption: (_pane, name, value) => { options.set(name, value); },
|
|
22
|
+
stampAsync: () => { options.set('@crtr_viewer_at', String(++stampCounter)); },
|
|
23
|
+
currentPane: () => PANE,
|
|
24
|
+
ownerId: () => pid,
|
|
25
|
+
});
|
|
26
|
+
return { options, io };
|
|
27
|
+
}
|
|
28
|
+
test('a late teardown does not clear the tags of the viewer that replaced it', () => {
|
|
29
|
+
const { options, io } = fakeTmux();
|
|
30
|
+
const outgoing = createPaneTag(false, NODE, io('4001'));
|
|
31
|
+
outgoing.set();
|
|
32
|
+
// The replacement claims the pane while the outgoing viewer is still busy.
|
|
33
|
+
const successor = createPaneTag(false, NODE, io('4002'));
|
|
34
|
+
successor.set();
|
|
35
|
+
outgoing.clear();
|
|
36
|
+
assert.equal(options.get('@crtr_node'), NODE, 'live viewer kept its node tag');
|
|
37
|
+
assert.equal(options.get('@crtr_attach'), '1', 'live viewer kept its attach tag');
|
|
38
|
+
assert.notEqual(options.get('@crtr_viewer_at'), '', 'live viewer kept its stamp');
|
|
39
|
+
});
|
|
40
|
+
test('an ordinary teardown still clears the tags it owns', () => {
|
|
41
|
+
const { options, io } = fakeTmux();
|
|
42
|
+
const viewer = createPaneTag(false, NODE, io('4001'));
|
|
43
|
+
viewer.set();
|
|
44
|
+
viewer.clear();
|
|
45
|
+
assert.equal(options.get('@crtr_node'), '');
|
|
46
|
+
assert.equal(options.get('@crtr_attach'), '');
|
|
47
|
+
assert.equal(options.get('@crtr_viewer_at'), '');
|
|
48
|
+
});
|
|
49
|
+
test('a focus refresh does not cost a viewer its own claim', () => {
|
|
50
|
+
const { options, io } = fakeTmux();
|
|
51
|
+
const viewer = createPaneTag(false, NODE, io('4001'));
|
|
52
|
+
viewer.set();
|
|
53
|
+
viewer.stamp(); // focus refresh
|
|
54
|
+
viewer.clear();
|
|
55
|
+
assert.equal(options.get('@crtr_node'), '', 'the pane it still owns is cleared');
|
|
56
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import { relatedNodeDirs } from '../session/profile-files.js';
|
|
4
|
+
test('relatedNodeDirs includes a node family but not unrelated nodes', () => {
|
|
5
|
+
const nodes = [
|
|
6
|
+
{ node_id: 'root', cwd: '/work/root', parent: null },
|
|
7
|
+
{ node_id: 'parent', cwd: '/work/parent', parent: 'root' },
|
|
8
|
+
{ node_id: 'current', cwd: '/work/current', parent: 'parent' },
|
|
9
|
+
{ node_id: 'child', cwd: '/work/child', parent: 'current' },
|
|
10
|
+
{ node_id: 'grandchild', cwd: '/work/grandchild', parent: 'child' },
|
|
11
|
+
{ node_id: 'sibling', cwd: '/work/sibling', parent: 'parent' },
|
|
12
|
+
{ node_id: 'unrelated', cwd: '/work/unrelated', parent: null },
|
|
13
|
+
];
|
|
14
|
+
assert.deepEqual(relatedNodeDirs(nodes, 'current'), [
|
|
15
|
+
'/work/root',
|
|
16
|
+
'/work/parent',
|
|
17
|
+
'/work/current',
|
|
18
|
+
'/work/child',
|
|
19
|
+
'/work/grandchild',
|
|
20
|
+
]);
|
|
21
|
+
});
|
|
@@ -91,16 +91,20 @@ export function createInboxStrip(s, hooks) {
|
|
|
91
91
|
// Same pending merge the inbox surface does — inbox-projected tickets plus
|
|
92
92
|
// reply-bearing no-inbox pages — but for every subtree node, then scoped to
|
|
93
93
|
// tickets whose origin is in the subtree.
|
|
94
|
+
// ONE page-history walk for the whole subtree, filtered by origin here.
|
|
95
|
+
// Calling `scanPageHistory(id)` per node re-walked every ticket directory
|
|
96
|
+
// once per subtree node — the same O(all tickets) scan repeated N times for
|
|
97
|
+
// a result that is just the union over subtree origins.
|
|
94
98
|
const merged = new Map();
|
|
95
99
|
for (const item of scanInbox())
|
|
96
100
|
merged.set(item.dir, item);
|
|
97
|
-
for (const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
for (const page of scanPageHistory()) {
|
|
102
|
+
if (page.source.nodeId === undefined || !nodes.has(page.source.nodeId))
|
|
103
|
+
continue;
|
|
104
|
+
if (page.state !== 'pending' || !page.awaitsResponse || page.inbox)
|
|
105
|
+
continue;
|
|
106
|
+
if (!merged.has(page.dir))
|
|
107
|
+
merged.set(page.dir, page);
|
|
104
108
|
}
|
|
105
109
|
tickets = [...merged.values()]
|
|
106
110
|
.filter((t) => t.source.nodeId !== undefined && nodes.has(t.source.nodeId))
|
|
@@ -5,13 +5,39 @@
|
|
|
5
5
|
* Split into a claim + a clear because ordering matters: a remote relay's "no
|
|
6
6
|
* node"/"no running broker" close can still throw AFTER the socket is up, so
|
|
7
7
|
* the tag is claimed only past that checkpoint — while `clear()` must be safe
|
|
8
|
-
* to call from a teardown that runs before it was ever claimed.
|
|
9
|
-
|
|
8
|
+
* to call from a teardown that runs before it was ever claimed.
|
|
9
|
+
*
|
|
10
|
+
* `clear()` also has to survive a SUCCESSOR already owning the pane. tmux
|
|
11
|
+
* `respawn-pane -k` only SIGHUPs the old viewer — it does not wait for it, and
|
|
12
|
+
* the replacement is running ~50ms later. A departing viewer whose event loop
|
|
13
|
+
* was busy when the signal arrived therefore runs its teardown after the
|
|
14
|
+
* replacement has claimed the pane, and an unconditional clear then wipes the
|
|
15
|
+
* LIVE viewer's identity: `nodeInPane()` returns nothing, so `surface reload`
|
|
16
|
+
* and viewer focus refuse the pane until someone re-tags it by hand. So the
|
|
17
|
+
* clear is conditional on still owning the pane, decided by `@crtr_viewer_pid`:
|
|
18
|
+
* a pane carrying someone else's pid has a successor, and its tags are not
|
|
19
|
+
* ours to remove. Skipping leaves at worst a stale tag on a dead pane, which
|
|
20
|
+
* `liveViewerPanes` and `surface reload` already validate against the live
|
|
21
|
+
* process; wiping a live viewer's tag has no such defense. */
|
|
22
|
+
/** The tmux reads and writes the tag lifecycle makes, injectable so the
|
|
23
|
+
* successor race is testable without a live tmux server. */
|
|
24
|
+
export interface PaneTagIo {
|
|
25
|
+
readOption: (pane: string, name: string) => string | undefined;
|
|
26
|
+
writeOption: (pane: string, name: string, value: string) => void;
|
|
27
|
+
stampAsync: (pane: string) => void;
|
|
28
|
+
currentPane: () => string | undefined;
|
|
29
|
+
/** This viewer process's identity — the pid, unique per viewer by construction. */
|
|
30
|
+
ownerId: () => string;
|
|
31
|
+
}
|
|
32
|
+
export declare function createPaneTag(remote: boolean, nodeId: string, io?: PaneTagIo): {
|
|
10
33
|
set: () => void;
|
|
11
34
|
stamp: () => void;
|
|
12
35
|
clear: () => void;
|
|
13
36
|
pane: () => string | undefined;
|
|
14
37
|
};
|
|
38
|
+
/** Which viewer process owns this pane's tags. Read only by `clear()`, so a
|
|
39
|
+
* departing viewer never removes a successor's identity. */
|
|
40
|
+
export declare const VIEWER_OWNER_OPTION = "@crtr_viewer_pid";
|
|
15
41
|
export declare function tagAttachPane(remote: boolean, pane: string | undefined, nodeId: string, setOpt?: (pane: string, name: string, value: string) => void): void;
|
|
16
42
|
export declare function untagAttachPane(remote: boolean, pane: string | undefined, setOpt?: (pane: string, name: string, value: string) => void): void;
|
|
17
43
|
export declare function tagAttachViewerPane(pane: string | undefined, setOpt?: (pane: string, name: string, value: string) => void): void;
|