@lumenflow/cli 4.23.0 → 5.0.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 +54 -52
- package/dist/agent-issues-query.js +10 -2
- package/dist/agent-issues-query.js.map +1 -1
- package/dist/agent-runtime-enrollment-events.js +44 -0
- package/dist/agent-runtime-enrollment-events.js.map +1 -0
- package/dist/agent-session-end.js +47 -0
- package/dist/agent-session-end.js.map +1 -1
- package/dist/agent-session-heartbeat.js +250 -0
- package/dist/agent-session-heartbeat.js.map +1 -0
- package/dist/agent-session.js +299 -5
- package/dist/agent-session.js.map +1 -1
- package/dist/capacity-snapshot-emitter.js +73 -0
- package/dist/capacity-snapshot-emitter.js.map +1 -0
- package/dist/claim-queue.js +276 -0
- package/dist/claim-queue.js.map +1 -0
- package/dist/config-set.js +22 -3
- package/dist/config-set.js.map +1 -1
- package/dist/control-plane-sidecar-runner.js +145 -0
- package/dist/control-plane-sidecar-runner.js.map +1 -0
- package/dist/delegation-list.js +160 -1
- package/dist/delegation-list.js.map +1 -1
- package/dist/delegation-role-resolver.js +69 -0
- package/dist/delegation-role-resolver.js.map +1 -0
- package/dist/docs-generate-pack-reference.js +500 -0
- package/dist/docs-generate-pack-reference.js.map +1 -0
- package/dist/docs-sync.js +116 -1
- package/dist/docs-sync.js.map +1 -1
- package/dist/file-edit.js +28 -8
- package/dist/file-edit.js.map +1 -1
- package/dist/file-write.js +29 -5
- package/dist/file-write.js.map +1 -1
- package/dist/gate-co-change.js +25 -7
- package/dist/gate-co-change.js.map +1 -1
- package/dist/gate-conditional.js +19 -7
- package/dist/gate-conditional.js.map +1 -1
- package/dist/gates-runners.js +42 -33
- package/dist/gates-runners.js.map +1 -1
- package/dist/gates-utils.js +34 -20
- package/dist/gates-utils.js.map +1 -1
- package/dist/gates.js +79 -7
- package/dist/gates.js.map +1 -1
- package/dist/hooks/config-resolver.js +10 -1
- package/dist/hooks/config-resolver.js.map +1 -1
- package/dist/init-package-config.js +1 -1
- package/dist/init-package-config.js.map +1 -1
- package/dist/init-scaffolding.js +5 -1
- package/dist/init-scaffolding.js.map +1 -1
- package/dist/init-templates.js +10 -0
- package/dist/init-templates.js.map +1 -1
- package/dist/init.js +1 -1
- package/dist/init.js.map +1 -1
- package/dist/initiative-create.js +17 -0
- package/dist/initiative-create.js.map +1 -1
- package/dist/initiative-remove-wu.js +17 -3
- package/dist/initiative-remove-wu.js.map +1 -1
- package/dist/kernel-event-sync/emitters.js +104 -0
- package/dist/kernel-event-sync/emitters.js.map +1 -0
- package/dist/kernel-event-sync/index.js +13 -0
- package/dist/kernel-event-sync/index.js.map +1 -0
- package/dist/kernel-event-sync/lifecycle-emitters.js +160 -0
- package/dist/kernel-event-sync/lifecycle-emitters.js.map +1 -0
- package/dist/kernel-event-sync/narrow-emissions.js +89 -0
- package/dist/kernel-event-sync/narrow-emissions.js.map +1 -0
- package/dist/kernel-event-sync/software-delivery-emitters.js +297 -0
- package/dist/kernel-event-sync/software-delivery-emitters.js.map +1 -0
- package/dist/lane-lock.js +14 -1
- package/dist/lane-lock.js.map +1 -1
- package/dist/lane-suggest.js +21 -0
- package/dist/lane-suggest.js.map +1 -1
- package/dist/lumenflow-upgrade.js +7 -5
- package/dist/lumenflow-upgrade.js.map +1 -1
- package/dist/mem-context.js +145 -0
- package/dist/mem-context.js.map +1 -1
- package/dist/mem-create.js +39 -6
- package/dist/mem-create.js.map +1 -1
- package/dist/mem-inbox.js +16 -0
- package/dist/mem-inbox.js.map +1 -1
- package/dist/mem-roster.js +95 -0
- package/dist/mem-roster.js.map +1 -0
- package/dist/mem-signal.js +97 -2
- package/dist/mem-signal.js.map +1 -1
- package/dist/metrics-cli.js +3 -2
- package/dist/metrics-cli.js.map +1 -1
- package/dist/metrics-snapshot.js +271 -13
- package/dist/metrics-snapshot.js.map +1 -1
- package/dist/orchestrate-init-status.js +117 -2
- package/dist/orchestrate-init-status.js.map +1 -1
- package/dist/orchestrate-initiative.js +83 -10
- package/dist/orchestrate-initiative.js.map +1 -1
- package/dist/orchestrate-monitor-quality.js +289 -0
- package/dist/orchestrate-monitor-quality.js.map +1 -0
- package/dist/orchestrate-monitor.js +85 -0
- package/dist/orchestrate-monitor.js.map +1 -1
- package/dist/pack-validate.js +127 -2
- package/dist/pack-validate.js.map +1 -1
- package/dist/plan-create.js +18 -0
- package/dist/plan-create.js.map +1 -1
- package/dist/plan-link.js +13 -0
- package/dist/plan-link.js.map +1 -1
- package/dist/plan-promote.js +14 -0
- package/dist/plan-promote.js.map +1 -1
- package/dist/pre-commit-check.js +4 -3
- package/dist/pre-commit-check.js.map +1 -1
- package/dist/public-manifest.js +17 -3
- package/dist/public-manifest.js.map +1 -1
- package/dist/release.js +10 -10
- package/dist/release.js.map +1 -1
- package/dist/session-cross-link.js +139 -0
- package/dist/session-cross-link.js.map +1 -0
- package/dist/sidecar-manager.js +208 -0
- package/dist/sidecar-manager.js.map +1 -0
- package/dist/state-path-resolvers.js +18 -0
- package/dist/state-path-resolvers.js.map +1 -1
- package/dist/stream-heartbeat.js +151 -0
- package/dist/stream-heartbeat.js.map +1 -0
- package/dist/sync-templates.js +56 -2
- package/dist/sync-templates.js.map +1 -1
- package/dist/wu-block.js +47 -5
- package/dist/wu-block.js.map +1 -1
- package/dist/wu-claim-branch.js +8 -4
- package/dist/wu-claim-branch.js.map +1 -1
- package/dist/wu-claim-state.js +5 -3
- package/dist/wu-claim-state.js.map +1 -1
- package/dist/wu-claim-worktree.js +5 -3
- package/dist/wu-claim-worktree.js.map +1 -1
- package/dist/wu-claim.js +261 -9
- package/dist/wu-claim.js.map +1 -1
- package/dist/wu-done-auto-cleanup.js +3 -2
- package/dist/wu-done-auto-cleanup.js.map +1 -1
- package/dist/wu-done-git-ops.js +12 -8
- package/dist/wu-done-git-ops.js.map +1 -1
- package/dist/wu-done-preflight.js +3 -3
- package/dist/wu-done-preflight.js.map +1 -1
- package/dist/wu-done.js +46 -10
- package/dist/wu-done.js.map +1 -1
- package/dist/wu-lifecycle-sync/gate-scope-resolver.js +16 -0
- package/dist/wu-lifecycle-sync/gate-scope-resolver.js.map +1 -0
- package/dist/wu-lifecycle-sync/kernel-event-sync-shim.js +10 -0
- package/dist/wu-lifecycle-sync/kernel-event-sync-shim.js.map +1 -0
- package/dist/wu-prep.js +363 -22
- package/dist/wu-prep.js.map +1 -1
- package/dist/wu-prune.js +68 -27
- package/dist/wu-prune.js.map +1 -1
- package/dist/wu-release.js +34 -3
- package/dist/wu-release.js.map +1 -1
- package/dist/wu-review.js +167 -0
- package/dist/wu-review.js.map +1 -0
- package/dist/wu-spawn-prompt-builders.js +296 -40
- package/dist/wu-spawn-prompt-builders.js.map +1 -1
- package/dist/wu-spawn-strategy-resolver.js +126 -14
- package/dist/wu-spawn-strategy-resolver.js.map +1 -1
- package/dist/wu-unblock.js +52 -22
- package/dist/wu-unblock.js.map +1 -1
- package/package.json +13 -8
- package/packs/agent-runtime/.turbo/turbo-build.log +1 -1
- package/packs/agent-runtime/.turbo/turbo-test.log +25 -0
- package/packs/agent-runtime/.turbo/turbo-typecheck.log +4 -0
- package/packs/agent-runtime/agent-heartbeat.ts +163 -0
- package/packs/agent-runtime/auto-session-integration.ts +874 -0
- package/packs/agent-runtime/delegation-registry-schema.ts +220 -0
- package/packs/agent-runtime/delegation-registry-store.ts +269 -0
- package/packs/agent-runtime/delegation-tree.ts +328 -0
- package/packs/agent-runtime/index.ts +9 -0
- package/packs/agent-runtime/manifest.ts +103 -19
- package/packs/agent-runtime/manifest.yaml +132 -0
- package/packs/agent-runtime/memory-coordination-contract.ts +86 -0
- package/packs/agent-runtime/memory.d.ts +19 -0
- package/packs/agent-runtime/orchestration.ts +238 -23
- package/packs/agent-runtime/package.json +11 -2
- package/packs/agent-runtime/remote-controls/index.ts +7 -0
- package/packs/agent-runtime/remote-controls/operations.ts +399 -0
- package/packs/agent-runtime/remote-controls/port.ts +48 -0
- package/packs/agent-runtime/remote-controls/state-store.ts +258 -0
- package/packs/agent-runtime/remote-controls/types.ts +105 -0
- package/packs/agent-runtime/session-schema.ts +423 -0
- package/packs/agent-runtime/tool-impl/index.ts +1 -0
- package/packs/agent-runtime/tool-impl/remote-controls.mock.ts +252 -0
- package/packs/agent-runtime/tool-impl/remote-controls.ts +273 -0
- package/packs/agent-runtime/tsconfig.json +1 -1
- package/packs/agent-runtime/turn-lifecycle-events.ts +501 -0
- package/packs/sidekick/.lumenflow/state/conductor/outbox/sidekick-events.jsonl +213 -0
- package/packs/sidekick/.turbo/turbo-build.log +1 -1
- package/packs/sidekick/.turbo/turbo-test.log +25 -0
- package/packs/sidekick/.turbo/turbo-typecheck.log +4 -0
- package/packs/sidekick/channel-ingress.ts +137 -0
- package/packs/sidekick/manifest.ts +74 -0
- package/packs/sidekick/manifest.yaml +88 -0
- package/packs/sidekick/package.json +3 -1
- package/packs/sidekick/sidekick-events.ts +517 -0
- package/packs/sidekick/src/adapters/cloud-queue.ts +101 -0
- package/packs/sidekick/src/adapters/control-plane-bridge.adapter.ts +378 -0
- package/packs/sidekick/src/adapters/filesystem-bridge.adapter.ts +224 -0
- package/packs/sidekick/src/domain/channel.types.ts +84 -0
- package/packs/sidekick/src/ports/channel-bridge.port.ts +75 -0
- package/packs/sidekick/src/routines/commit.ts +74 -0
- package/packs/sidekick/tool-impl/channel-tools.ts +47 -0
- package/packs/sidekick/tool-impl/memory-tools.ts +17 -0
- package/packs/sidekick/tool-impl/routine-commit.ts +102 -0
- package/packs/sidekick/tool-impl/routine-tools.ts +67 -7
- package/packs/sidekick/tool-impl/runtime-context.ts +4 -0
- package/packs/sidekick/tool-impl/storage.ts +3 -0
- package/packs/sidekick/tool-impl/system-tools.ts +7 -0
- package/packs/sidekick/tool-impl/task-tools.ts +46 -0
- package/packs/sidekick/tsconfig.json +1 -1
- package/packs/software-delivery/.turbo/turbo-build.log +1 -1
- package/packs/software-delivery/.turbo/turbo-test.log +63 -0
- package/packs/software-delivery/.turbo/turbo-typecheck.log +4 -0
- package/packs/software-delivery/manifest-schema.ts +30 -0
- package/packs/software-delivery/manifest.ts +99 -1
- package/packs/software-delivery/manifest.yaml +46 -0
- package/packs/software-delivery/package.json +88 -3
- package/packs/software-delivery/src/commands/index.ts +5 -0
- package/packs/software-delivery/src/config/delivery-review-contract.ts +20 -0
- package/packs/software-delivery/src/config/env-accessors.ts +19 -0
- package/packs/software-delivery/src/config/index.ts +8 -0
- package/packs/software-delivery/src/config/normalize-config-keys.ts +19 -0
- package/packs/software-delivery/src/config/schemas/lumenflow-config-schema-types.ts +436 -0
- package/packs/software-delivery/src/config/workspace-reader.ts +310 -0
- package/packs/software-delivery/src/constants/backlog-patterns.ts +31 -0
- package/packs/software-delivery/src/constants/client-ids.ts +19 -0
- package/packs/software-delivery/src/constants/config-contract.ts +7 -0
- package/packs/software-delivery/src/constants/docs-layout-presets.ts +50 -0
- package/packs/software-delivery/src/constants/duration-constants.ts +20 -0
- package/packs/software-delivery/src/constants/gate-constants.ts +32 -0
- package/packs/software-delivery/src/constants/index.ts +29 -0
- package/packs/software-delivery/src/constants/lock-constants.ts +35 -0
- package/packs/software-delivery/src/constants/object-guards.ts +12 -0
- package/packs/software-delivery/src/constants/section-headings.ts +107 -0
- package/packs/software-delivery/src/constants/wu-cli-constants.ts +485 -0
- package/packs/software-delivery/src/constants/wu-domain-constants.ts +466 -0
- package/packs/software-delivery/src/constants/wu-git-constants.ts +7 -0
- package/packs/software-delivery/src/constants/wu-id-format.ts +327 -0
- package/packs/software-delivery/src/constants/wu-paths-constants.ts +358 -0
- package/packs/software-delivery/src/constants/wu-statuses.ts +287 -0
- package/packs/software-delivery/src/constants/wu-type-helpers.ts +67 -0
- package/packs/software-delivery/src/constants/wu-ui-constants.ts +267 -0
- package/packs/software-delivery/src/constants/wu-validation-constants.ts +73 -0
- package/packs/software-delivery/src/domain/index.ts +5 -0
- package/packs/software-delivery/src/domain/orchestration.constants.ts +168 -0
- package/packs/software-delivery/src/domain/orchestration.schemas.ts +239 -0
- package/packs/software-delivery/src/domain/orchestration.types.ts +178 -0
- package/packs/software-delivery/src/methodology/incremental-test.ts +90 -0
- package/packs/software-delivery/src/methodology/index.ts +6 -0
- package/packs/software-delivery/src/methodology/manual-test-validator.ts +292 -0
- package/packs/software-delivery/src/policy/coverage-gate.ts +270 -0
- package/packs/software-delivery/src/policy/gates-agent-mode.ts +223 -0
- package/packs/software-delivery/src/policy/gates-config-internal.ts +121 -0
- package/packs/software-delivery/src/policy/gates-config.ts +293 -0
- package/packs/software-delivery/src/policy/gates-coverage.ts +247 -0
- package/packs/software-delivery/src/policy/gates-presets.ts +134 -0
- package/packs/software-delivery/src/policy/gates-schemas.ts +173 -0
- package/packs/software-delivery/src/policy/index.ts +22 -0
- package/packs/software-delivery/src/policy/package-manager-resolver.ts +319 -0
- package/packs/software-delivery/src/policy/resolve-policy.ts +518 -0
- package/packs/software-delivery/src/ports/config.ports.ts +90 -0
- package/packs/software-delivery/src/ports/dashboard-renderer.port.ts +125 -0
- package/packs/software-delivery/src/ports/index.ts +10 -0
- package/packs/software-delivery/src/ports/sync-validator.ports.ts +59 -0
- package/packs/software-delivery/src/ports/wu-helpers.ports.ts +168 -0
- package/packs/software-delivery/src/ports/wu-state.ports.ts +241 -0
- package/packs/software-delivery/src/primitives/index.ts +5 -0
- package/packs/software-delivery/src/runtime/index.ts +6 -0
- package/packs/software-delivery/src/runtime/work-classifier.ts +561 -0
- package/packs/software-delivery/src/sandbox/index.ts +10 -0
- package/packs/software-delivery/src/sandbox/sandbox-allowlist.ts +118 -0
- package/packs/software-delivery/src/sandbox/sandbox-backend-linux.ts +88 -0
- package/packs/software-delivery/src/sandbox/sandbox-backend-macos.ts +154 -0
- package/packs/software-delivery/src/sandbox/sandbox-backend-windows.ts +47 -0
- package/packs/software-delivery/src/sandbox/sandbox-profile.ts +153 -0
- package/packs/software-delivery/src/schemas/index.ts +5 -0
- package/packs/software-delivery/src/state/date-utils.ts +158 -0
- package/packs/software-delivery/src/state/index.ts +15 -0
- package/packs/software-delivery/src/state/state-machine.ts +119 -0
- package/packs/software-delivery/src/state/wu-doc-types.ts +51 -0
- package/packs/software-delivery/src/state/wu-paths.ts +381 -0
- package/packs/software-delivery/src/state/wu-schema.ts +1139 -0
- package/packs/software-delivery/src/state/wu-state-schema.ts +255 -0
- package/packs/software-delivery/src/state/wu-yaml.ts +338 -0
- package/packs/software-delivery/src/types.d.ts +16 -0
- package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +18 -0
- package/packs/software-delivery/tsconfig.json +28 -2
- package/templates/core/AGENTS.md.template +76 -17
- package/templates/core/LUMENFLOW.md.template +265 -66
- package/templates/core/_frameworks/lumenflow/wu-sizing-guide.md.template +180 -116
- package/templates/core/ai/onboarding/agent-invocation-guide.md.template +26 -8
- package/templates/core/ai/onboarding/existing-project-bootstrap.md.template +171 -0
- package/templates/core/ai/onboarding/first-15-mins.md.template +3 -1
- package/templates/core/ai/onboarding/first-wu-mistakes.md.template +1 -1
- package/templates/core/ai/onboarding/initiative-orchestration.md.template +46 -30
- package/templates/core/ai/onboarding/quick-ref-commands.md.template +36 -33
- package/templates/core/ai/onboarding/release-process.md.template +8 -7
- package/templates/core/ai/onboarding/starting-prompt.md.template +2 -0
- package/templates/core/ai/onboarding/troubleshooting-wu-done.md.template +62 -0
- package/templates/vendors/claude/.claude/CLAUDE.md.template +29 -54
- package/templates/vendors/cursor/.cursor/rules/lumenflow.md.template +24 -52
- package/templates/vendors/windsurf/.windsurf/rules/lumenflow.md.template +24 -52
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// Copyright (c) 2026 Hellmai Ltd
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* WU-2731 (INIT-060 phase 3, ADR-013 §5 Identity):
|
|
6
|
+
* Pure inbound-channel ingress sanitizer.
|
|
7
|
+
*
|
|
8
|
+
* ADR-013 §5 rules, enforced here:
|
|
9
|
+
*
|
|
10
|
+
* - The authoritative `from` value for an inbound phone POST comes from the
|
|
11
|
+
* authenticated token subject (`{workspace_id}:phone:{device_id}`). Cloud
|
|
12
|
+
* MUST NOT trust a `from` field supplied in the request body.
|
|
13
|
+
*
|
|
14
|
+
* - Body-supplied `from` (and any alias under `metadata.from`) is stripped
|
|
15
|
+
* before the envelope reaches domain code. The surface that calls this
|
|
16
|
+
* module is expected to pass the resolved `from` separately; attempting to
|
|
17
|
+
* ingest a body-only envelope (no authoritative from) fails closed.
|
|
18
|
+
*
|
|
19
|
+
* The module is HTTP-independent: both the kernel tool-api surface and the
|
|
20
|
+
* future control-plane adapter (WU-2737) call the same sanitizer so the
|
|
21
|
+
* ignore-body-from rule is enforced in one place.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const ENVELOPE_BODY_FIELD_FROM = 'from' as const;
|
|
25
|
+
const ENVELOPE_METADATA_KEY = 'metadata' as const;
|
|
26
|
+
const ENVELOPE_FROM_SOURCE_TOKEN = 'token' as const;
|
|
27
|
+
|
|
28
|
+
export interface PhoneChannelIngressInput {
|
|
29
|
+
/**
|
|
30
|
+
* Raw request body as parsed from JSON. Opaque record; the sanitizer does
|
|
31
|
+
* not inspect `body`, only the `from` attribution fields.
|
|
32
|
+
*/
|
|
33
|
+
body: Readonly<Record<string, unknown>>;
|
|
34
|
+
/**
|
|
35
|
+
* Authoritative identity claim resolved from the bearer token. Required:
|
|
36
|
+
* without a token subject, cloud cannot attribute the message, and the
|
|
37
|
+
* ingress path rejects the request.
|
|
38
|
+
*/
|
|
39
|
+
authoritativeFrom: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface PhoneChannelIngressEnvelope {
|
|
43
|
+
/**
|
|
44
|
+
* Sanitised request body with any body-level `from` stripped. Everything
|
|
45
|
+
* else the caller supplied is preserved so downstream code (channel.send,
|
|
46
|
+
* routing) can consume arbitrary payload fields.
|
|
47
|
+
*/
|
|
48
|
+
body: Record<string, unknown>;
|
|
49
|
+
/** Authoritative attribution string (`{workspace_id}:phone:{device_id}`). */
|
|
50
|
+
from: string;
|
|
51
|
+
/** Always `'token'` — cloud-safe invariant per ADR-013 §5. */
|
|
52
|
+
from_source: typeof ENVELOPE_FROM_SOURCE_TOKEN;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class PhoneChannelIngressError extends Error {
|
|
56
|
+
readonly statusCode: number;
|
|
57
|
+
|
|
58
|
+
constructor(message: string, statusCode: number) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = 'PhoneChannelIngressError';
|
|
61
|
+
this.statusCode = statusCode;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Sanitize an inbound phone-channel request. Returns a cleaned envelope with
|
|
67
|
+
* the authoritative `from` baked in. Throws `PhoneChannelIngressError` (HTTP
|
|
68
|
+
* 400) when the authoritative `from` is missing — the surface translates the
|
|
69
|
+
* error to a 400/403 response.
|
|
70
|
+
*/
|
|
71
|
+
export function sanitizePhoneChannelIngress(
|
|
72
|
+
input: PhoneChannelIngressInput,
|
|
73
|
+
): PhoneChannelIngressEnvelope {
|
|
74
|
+
if (typeof input.authoritativeFrom !== 'string' || input.authoritativeFrom.length === 0) {
|
|
75
|
+
throw new PhoneChannelIngressError(
|
|
76
|
+
'Inbound phone channel requires authoritative from (token subject); body-only attribution is rejected.',
|
|
77
|
+
400,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const sanitizedBody = stripKey(input.body, ENVELOPE_BODY_FIELD_FROM);
|
|
82
|
+
const rawMetadata = sanitizedBody[ENVELOPE_METADATA_KEY];
|
|
83
|
+
if (
|
|
84
|
+
rawMetadata !== null &&
|
|
85
|
+
typeof rawMetadata === 'object' &&
|
|
86
|
+
!Array.isArray(rawMetadata) &&
|
|
87
|
+
ENVELOPE_BODY_FIELD_FROM in (rawMetadata as Record<string, unknown>)
|
|
88
|
+
) {
|
|
89
|
+
sanitizedBody[ENVELOPE_METADATA_KEY] = stripKey(
|
|
90
|
+
rawMetadata as Record<string, unknown>,
|
|
91
|
+
ENVELOPE_BODY_FIELD_FROM,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
body: sanitizedBody,
|
|
97
|
+
from: input.authoritativeFrom,
|
|
98
|
+
from_source: ENVELOPE_FROM_SOURCE_TOKEN,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Copy `record` omitting the given key. Implemented with a filtered
|
|
104
|
+
* `Object.entries` rather than `delete` to satisfy the linter's ban on
|
|
105
|
+
* dynamic-delete (which would otherwise be a no-op for literal keys but
|
|
106
|
+
* fails the rule uniformly).
|
|
107
|
+
*/
|
|
108
|
+
function stripKey(record: Readonly<Record<string, unknown>>, key: string): Record<string, unknown> {
|
|
109
|
+
const result: Record<string, unknown> = {};
|
|
110
|
+
for (const [entryKey, entryValue] of Object.entries(record)) {
|
|
111
|
+
if (entryKey !== key) {
|
|
112
|
+
result[entryKey] = entryValue;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Convenience: reports whether the given `from` subject matches the
|
|
120
|
+
* phone-device grammar (`{workspace_id}:phone:{device_id}`). Useful to
|
|
121
|
+
* tell workspace-scoped actors from phone-device actors in the audit log
|
|
122
|
+
* without reaching for the enrollment parser.
|
|
123
|
+
*/
|
|
124
|
+
export function isPhoneSubject(subject: string): boolean {
|
|
125
|
+
const parts = subject.split(':');
|
|
126
|
+
if (parts.length !== 3) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
const [workspace, kind, device] = parts;
|
|
130
|
+
return (
|
|
131
|
+
kind === 'phone' &&
|
|
132
|
+
typeof workspace === 'string' &&
|
|
133
|
+
workspace.length > 0 &&
|
|
134
|
+
typeof device === 'string' &&
|
|
135
|
+
device.length > 0
|
|
136
|
+
);
|
|
137
|
+
}
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
type PathScope,
|
|
17
17
|
type ToolPermission,
|
|
18
18
|
} from './tools/types.js';
|
|
19
|
+
import { SIDEKICK_EVENT_KIND_VALUES } from './sidekick-events.js';
|
|
19
20
|
|
|
20
21
|
// ---------------------------------------------------------------------------
|
|
21
22
|
// Scope constants
|
|
@@ -62,6 +63,10 @@ const TOOL_PERMISSIONS_MAP = {
|
|
|
62
63
|
'routine:update': TOOL_PERMISSIONS.WRITE,
|
|
63
64
|
'routine:delete': TOOL_PERMISSIONS.ADMIN,
|
|
64
65
|
'routine:run': TOOL_PERMISSIONS.READ, // plan-only, no execution
|
|
66
|
+
// WU-2738 (INIT-060, ADR-013 §6 governance): plan-to-commit flow routed
|
|
67
|
+
// through agent:execute-turn. Runtime-callable tool, no top-level
|
|
68
|
+
// surface -- the governed dispatch is the only path to commit a plan.
|
|
69
|
+
'sidekick:routine:commit_plan': TOOL_PERMISSIONS.WRITE,
|
|
65
70
|
// System tools (3)
|
|
66
71
|
'sidekick:init': TOOL_PERMISSIONS.WRITE,
|
|
67
72
|
'sidekick:status': TOOL_PERMISSIONS.READ,
|
|
@@ -74,6 +79,7 @@ const TASK_TOOLS_ENTRY = 'tool-impl/task-tools.ts';
|
|
|
74
79
|
const MEMORY_TOOLS_ENTRY = 'tool-impl/memory-tools.ts';
|
|
75
80
|
const CHANNEL_TOOLS_ENTRY = 'tool-impl/channel-tools.ts';
|
|
76
81
|
const ROUTINE_TOOLS_ENTRY = 'tool-impl/routine-tools.ts';
|
|
82
|
+
const ROUTINE_COMMIT_TOOL_ENTRY = 'tool-impl/routine-commit.ts';
|
|
77
83
|
const SYSTEM_TOOLS_ENTRY = 'tool-impl/system-tools.ts';
|
|
78
84
|
const POLICY_FACTORY_ENTRY = 'policy-factory.ts#createSidekickPolicyFactory';
|
|
79
85
|
|
|
@@ -98,6 +104,7 @@ const TOOL_ENTRIES: Record<SidekickToolName, string> = {
|
|
|
98
104
|
'routine:update': ROUTINE_TOOLS_ENTRY,
|
|
99
105
|
'routine:delete': ROUTINE_TOOLS_ENTRY,
|
|
100
106
|
'routine:run': ROUTINE_TOOLS_ENTRY,
|
|
107
|
+
'sidekick:routine:commit_plan': ROUTINE_COMMIT_TOOL_ENTRY,
|
|
101
108
|
'sidekick:init': SYSTEM_TOOLS_ENTRY,
|
|
102
109
|
'sidekick:status': SYSTEM_TOOLS_ENTRY,
|
|
103
110
|
'sidekick:export': SYSTEM_TOOLS_ENTRY,
|
|
@@ -343,6 +350,23 @@ const TOOL_INPUT_SCHEMAS: Record<SidekickToolName, Record<string, unknown>> = {
|
|
|
343
350
|
required: ['id'],
|
|
344
351
|
additionalProperties: false,
|
|
345
352
|
},
|
|
353
|
+
'sidekick:routine:commit_plan': {
|
|
354
|
+
type: 'object',
|
|
355
|
+
properties: {
|
|
356
|
+
plan_id: { type: 'string', minLength: 1 },
|
|
357
|
+
attestation: {
|
|
358
|
+
type: 'object',
|
|
359
|
+
properties: {
|
|
360
|
+
actor: { type: 'string', minLength: 1 },
|
|
361
|
+
reason: { type: 'string', minLength: 1 },
|
|
362
|
+
},
|
|
363
|
+
required: ['actor', 'reason'],
|
|
364
|
+
additionalProperties: true,
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
required: ['plan_id', 'attestation'],
|
|
368
|
+
additionalProperties: false,
|
|
369
|
+
},
|
|
346
370
|
'sidekick:init': {
|
|
347
371
|
type: 'object',
|
|
348
372
|
properties: {},
|
|
@@ -387,8 +411,17 @@ function resolveRequiredScopes(permission: ToolPermission): PathScope[] {
|
|
|
387
411
|
return [SIDEKICK_SCOPE_READ, SIDEKICK_SCOPE_WRITE];
|
|
388
412
|
}
|
|
389
413
|
|
|
414
|
+
// WU-2738 (INIT-060, ADR-013 §6 governance): tool-level approval surface
|
|
415
|
+
// declarations. Empty array means the default policy permits dispatch; a
|
|
416
|
+
// populated array signals the cloud conductor to render an approval prompt
|
|
417
|
+
// before the governed `agent:execute-turn` dispatch invokes the tool.
|
|
418
|
+
const TOOL_REQUIRED_APPROVALS: Partial<Record<SidekickToolName, string[]>> = {
|
|
419
|
+
'sidekick:routine:commit_plan': [],
|
|
420
|
+
};
|
|
421
|
+
|
|
390
422
|
function buildTool(name: SidekickToolName): SidekickManifestTool {
|
|
391
423
|
const permission = TOOL_PERMISSIONS_MAP[name];
|
|
424
|
+
const requiredApprovals = TOOL_REQUIRED_APPROVALS[name];
|
|
392
425
|
return {
|
|
393
426
|
name,
|
|
394
427
|
entry: TOOL_ENTRIES[name],
|
|
@@ -396,6 +429,7 @@ function buildTool(name: SidekickToolName): SidekickManifestTool {
|
|
|
396
429
|
required_scopes: resolveRequiredScopes(permission),
|
|
397
430
|
input_schema: TOOL_INPUT_SCHEMAS[name],
|
|
398
431
|
output_schema: GENERIC_OUTPUT_SCHEMA,
|
|
432
|
+
...(requiredApprovals !== undefined ? { required_approvals: requiredApprovals } : {}),
|
|
399
433
|
};
|
|
400
434
|
}
|
|
401
435
|
|
|
@@ -405,6 +439,41 @@ function buildTool(name: SidekickToolName): SidekickManifestTool {
|
|
|
405
439
|
|
|
406
440
|
export const SIDEKICK_TOOL_NAMES = Object.keys(TOOL_PERMISSIONS_MAP) as SidekickToolName[];
|
|
407
441
|
|
|
442
|
+
/**
|
|
443
|
+
* WU-2780 (ADR-013 §6 governance): tool names the sidekick pack forbids from
|
|
444
|
+
* the top-level remote surface (POST /tools/:name). These tools remain
|
|
445
|
+
* registered as runtime-callable — `agent:execute-turn` dispatches them via
|
|
446
|
+
* the governed manifest path — but any HTTP allowlist that includes them
|
|
447
|
+
* MUST be rejected fail-closed. ADR-013 §6 explicitly names `channel.send`:
|
|
448
|
+
* "The sidekick pack does NOT expose `channel.send` as a top-level surface
|
|
449
|
+
* the agent can call outside a turn. It is registered only as a
|
|
450
|
+
* runtime-callable tool."
|
|
451
|
+
*/
|
|
452
|
+
const ADR_013_SECTION_6_RUNTIME_ONLY_TOOLS: readonly SidekickToolName[] = ['channel:send'] as const;
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* WU-2780 (INIT-060, ADR-013 §6): sidekick pack tools that MAY be exposed on
|
|
456
|
+
* the HTTP tool-api surface (POST /tools/:name). Mirrors the
|
|
457
|
+
* `REMOTE_CALLABLE_TOOLS` export pattern in sibling packs (software-delivery,
|
|
458
|
+
* agent-runtime) so integrators have a single source of truth when wiring
|
|
459
|
+
* the surface allowlist. ADR-013 §6 runtime-only tools are excluded by
|
|
460
|
+
* construction; the HTTP tool-api also enforces this fail-closed at router
|
|
461
|
+
* construction.
|
|
462
|
+
*/
|
|
463
|
+
export const SIDEKICK_REMOTE_CALLABLE_TOOLS: readonly SidekickToolName[] =
|
|
464
|
+
SIDEKICK_TOOL_NAMES.filter(
|
|
465
|
+
(name): name is SidekickToolName => !ADR_013_SECTION_6_RUNTIME_ONLY_TOOLS.includes(name),
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* WU-2780 (INIT-060, ADR-013 §6): returns a fresh copy of the ordered
|
|
470
|
+
* remote-callable tool name list. Keeps the export immutable for callers
|
|
471
|
+
* that prefer arrays over readonly tuples.
|
|
472
|
+
*/
|
|
473
|
+
export function getSidekickRemoteCallableToolNames(): SidekickToolName[] {
|
|
474
|
+
return [...SIDEKICK_REMOTE_CALLABLE_TOOLS];
|
|
475
|
+
}
|
|
476
|
+
|
|
408
477
|
const SIDEKICK_MANIFEST_TEMPLATE = {
|
|
409
478
|
id: SIDEKICK_PACK_ID,
|
|
410
479
|
version: SIDEKICK_PACK_VERSION,
|
|
@@ -421,8 +490,13 @@ const SIDEKICK_MANIFEST_TEMPLATE = {
|
|
|
421
490
|
},
|
|
422
491
|
],
|
|
423
492
|
evidence_types: ['sidekick.audited.tool-call'],
|
|
493
|
+
emitted_event_kinds: [...SIDEKICK_EVENT_KIND_VALUES],
|
|
424
494
|
state_aliases: {},
|
|
425
495
|
lane_templates: [],
|
|
496
|
+
// WU-2735 (INIT-060 WU-7a, ADR-013 §ChannelBridge): the sidekick pack
|
|
497
|
+
// requires the `sidekick-channel` transport surface. The kernel refuses
|
|
498
|
+
// to activate the pack if the surface isn't registered at startup.
|
|
499
|
+
surfaces_required: ['sidekick-channel'],
|
|
426
500
|
};
|
|
427
501
|
|
|
428
502
|
export const SIDEKICK_MANIFEST: SidekickPackManifest = SidekickManifestSchema.parse(
|
|
@@ -353,6 +353,13 @@ tools:
|
|
|
353
353
|
output_schema:
|
|
354
354
|
type: object
|
|
355
355
|
additionalProperties: true
|
|
356
|
+
# WU-2780 (ADR-013 §6 governance): runtime-callable only. `channel.send`
|
|
357
|
+
# MUST route through agent:execute-turn so every phone-directed message
|
|
358
|
+
# becomes an `agent-runtime:tool_called` audit event. The pack manifest
|
|
359
|
+
# registers it here so the kernel can dispatch it from within a turn, but
|
|
360
|
+
# the HTTP tool-api surface (POST /tools/:name) rejects it fail-closed —
|
|
361
|
+
# see SIDEKICK_REMOTE_CALLABLE_TOOLS in manifest.ts and
|
|
362
|
+
# ADR_013_SECTION_6_FORBIDDEN_REMOTE_TOOLS in surfaces/http/tool-api.ts.
|
|
356
363
|
- name: channel:send
|
|
357
364
|
entry: tool-impl/channel-tools.ts
|
|
358
365
|
permission: write
|
|
@@ -558,6 +565,44 @@ tools:
|
|
|
558
565
|
output_schema:
|
|
559
566
|
type: object
|
|
560
567
|
additionalProperties: true
|
|
568
|
+
# WU-2738 (INIT-060, ADR-013 §6 governance): plan-to-commit flow routed
|
|
569
|
+
# through agent:execute-turn. Runtime-callable tool, no top-level
|
|
570
|
+
# surface -- the governed dispatch is the only path to commit a plan.
|
|
571
|
+
# required_approvals is declared (empty) so the cloud conductor treats
|
|
572
|
+
# the tool as approval-aware even when the default policy permits it.
|
|
573
|
+
- name: sidekick:routine:commit_plan
|
|
574
|
+
entry: tool-impl/routine-commit.ts
|
|
575
|
+
permission: write
|
|
576
|
+
required_scopes:
|
|
577
|
+
- type: path
|
|
578
|
+
pattern: .sidekick/**
|
|
579
|
+
access: read
|
|
580
|
+
- type: path
|
|
581
|
+
pattern: .sidekick/**
|
|
582
|
+
access: write
|
|
583
|
+
required_approvals: []
|
|
584
|
+
input_schema:
|
|
585
|
+
type: object
|
|
586
|
+
properties:
|
|
587
|
+
plan_id:
|
|
588
|
+
type: string
|
|
589
|
+
minLength: 1
|
|
590
|
+
attestation:
|
|
591
|
+
type: object
|
|
592
|
+
properties:
|
|
593
|
+
actor:
|
|
594
|
+
type: string
|
|
595
|
+
minLength: 1
|
|
596
|
+
reason:
|
|
597
|
+
type: string
|
|
598
|
+
minLength: 1
|
|
599
|
+
required: [actor, reason]
|
|
600
|
+
additionalProperties: true
|
|
601
|
+
required: [plan_id, attestation]
|
|
602
|
+
additionalProperties: false
|
|
603
|
+
output_schema:
|
|
604
|
+
type: object
|
|
605
|
+
additionalProperties: true
|
|
561
606
|
- name: sidekick:init
|
|
562
607
|
entry: tool-impl/system-tools.ts
|
|
563
608
|
permission: write
|
|
@@ -612,5 +657,48 @@ policies:
|
|
|
612
657
|
reason: Default sidekick policy permits declared tools within scoped access.
|
|
613
658
|
evidence_types:
|
|
614
659
|
- sidekick.audited.tool-call
|
|
660
|
+
# WU-2734 (INIT-060, ADR-013): sidekick emits 16 namespaced event kinds on the
|
|
661
|
+
# pack channel. Command-style task/routine/bootstrap events use queued replay;
|
|
662
|
+
# memory and channel observations are ephemeral and fail silent without
|
|
663
|
+
# control_plane.org_id.
|
|
664
|
+
emitted_event_kinds:
|
|
665
|
+
- sidekick:task_created
|
|
666
|
+
- sidekick:task_completed
|
|
667
|
+
- sidekick:task_scheduled
|
|
668
|
+
- sidekick:task_snoozed
|
|
669
|
+
- sidekick:memory_stored
|
|
670
|
+
- sidekick:memory_recalled
|
|
671
|
+
- sidekick:memory_forgotten
|
|
672
|
+
- sidekick:channel_message_sent
|
|
673
|
+
- sidekick:channel_message_received
|
|
674
|
+
- sidekick:channel_bridge_connected
|
|
675
|
+
- sidekick:channel_bridge_disconnected
|
|
676
|
+
- sidekick:routine_planned
|
|
677
|
+
- sidekick:routine_committed
|
|
678
|
+
- sidekick:routine_executed
|
|
679
|
+
- sidekick:routine_step_failed
|
|
680
|
+
- sidekick:state_rehydrated
|
|
681
|
+
backpressure_policy:
|
|
682
|
+
sidekick:task_created: queue-with-replay
|
|
683
|
+
sidekick:task_completed: queue-with-replay
|
|
684
|
+
sidekick:task_scheduled: queue-with-replay
|
|
685
|
+
sidekick:task_snoozed: queue-with-replay
|
|
686
|
+
sidekick:memory_stored: ephemeral
|
|
687
|
+
sidekick:memory_recalled: ephemeral
|
|
688
|
+
sidekick:memory_forgotten: ephemeral
|
|
689
|
+
sidekick:channel_message_sent: ephemeral
|
|
690
|
+
sidekick:channel_message_received: ephemeral
|
|
691
|
+
sidekick:channel_bridge_connected: ephemeral
|
|
692
|
+
sidekick:channel_bridge_disconnected: ephemeral
|
|
693
|
+
sidekick:routine_planned: queue-with-replay
|
|
694
|
+
sidekick:routine_committed: queue-with-replay
|
|
695
|
+
sidekick:routine_executed: queue-with-replay
|
|
696
|
+
sidekick:routine_step_failed: queue-with-replay
|
|
697
|
+
sidekick:state_rehydrated: queue-with-replay
|
|
615
698
|
state_aliases: {}
|
|
616
699
|
lane_templates: []
|
|
700
|
+
# WU-2735 (INIT-060 WU-7a, ADR-013 §ChannelBridge): the sidekick pack requires
|
|
701
|
+
# the `sidekick-channel` transport surface. The kernel refuses to activate the
|
|
702
|
+
# pack if the surface isn't registered at startup.
|
|
703
|
+
surfaces_required:
|
|
704
|
+
- sidekick-channel
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumenflow/packs-sidekick",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Sidekick personal assistant pack for LumenFlow — 16 tools for task management, typed memory, channels, routines, and audit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lumenflow",
|
|
@@ -24,12 +24,14 @@
|
|
|
24
24
|
"type": "module",
|
|
25
25
|
"exports": {
|
|
26
26
|
".": "./dist/index.js",
|
|
27
|
+
"./channel-ingress": "./dist/channel-ingress.js",
|
|
27
28
|
"./storage": "./dist/tool-impl/storage.js",
|
|
28
29
|
"./tools": "./dist/tools/index.js",
|
|
29
30
|
"./tool-impl": "./dist/tool-impl/index.js",
|
|
30
31
|
"./tool-impl/channel-transports": "./dist/tool-impl/channel-transports.js",
|
|
31
32
|
"./tool-impl/channel-tools": "./dist/tool-impl/channel-tools.js",
|
|
32
33
|
"./tool-impl/memory-tools": "./dist/tool-impl/memory-tools.js",
|
|
34
|
+
"./tool-impl/routine-commit": "./dist/tool-impl/routine-commit.js",
|
|
33
35
|
"./tool-impl/routine-tools": "./dist/tool-impl/routine-tools.js",
|
|
34
36
|
"./tool-impl/shared": "./dist/tool-impl/shared.js",
|
|
35
37
|
"./tool-impl/storage": "./dist/tool-impl/storage.js",
|