@adhdev/mesh-shared 1.0.82-rc.35 → 1.0.82-rc.37
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/assistant-protocol.d.ts +11 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +149 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +130 -8
- package/dist/index.mjs.map +1 -1
- package/dist/launch-defaults.d.ts +2 -0
- package/dist/mesh-tool-names.d.ts +2 -2
- package/dist/mission-git-state.d.ts +83 -0
- package/dist/mission-items.d.ts +2 -2
- package/dist/node-facts.d.ts +18 -0
- package/dist/release.d.ts +90 -0
- package/dist/session-launch.d.ts +7 -0
- package/dist/turn-ipc-mission.d.ts +5 -0
- package/package.json +1 -1
- package/src/assistant-protocol.ts +19 -1
- package/src/index.ts +2 -0
- package/src/launch-defaults.ts +2 -0
- package/src/mesh-tool-names.ts +8 -0
- package/src/mission-git-state.ts +112 -0
- package/src/mission-items.ts +2 -2
- package/src/node-facts.ts +18 -0
- package/src/release.ts +121 -0
- package/src/session-launch.ts +9 -0
- package/src/turn-ipc-mission.ts +9 -4
|
@@ -20,6 +20,8 @@ export interface LaunchDefaultEntry extends LaunchDefaultSelection {
|
|
|
20
20
|
revision: number;
|
|
21
21
|
setBy: 'owner' | 'assistant';
|
|
22
22
|
setAt: number;
|
|
23
|
+
/** Ordered quota-failover alternatives (<= 3, distinct providers). Absent = none. */
|
|
24
|
+
fallback?: LaunchDefaultSelection[];
|
|
23
25
|
}
|
|
24
26
|
export interface LaunchDefaultChange {
|
|
25
27
|
at: number;
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
* Order mirrors mcp-server `ALL_MESH_TOOLS` for easy visual diffing, but the consistency
|
|
19
19
|
* checks are set-based (order-insensitive).
|
|
20
20
|
*/
|
|
21
|
-
export declare const CANONICAL_MESH_TOOL_NAMES: readonly ["mesh_status", "mesh_route_preview", "mesh_list_nodes", "mesh_enqueue_batch", "mesh_enqueue_task", "mesh_view_queue", "mesh_queue_cancel", "mesh_queue_requeue", "mesh_queue_revise", "mesh_send_task", "mesh_read_chat", "mesh_read_debug", "mesh_read_terminal", "mesh_send_keys", "mesh_launch_session", "mesh_git_status", "mesh_read_node_logs", "mesh_fast_forward_node", "mesh_restart_daemon", "mesh_checkpoint", "mesh_approve", "mesh_answer_question", "mesh_list_pending_approvals", "mesh_create", "mesh_add_node", "mesh_reattach_source_parent", "mesh_attach_remote", "mesh_clone_node", "mesh_remove_node", "mesh_cleanup_worktree_nodes", "mesh_refine_node", "mesh_refine_batch", "mesh_config", "mesh_init", "mesh_cleanup_sessions", "mesh_task_history", "mesh_ledger_query", "mesh_note", "mesh_reconcile_ledger", "mesh_mission_upsert", "mesh_mission_list", "mesh_review_inbox", "mesh_node_slots", "driver_list", "driver_describe", "artifact_list", "artifact_read", "artifact_register"];
|
|
21
|
+
export declare const CANONICAL_MESH_TOOL_NAMES: readonly ["mesh_status", "mesh_route_preview", "mesh_list_nodes", "mesh_enqueue_batch", "mesh_enqueue_task", "mesh_view_queue", "mesh_queue_cancel", "mesh_direct_cancel", "mesh_queue_requeue", "mesh_queue_revise", "mesh_send_task", "mesh_read_chat", "mesh_read_debug", "mesh_read_terminal", "mesh_send_keys", "mesh_launch_session", "mesh_git_status", "mesh_read_node_logs", "mesh_fast_forward_node", "mesh_restart_daemon", "mesh_checkpoint", "mesh_approve", "mesh_answer_question", "mesh_list_pending_approvals", "mesh_create", "mesh_add_node", "mesh_reattach_source_parent", "mesh_attach_remote", "mesh_clone_node", "mesh_remove_node", "mesh_retry_node_bootstrap", "mesh_cleanup_worktree_nodes", "mesh_refine_node", "mesh_refine_batch", "mesh_config", "mesh_init", "mesh_cleanup_sessions", "mesh_task_history", "mesh_ledger_query", "mesh_note", "mesh_reconcile_ledger", "mesh_mission_upsert", "mesh_mission_list", "mesh_mission_git_eval", "mesh_release_upsert", "mesh_release_scope", "mesh_release_list", "mesh_release_record_deploy", "mesh_release_changelog_draft", "mesh_review_inbox", "mesh_node_slots", "driver_list", "driver_describe", "artifact_list", "artifact_read", "artifact_register"];
|
|
22
22
|
export type CanonicalMeshToolName = typeof CANONICAL_MESH_TOOL_NAMES[number];
|
|
23
23
|
/** The count the `NN tools` barrel doc comments and consistency test assert against. */
|
|
24
|
-
export declare const CANONICAL_MESH_TOOL_COUNT:
|
|
24
|
+
export declare const CANONICAL_MESH_TOOL_COUNT: 56;
|
|
25
25
|
/**
|
|
26
26
|
* Tool names retired by the 2026-09-26 tool-surface consolidation (60 → 48).
|
|
27
27
|
* Every capability behind them is still reachable: each retired name maps to the
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mission-git-state — types and the pure aggregation for "did this mission's
|
|
3
|
+
* referenced commits/branches land on the default branch?"
|
|
4
|
+
* (docs/design/2026-11-01-mission-git-refs.md §3).
|
|
5
|
+
*
|
|
6
|
+
* The facts come from the daemon opening git objects itself (never from
|
|
7
|
+
* commit-message text, branch-name similarity or worker prose). `landed` means
|
|
8
|
+
* ONLY "the referenced changes are on the base"; it never implies live
|
|
9
|
+
* acceptance, mission completion or that remaining items are done, and it is
|
|
10
|
+
* never used to change a mission's status.
|
|
11
|
+
*
|
|
12
|
+
* Dependency-free leaf: plain data in, plain data out.
|
|
13
|
+
*/
|
|
14
|
+
/** Per-ref verdict. `unknown` is never folded into `not_contained` nor promoted to `contained_*`. */
|
|
15
|
+
export declare const MISSION_REF_GIT_STATUSES: readonly ["contained_ancestor", "contained_patch_equivalent", "not_contained", "unknown"];
|
|
16
|
+
export type MissionRefGitStatus = typeof MISSION_REF_GIT_STATUSES[number];
|
|
17
|
+
/** How a contained verdict was reached. */
|
|
18
|
+
export declare const MISSION_REF_GIT_METHODS: readonly ["ancestry", "cherry", "residual_patch"];
|
|
19
|
+
export type MissionRefGitMethod = typeof MISSION_REF_GIT_METHODS[number];
|
|
20
|
+
/** Mission-level projection. */
|
|
21
|
+
export declare const MISSION_GIT_STATES: readonly ["no_refs", "landed", "partial", "not_landed", "unknown"];
|
|
22
|
+
export type MissionGitStateValue = typeof MISSION_GIT_STATES[number];
|
|
23
|
+
export declare function isMissionRefContained(status: MissionRefGitStatus): boolean;
|
|
24
|
+
/** Why a ref is `unknown` (detail.unknownReason). Free-form strings are tolerated on read. */
|
|
25
|
+
export type MissionRefUnknownReason = 'object_missing' | 'shallow' | 'undeterminable' | 'base_missing' | 'branch_not_found' | 'base_branch_ref' | 'gitlink_undeterminable' | 'merge_tree_failed' | 'node_offline' | 'no_repo' | 'budget' | 'not_a_git_ref';
|
|
26
|
+
export interface MissionRefGitDetail {
|
|
27
|
+
reasonCode?: string;
|
|
28
|
+
unknownReason?: MissionRefUnknownReason | string;
|
|
29
|
+
/** `modified_since_landing_possible`: main later touched the same lines — shown as a hint, not a verdict. */
|
|
30
|
+
note?: string;
|
|
31
|
+
nodeId?: string;
|
|
32
|
+
residualPatchId?: string;
|
|
33
|
+
ahead?: number;
|
|
34
|
+
behind?: number;
|
|
35
|
+
}
|
|
36
|
+
/** One stored per-ref evaluation (a row of `mesh_mission_ref_evals`). */
|
|
37
|
+
export interface MissionRefGitEval {
|
|
38
|
+
itemId: string;
|
|
39
|
+
/** `kind:repo:value` (normalized, lower-case SHA). */
|
|
40
|
+
refKey: string;
|
|
41
|
+
kind: 'commit' | 'branch';
|
|
42
|
+
value: string;
|
|
43
|
+
repo?: string;
|
|
44
|
+
/** Branch refs: the SHA the name resolved to at first evaluation (re-evaluation keeps using it). */
|
|
45
|
+
pinnedSha?: string;
|
|
46
|
+
baseRef: string;
|
|
47
|
+
baseSha?: string;
|
|
48
|
+
status: MissionRefGitStatus;
|
|
49
|
+
method?: MissionRefGitMethod;
|
|
50
|
+
detail?: MissionRefGitDetail;
|
|
51
|
+
evaluatedAt: string;
|
|
52
|
+
}
|
|
53
|
+
export interface MissionGitState {
|
|
54
|
+
missionId: string;
|
|
55
|
+
state: MissionGitStateValue;
|
|
56
|
+
/** `partial` only: some refs were `unknown` (not just `not_contained`). */
|
|
57
|
+
partialUnknown: boolean;
|
|
58
|
+
counts: {
|
|
59
|
+
total: number;
|
|
60
|
+
contained: number;
|
|
61
|
+
notContained: number;
|
|
62
|
+
unknown: number;
|
|
63
|
+
};
|
|
64
|
+
/** Base the newest evaluation compared against. */
|
|
65
|
+
baseRef?: string;
|
|
66
|
+
baseSha?: string;
|
|
67
|
+
/** Oldest `evaluatedAt` among the refs (the freshness floor). */
|
|
68
|
+
evaluatedAt?: string;
|
|
69
|
+
/** True when no row exists yet / the rows are older than the TTL — a refresh was (or can be) triggered. */
|
|
70
|
+
stale: boolean;
|
|
71
|
+
refs: MissionRefGitEval[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Aggregate per-ref statuses (design §3.3):
|
|
75
|
+
* - none → `no_refs`; all contained → `landed`; some contained → `partial`
|
|
76
|
+
* (`partialUnknown` when any of the rest is `unknown`);
|
|
77
|
+
* - none contained: all `not_contained` → `not_landed`, otherwise `unknown`.
|
|
78
|
+
*/
|
|
79
|
+
export declare function aggregateMissionGitState(statuses: readonly MissionRefGitStatus[]): {
|
|
80
|
+
state: MissionGitStateValue;
|
|
81
|
+
partialUnknown: boolean;
|
|
82
|
+
counts: MissionGitState['counts'];
|
|
83
|
+
};
|
package/dist/mission-items.d.ts
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
*/
|
|
15
15
|
export declare const MISSION_ITEM_KINDS: readonly ["remaining", "live_check", "decision", "evidence"];
|
|
16
16
|
export type MissionItemKind = typeof MISSION_ITEM_KINDS[number];
|
|
17
|
-
export declare const MISSION_ITEM_STATES: readonly ["open", "done", "dropped", "moved", "answered", "expired", "withdrawn", "superseded"];
|
|
17
|
+
export declare const MISSION_ITEM_STATES: readonly ["open", "done", "failed", "dropped", "moved", "answered", "expired", "withdrawn", "superseded"];
|
|
18
18
|
export type MissionItemState = typeof MISSION_ITEM_STATES[number];
|
|
19
|
-
/** States a coordinator/worker may SET through items_update, per kind. `answered`/`expired` are daemon-owned. */
|
|
19
|
+
/** States a coordinator/worker may SET through items_update, per kind. `answered`/`expired`/`failed` (owner live-check verdict) are daemon-owned. */
|
|
20
20
|
export declare const COORDINATOR_SETTABLE_ITEM_STATES: Readonly<Record<MissionItemKind, readonly MissionItemState[]>>;
|
|
21
21
|
export declare const MISSION_OUTCOMES: readonly ["merged", "verified_live", "superseded", "not_needed", "owner_abandoned", "unspecified"];
|
|
22
22
|
export type MissionOutcome = typeof MISSION_OUTCOMES[number];
|
package/dist/node-facts.d.ts
CHANGED
|
@@ -234,6 +234,24 @@ export interface MeshNodeFacts {
|
|
|
234
234
|
* Booleans keyed by provider type only — no free text, no credentials.
|
|
235
235
|
*/
|
|
236
236
|
providerEnablement?: Record<string, MeshNodeFactsProviderEnablement>;
|
|
237
|
+
/**
|
|
238
|
+
* The reporting machine's stored quota RESERVE (daemon-core
|
|
239
|
+
* `ADHDevConfig.quotaReserve`, sparse, ≤ 2 KB, migration audit trail
|
|
240
|
+
* stripped): the "how much quota to leave for the person" bar that the
|
|
241
|
+
* coordinator's launch gate applies to THIS machine's snapshots.
|
|
242
|
+
* ★ABSENT means "this node did not tell us" (older daemon) and resolves to
|
|
243
|
+
* the code defaults — the same fail-open direction as before the field
|
|
244
|
+
* existed. Percentages, durations and hashed account keys only; no free
|
|
245
|
+
* text, no emails. Resolve with daemon-core `resolveQuotaReserve`; never
|
|
246
|
+
* read its fields directly.
|
|
247
|
+
*/
|
|
248
|
+
quotaReserve?: {
|
|
249
|
+
version: 1;
|
|
250
|
+
defaults?: Record<string, number>;
|
|
251
|
+
pools?: Record<string, Record<string, number>>;
|
|
252
|
+
accounts?: Record<string, Record<string, Record<string, number>>>;
|
|
253
|
+
updatedAt?: string;
|
|
254
|
+
};
|
|
237
255
|
/** Future fields ride through opaquely — do not enumerate them in relays. */
|
|
238
256
|
[extra: string]: unknown;
|
|
239
257
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* release — types, limits and pure helpers for release objects
|
|
3
|
+
* (docs/design/2026-11-01-release-objects.md).
|
|
4
|
+
*
|
|
5
|
+
* A release is a mesh-scoped entity that groups MISSIONS (explicit membership) and records
|
|
6
|
+
* deploy facts. It is distinct from the vendor release stamp (a build channel stamp) and
|
|
7
|
+
* from `.adhdev/preview-deploy.json` (the per-checkout deploy record it snapshots).
|
|
8
|
+
* Membership is only ever created by an explicit call; git evaluation and deploy heads
|
|
9
|
+
* produce suggestions, never members. Dependency-free leaf.
|
|
10
|
+
*/
|
|
11
|
+
export declare const MESH_RELEASE_CHANNELS: readonly ["preview", "stable"];
|
|
12
|
+
export type MeshReleaseChannel = typeof MESH_RELEASE_CHANNELS[number];
|
|
13
|
+
export declare function isMeshReleaseChannel(value: unknown): value is MeshReleaseChannel;
|
|
14
|
+
export declare const MESH_RELEASE_STATUSES: readonly ["planned", "frozen", "deployed", "verified", "superseded", "cancelled"];
|
|
15
|
+
export type ReleaseStatus = typeof MESH_RELEASE_STATUSES[number];
|
|
16
|
+
export declare function isReleaseStatus(value: unknown): value is ReleaseStatus;
|
|
17
|
+
export declare const RELEASE_MEMBER_STATES: readonly ["member", "moved_out", "removed"];
|
|
18
|
+
export type ReleaseMemberState = typeof RELEASE_MEMBER_STATES[number];
|
|
19
|
+
/** Who may write release membership. The daemon never adds a member on its own. */
|
|
20
|
+
export declare const RELEASE_ACTORS: readonly ["coordinator", "owner", "assistant", "script"];
|
|
21
|
+
export type ReleaseActor = typeof RELEASE_ACTORS[number];
|
|
22
|
+
export declare const RELEASE_EVENT_TYPES: readonly ["created", "status_changed", "scope_added", "scope_moved", "scope_removed", "deploy_recorded", "changelog_drafted", "changelog_applied"];
|
|
23
|
+
export type ReleaseEventType = typeof RELEASE_EVENT_TYPES[number];
|
|
24
|
+
/** Mission-side events recorded when membership changes (so the mission history shows it). */
|
|
25
|
+
export declare const MISSION_RELEASE_EVENT_TYPES: readonly ["release_attached", "release_moved", "release_detached"];
|
|
26
|
+
export declare const RELEASE_LIMITS: {
|
|
27
|
+
readonly name: 80;
|
|
28
|
+
readonly note: 500;
|
|
29
|
+
/** `mesh_missions.release_note`: one user/operator-visible sentence. */
|
|
30
|
+
readonly releaseNote: 400;
|
|
31
|
+
readonly missionsPerCall: 100;
|
|
32
|
+
readonly changelogEntries: 300;
|
|
33
|
+
};
|
|
34
|
+
/** Deploy targets snapshot (a copy of `.adhdev/preview-deploy.json` `targets`). */
|
|
35
|
+
export interface ReleaseDeployTarget {
|
|
36
|
+
commit?: string;
|
|
37
|
+
deployedAt?: string;
|
|
38
|
+
previewVersion?: string;
|
|
39
|
+
[key: string]: unknown;
|
|
40
|
+
}
|
|
41
|
+
export type ReleaseTargets = Partial<Record<'npm' | 'server' | 'web', ReleaseDeployTarget>> & Record<string, ReleaseDeployTarget | undefined>;
|
|
42
|
+
export declare const CHANGELOG_SECTIONS: readonly ["Added", "Fixed", "Changed"];
|
|
43
|
+
export type ChangelogSection = typeof CHANGELOG_SECTIONS[number];
|
|
44
|
+
export interface ChangelogDraftEntry {
|
|
45
|
+
missionId: string;
|
|
46
|
+
/** `<!-- m:<id8> -->` — the idempotency marker `--apply` writes after the line. */
|
|
47
|
+
marker: string;
|
|
48
|
+
section: ChangelogSection;
|
|
49
|
+
/** The sentence that would be written to CHANGELOG.md. */
|
|
50
|
+
text: string;
|
|
51
|
+
source: 'release_note' | 'summary';
|
|
52
|
+
/** True when `text` is not user-facing wording yet (carries the needs-wording marker). */
|
|
53
|
+
needsWording?: boolean;
|
|
54
|
+
/** Evidence kept in the draft JSON only; never written to CHANGELOG.md. */
|
|
55
|
+
evidence?: {
|
|
56
|
+
gitState?: string;
|
|
57
|
+
outcome?: string;
|
|
58
|
+
shas?: string[];
|
|
59
|
+
};
|
|
60
|
+
/** Non-blocking lint warnings (internal ids / wave numbers / forbidden phrases). */
|
|
61
|
+
lint?: string[];
|
|
62
|
+
}
|
|
63
|
+
export interface ChangelogDraftExcluded {
|
|
64
|
+
missionId: string;
|
|
65
|
+
reason: string;
|
|
66
|
+
}
|
|
67
|
+
export interface ChangelogDraft {
|
|
68
|
+
generatedAt: string;
|
|
69
|
+
entries: ChangelogDraftEntry[];
|
|
70
|
+
/** Member missions without a `release_note` (target 0 at deploy time). */
|
|
71
|
+
needsNote: string[];
|
|
72
|
+
excluded: ChangelogDraftExcluded[];
|
|
73
|
+
/** Member missions whose refs are not confirmed on the default branch (`not_landed` / `unknown`). */
|
|
74
|
+
warnings: Array<{
|
|
75
|
+
missionId: string;
|
|
76
|
+
gitState: string;
|
|
77
|
+
message: string;
|
|
78
|
+
}>;
|
|
79
|
+
appliedAt?: string;
|
|
80
|
+
}
|
|
81
|
+
export declare const NEEDS_WORDING_MARKER = "[needs user-facing wording]";
|
|
82
|
+
/** Marker that makes `--apply` idempotent: one per mission entry inside CHANGELOG.md. */
|
|
83
|
+
export declare function changelogMissionMarker(missionId: string): string;
|
|
84
|
+
/** Default section for an entry; `[Fixed]`/`[Added]`/`[Changed]` prefixes on the note pin it. */
|
|
85
|
+
export declare function classifyChangelogSection(text: string, hint?: string): {
|
|
86
|
+
section: ChangelogSection;
|
|
87
|
+
text: string;
|
|
88
|
+
};
|
|
89
|
+
/** Phrases that must not reach a public CHANGELOG (internal waves, rc numbering, ids). Warning-only. */
|
|
90
|
+
export declare function lintChangelogText(text: string): string[];
|
package/dist/session-launch.d.ts
CHANGED
|
@@ -41,6 +41,13 @@ export interface ModelSelection {
|
|
|
41
41
|
/** Last value the provider itself reported (statusline, native history). */
|
|
42
42
|
observed?: string;
|
|
43
43
|
observedAt?: number;
|
|
44
|
+
/**
|
|
45
|
+
* The provider SILENTLY substituted another model for the requested one
|
|
46
|
+
* (antigravity: `model X is not recognized … Using "Y" instead`). `observed`
|
|
47
|
+
* then holds the model actually running. P2P/launch-record only — the
|
|
48
|
+
* server path never carries it (see the content boundary above).
|
|
49
|
+
*/
|
|
50
|
+
fallback?: boolean;
|
|
44
51
|
/** Every value change in order. The last entry is the value in force. */
|
|
45
52
|
history: ModelSelectionHistoryEntry[];
|
|
46
53
|
}
|
|
@@ -39,6 +39,8 @@ export interface MissionUpsertRequest {
|
|
|
39
39
|
*/
|
|
40
40
|
structured?: boolean;
|
|
41
41
|
summary?: string;
|
|
42
|
+
/** One user/operator-visible sentence for the release CHANGELOG draft (design 2026-11-01-release-objects L5). `''` clears. */
|
|
43
|
+
releaseNote?: string;
|
|
42
44
|
outcome?: string;
|
|
43
45
|
outcomeReason?: string;
|
|
44
46
|
/** Mission id open items move to when this call closes the mission (default: the carry-over mission). */
|
|
@@ -57,6 +59,7 @@ export interface MeshMissionOpenItemCountsWire {
|
|
|
57
59
|
/** Structured-missions fields (only with `structured: true` on the request). */
|
|
58
60
|
export interface MeshMissionStructuredWire {
|
|
59
61
|
summary?: string;
|
|
62
|
+
releaseNote?: string;
|
|
60
63
|
outcome?: string;
|
|
61
64
|
outcomeReason?: string;
|
|
62
65
|
version?: number;
|
|
@@ -157,6 +160,7 @@ export interface MissionListSummaryVerboseWire {
|
|
|
157
160
|
closeCandidateEmittedAt?: string | null;
|
|
158
161
|
/** Structured lists only. */
|
|
159
162
|
summary?: string;
|
|
163
|
+
releaseNote?: string;
|
|
160
164
|
outcome?: string;
|
|
161
165
|
outcomeReason?: string;
|
|
162
166
|
version?: number;
|
|
@@ -183,6 +187,7 @@ export interface MissionListSummarySlimWire {
|
|
|
183
187
|
closeCandidateEmittedAt?: string | null;
|
|
184
188
|
/** Structured lists only. */
|
|
185
189
|
summary?: string;
|
|
190
|
+
releaseNote?: string;
|
|
186
191
|
outcome?: string;
|
|
187
192
|
outcomeReason?: string;
|
|
188
193
|
version?: number;
|
package/package.json
CHANGED
|
@@ -27,6 +27,7 @@ export const ASSISTANT_TOOLS = [
|
|
|
27
27
|
'project_attach_remote',
|
|
28
28
|
'discover_repos',
|
|
29
29
|
'memory',
|
|
30
|
+
'memory_search',
|
|
30
31
|
'skill_view',
|
|
31
32
|
'skill_manage',
|
|
32
33
|
'project_note',
|
|
@@ -38,6 +39,7 @@ export const ASSISTANT_TOOLS = [
|
|
|
38
39
|
'artifact_read',
|
|
39
40
|
'decision_answer',
|
|
40
41
|
'decision_request',
|
|
42
|
+
'session_control',
|
|
41
43
|
] as const
|
|
42
44
|
|
|
43
45
|
export type AssistantTool = typeof ASSISTANT_TOOLS[number]
|
|
@@ -66,6 +68,8 @@ export const ASSISTANT_VERB = {
|
|
|
66
68
|
projectAttachRemote: 'assistant_project_attach_remote',
|
|
67
69
|
discoverRepos: 'assistant_discover_repos',
|
|
68
70
|
memory: 'assistant_memory',
|
|
71
|
+
/** Pull-only FTS search over the archive tier (memory design 2026-11-01 §3.4). */
|
|
72
|
+
memorySearch: 'assistant_memory_search',
|
|
69
73
|
skillView: 'assistant_skill_view',
|
|
70
74
|
skillManage: 'assistant_skill_manage',
|
|
71
75
|
projectNote: 'assistant_project_note',
|
|
@@ -77,6 +81,8 @@ export const ASSISTANT_VERB = {
|
|
|
77
81
|
decisionAnswer: 'assistant_decision_answer',
|
|
78
82
|
/** Register a plain-text question a coordinator put to the owner as a decision item (§5.2). */
|
|
79
83
|
decisionRequest: 'assistant_decision_request',
|
|
84
|
+
/** Stop / restart / switch the provider of a coordinator, worker or the assistant session (handoff design 2026-11-01 §4). */
|
|
85
|
+
sessionControl: 'assistant_session_control',
|
|
80
86
|
// assistant-side daemon verbs without a tool of the same name
|
|
81
87
|
launch: 'launch_assistant',
|
|
82
88
|
pendingRelays: 'assistant_pending_relays',
|
|
@@ -84,6 +90,12 @@ export const ASSISTANT_VERB = {
|
|
|
84
90
|
stagedResolve: 'assistant_staged_resolve',
|
|
85
91
|
storeAdmin: 'assistant_store_admin',
|
|
86
92
|
importSkills: 'assistant_import_skills',
|
|
93
|
+
/** Owner skill list (attach/view counts, save proposals, recent skill metrics); reads move no counter. */
|
|
94
|
+
skillsList: 'assistant_skills_list',
|
|
95
|
+
/** Owner: what the assistant remembered recently, with undo handles (memory design §3.2). */
|
|
96
|
+
memoryDigest: 'assistant_memory_digest',
|
|
97
|
+
/** Owner: reverse one remembered write or one batch (memory design §3.2). Never an assistant tool. */
|
|
98
|
+
memoryUndo: 'assistant_memory_undo',
|
|
87
99
|
/** Projects the assistant is following (open relay threads) — list / stop following. */
|
|
88
100
|
threads: 'assistant_threads',
|
|
89
101
|
threadClose: 'assistant_thread_close',
|
|
@@ -106,6 +118,7 @@ export const ASSISTANT_TOOL_VERBS: Readonly<Record<AssistantTool, AssistantVerb>
|
|
|
106
118
|
project_attach_remote: ASSISTANT_VERB.projectAttachRemote,
|
|
107
119
|
discover_repos: ASSISTANT_VERB.discoverRepos,
|
|
108
120
|
memory: ASSISTANT_VERB.memory,
|
|
121
|
+
memory_search: ASSISTANT_VERB.memorySearch,
|
|
109
122
|
skill_view: ASSISTANT_VERB.skillView,
|
|
110
123
|
skill_manage: ASSISTANT_VERB.skillManage,
|
|
111
124
|
project_note: ASSISTANT_VERB.projectNote,
|
|
@@ -115,6 +128,7 @@ export const ASSISTANT_TOOL_VERBS: Readonly<Record<AssistantTool, AssistantVerb>
|
|
|
115
128
|
artifact_read: ASSISTANT_VERB.artifactRead,
|
|
116
129
|
decision_answer: ASSISTANT_VERB.decisionAnswer,
|
|
117
130
|
decision_request: ASSISTANT_VERB.decisionRequest,
|
|
131
|
+
session_control: ASSISTANT_VERB.sessionControl,
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
/**
|
|
@@ -123,7 +137,7 @@ export const ASSISTANT_TOOL_VERBS: Readonly<Record<AssistantTool, AssistantVerb>
|
|
|
123
137
|
* because they cause effects (a coordinator message or launch, a new
|
|
124
138
|
* project), and MCP clients use readOnlyHint to skip confirmation.
|
|
125
139
|
*/
|
|
126
|
-
export const ASSISTANT_WRITE_TOOLS: readonly AssistantTool[] = ['project_watch', 'assistant_action', 'memory', 'skill_manage', 'project_note', 'project_send', 'project_add', 'project_attach_remote', 'launch_defaults_set', 'decision_answer', 'decision_request']
|
|
140
|
+
export const ASSISTANT_WRITE_TOOLS: readonly AssistantTool[] = ['project_watch', 'assistant_action', 'memory', 'skill_manage', 'project_note', 'project_send', 'project_add', 'project_attach_remote', 'launch_defaults_set', 'decision_answer', 'decision_request', 'session_control']
|
|
127
141
|
|
|
128
142
|
/** Owner-only verbs: never reachable from the assistant's MCP server (no `ipc`). */
|
|
129
143
|
export const ASSISTANT_OWNER_VERBS: readonly AssistantVerb[] = [
|
|
@@ -131,12 +145,16 @@ export const ASSISTANT_OWNER_VERBS: readonly AssistantVerb[] = [
|
|
|
131
145
|
ASSISTANT_VERB.stagedResolve,
|
|
132
146
|
ASSISTANT_VERB.storeAdmin,
|
|
133
147
|
ASSISTANT_VERB.importSkills,
|
|
148
|
+
ASSISTANT_VERB.skillsList,
|
|
149
|
+
ASSISTANT_VERB.memoryDigest,
|
|
150
|
+
ASSISTANT_VERB.memoryUndo,
|
|
134
151
|
ASSISTANT_VERB.threadClose,
|
|
135
152
|
]
|
|
136
153
|
|
|
137
154
|
/** The only assistant verbs accepted while an idle review turn is open (§4.10.7). */
|
|
138
155
|
export const ASSISTANT_REVIEW_TURN_VERBS: readonly AssistantVerb[] = [
|
|
139
156
|
ASSISTANT_VERB.memory,
|
|
157
|
+
ASSISTANT_VERB.memorySearch,
|
|
140
158
|
ASSISTANT_VERB.skillView,
|
|
141
159
|
ASSISTANT_VERB.skillManage,
|
|
142
160
|
ASSISTANT_VERB.projectNote,
|
package/src/index.ts
CHANGED
|
@@ -42,6 +42,8 @@ export * from './turn-ipc'
|
|
|
42
42
|
export * from './path-ownership'
|
|
43
43
|
export * from './mission-brief'
|
|
44
44
|
export * from './mission-items'
|
|
45
|
+
export * from './mission-git-state'
|
|
46
|
+
export * from './release'
|
|
45
47
|
export * from './decision-push-relay'
|
|
46
48
|
export * from './keyed-doc-delta'
|
|
47
49
|
export * from './provider-approval'
|
package/src/launch-defaults.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface LaunchDefaultEntry extends LaunchDefaultSelection {
|
|
|
24
24
|
revision: number;
|
|
25
25
|
setBy: 'owner' | 'assistant';
|
|
26
26
|
setAt: number;
|
|
27
|
+
/** Ordered quota-failover alternatives (<= 3, distinct providers). Absent = none. */
|
|
28
|
+
fallback?: LaunchDefaultSelection[];
|
|
27
29
|
}
|
|
28
30
|
export interface LaunchDefaultChange {
|
|
29
31
|
at: number;
|
package/src/mesh-tool-names.ts
CHANGED
|
@@ -27,6 +27,7 @@ export const CANONICAL_MESH_TOOL_NAMES = [
|
|
|
27
27
|
'mesh_enqueue_task',
|
|
28
28
|
'mesh_view_queue',
|
|
29
29
|
'mesh_queue_cancel',
|
|
30
|
+
'mesh_direct_cancel',
|
|
30
31
|
'mesh_queue_requeue',
|
|
31
32
|
'mesh_queue_revise',
|
|
32
33
|
'mesh_send_task',
|
|
@@ -49,6 +50,7 @@ export const CANONICAL_MESH_TOOL_NAMES = [
|
|
|
49
50
|
'mesh_attach_remote',
|
|
50
51
|
'mesh_clone_node',
|
|
51
52
|
'mesh_remove_node',
|
|
53
|
+
'mesh_retry_node_bootstrap',
|
|
52
54
|
'mesh_cleanup_worktree_nodes',
|
|
53
55
|
'mesh_refine_node',
|
|
54
56
|
'mesh_refine_batch',
|
|
@@ -65,6 +67,12 @@ export const CANONICAL_MESH_TOOL_NAMES = [
|
|
|
65
67
|
'mesh_reconcile_ledger',
|
|
66
68
|
'mesh_mission_upsert',
|
|
67
69
|
'mesh_mission_list',
|
|
70
|
+
'mesh_mission_git_eval',
|
|
71
|
+
'mesh_release_upsert',
|
|
72
|
+
'mesh_release_scope',
|
|
73
|
+
'mesh_release_list',
|
|
74
|
+
'mesh_release_record_deploy',
|
|
75
|
+
'mesh_release_changelog_draft',
|
|
68
76
|
'mesh_review_inbox',
|
|
69
77
|
'mesh_node_slots',
|
|
70
78
|
'driver_list',
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mission-git-state — types and the pure aggregation for "did this mission's
|
|
3
|
+
* referenced commits/branches land on the default branch?"
|
|
4
|
+
* (docs/design/2026-11-01-mission-git-refs.md §3).
|
|
5
|
+
*
|
|
6
|
+
* The facts come from the daemon opening git objects itself (never from
|
|
7
|
+
* commit-message text, branch-name similarity or worker prose). `landed` means
|
|
8
|
+
* ONLY "the referenced changes are on the base"; it never implies live
|
|
9
|
+
* acceptance, mission completion or that remaining items are done, and it is
|
|
10
|
+
* never used to change a mission's status.
|
|
11
|
+
*
|
|
12
|
+
* Dependency-free leaf: plain data in, plain data out.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Per-ref verdict. `unknown` is never folded into `not_contained` nor promoted to `contained_*`. */
|
|
16
|
+
export const MISSION_REF_GIT_STATUSES = ['contained_ancestor', 'contained_patch_equivalent', 'not_contained', 'unknown'] as const
|
|
17
|
+
export type MissionRefGitStatus = typeof MISSION_REF_GIT_STATUSES[number]
|
|
18
|
+
|
|
19
|
+
/** How a contained verdict was reached. */
|
|
20
|
+
export const MISSION_REF_GIT_METHODS = ['ancestry', 'cherry', 'residual_patch'] as const
|
|
21
|
+
export type MissionRefGitMethod = typeof MISSION_REF_GIT_METHODS[number]
|
|
22
|
+
|
|
23
|
+
/** Mission-level projection. */
|
|
24
|
+
export const MISSION_GIT_STATES = ['no_refs', 'landed', 'partial', 'not_landed', 'unknown'] as const
|
|
25
|
+
export type MissionGitStateValue = typeof MISSION_GIT_STATES[number]
|
|
26
|
+
|
|
27
|
+
export function isMissionRefContained(status: MissionRefGitStatus): boolean {
|
|
28
|
+
return status === 'contained_ancestor' || status === 'contained_patch_equivalent'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Why a ref is `unknown` (detail.unknownReason). Free-form strings are tolerated on read. */
|
|
32
|
+
export type MissionRefUnknownReason =
|
|
33
|
+
| 'object_missing'
|
|
34
|
+
| 'shallow'
|
|
35
|
+
| 'undeterminable'
|
|
36
|
+
| 'base_missing'
|
|
37
|
+
| 'branch_not_found'
|
|
38
|
+
| 'base_branch_ref'
|
|
39
|
+
| 'gitlink_undeterminable'
|
|
40
|
+
| 'merge_tree_failed'
|
|
41
|
+
| 'node_offline'
|
|
42
|
+
| 'no_repo'
|
|
43
|
+
| 'budget'
|
|
44
|
+
| 'not_a_git_ref'
|
|
45
|
+
|
|
46
|
+
export interface MissionRefGitDetail {
|
|
47
|
+
reasonCode?: string
|
|
48
|
+
unknownReason?: MissionRefUnknownReason | string
|
|
49
|
+
/** `modified_since_landing_possible`: main later touched the same lines — shown as a hint, not a verdict. */
|
|
50
|
+
note?: string
|
|
51
|
+
nodeId?: string
|
|
52
|
+
residualPatchId?: string
|
|
53
|
+
ahead?: number
|
|
54
|
+
behind?: number
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** One stored per-ref evaluation (a row of `mesh_mission_ref_evals`). */
|
|
58
|
+
export interface MissionRefGitEval {
|
|
59
|
+
itemId: string
|
|
60
|
+
/** `kind:repo:value` (normalized, lower-case SHA). */
|
|
61
|
+
refKey: string
|
|
62
|
+
kind: 'commit' | 'branch'
|
|
63
|
+
value: string
|
|
64
|
+
repo?: string
|
|
65
|
+
/** Branch refs: the SHA the name resolved to at first evaluation (re-evaluation keeps using it). */
|
|
66
|
+
pinnedSha?: string
|
|
67
|
+
baseRef: string
|
|
68
|
+
baseSha?: string
|
|
69
|
+
status: MissionRefGitStatus
|
|
70
|
+
method?: MissionRefGitMethod
|
|
71
|
+
detail?: MissionRefGitDetail
|
|
72
|
+
evaluatedAt: string
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface MissionGitState {
|
|
76
|
+
missionId: string
|
|
77
|
+
state: MissionGitStateValue
|
|
78
|
+
/** `partial` only: some refs were `unknown` (not just `not_contained`). */
|
|
79
|
+
partialUnknown: boolean
|
|
80
|
+
counts: { total: number; contained: number; notContained: number; unknown: number }
|
|
81
|
+
/** Base the newest evaluation compared against. */
|
|
82
|
+
baseRef?: string
|
|
83
|
+
baseSha?: string
|
|
84
|
+
/** Oldest `evaluatedAt` among the refs (the freshness floor). */
|
|
85
|
+
evaluatedAt?: string
|
|
86
|
+
/** True when no row exists yet / the rows are older than the TTL — a refresh was (or can be) triggered. */
|
|
87
|
+
stale: boolean
|
|
88
|
+
refs: MissionRefGitEval[]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Aggregate per-ref statuses (design §3.3):
|
|
93
|
+
* - none → `no_refs`; all contained → `landed`; some contained → `partial`
|
|
94
|
+
* (`partialUnknown` when any of the rest is `unknown`);
|
|
95
|
+
* - none contained: all `not_contained` → `not_landed`, otherwise `unknown`.
|
|
96
|
+
*/
|
|
97
|
+
export function aggregateMissionGitState(statuses: readonly MissionRefGitStatus[]): {
|
|
98
|
+
state: MissionGitStateValue
|
|
99
|
+
partialUnknown: boolean
|
|
100
|
+
counts: MissionGitState['counts']
|
|
101
|
+
} {
|
|
102
|
+
const total = statuses.length
|
|
103
|
+
const contained = statuses.filter(isMissionRefContained).length
|
|
104
|
+
const notContained = statuses.filter(s => s === 'not_contained').length
|
|
105
|
+
const unknown = statuses.filter(s => s === 'unknown').length
|
|
106
|
+
const counts = { total, contained, notContained, unknown }
|
|
107
|
+
if (total === 0) return { state: 'no_refs', partialUnknown: false, counts }
|
|
108
|
+
if (contained === total) return { state: 'landed', partialUnknown: false, counts }
|
|
109
|
+
if (contained > 0) return { state: 'partial', partialUnknown: unknown > 0, counts }
|
|
110
|
+
if (notContained === total) return { state: 'not_landed', partialUnknown: false, counts }
|
|
111
|
+
return { state: 'unknown', partialUnknown: false, counts }
|
|
112
|
+
}
|
package/src/mission-items.ts
CHANGED
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
export const MISSION_ITEM_KINDS = ['remaining', 'live_check', 'decision', 'evidence'] as const
|
|
17
17
|
export type MissionItemKind = typeof MISSION_ITEM_KINDS[number]
|
|
18
18
|
|
|
19
|
-
export const MISSION_ITEM_STATES = ['open', 'done', 'dropped', 'moved', 'answered', 'expired', 'withdrawn', 'superseded'] as const
|
|
19
|
+
export const MISSION_ITEM_STATES = ['open', 'done', 'failed', 'dropped', 'moved', 'answered', 'expired', 'withdrawn', 'superseded'] as const
|
|
20
20
|
export type MissionItemState = typeof MISSION_ITEM_STATES[number]
|
|
21
21
|
|
|
22
|
-
/** States a coordinator/worker may SET through items_update, per kind. `answered`/`expired` are daemon-owned. */
|
|
22
|
+
/** States a coordinator/worker may SET through items_update, per kind. `answered`/`expired`/`failed` (owner live-check verdict) are daemon-owned. */
|
|
23
23
|
export const COORDINATOR_SETTABLE_ITEM_STATES: Readonly<Record<MissionItemKind, readonly MissionItemState[]>> = {
|
|
24
24
|
remaining: ['open', 'done', 'dropped'],
|
|
25
25
|
live_check: ['open', 'done', 'dropped'],
|
package/src/node-facts.ts
CHANGED
|
@@ -234,6 +234,24 @@ export interface MeshNodeFacts {
|
|
|
234
234
|
* Booleans keyed by provider type only — no free text, no credentials.
|
|
235
235
|
*/
|
|
236
236
|
providerEnablement?: Record<string, MeshNodeFactsProviderEnablement>
|
|
237
|
+
/**
|
|
238
|
+
* The reporting machine's stored quota RESERVE (daemon-core
|
|
239
|
+
* `ADHDevConfig.quotaReserve`, sparse, ≤ 2 KB, migration audit trail
|
|
240
|
+
* stripped): the "how much quota to leave for the person" bar that the
|
|
241
|
+
* coordinator's launch gate applies to THIS machine's snapshots.
|
|
242
|
+
* ★ABSENT means "this node did not tell us" (older daemon) and resolves to
|
|
243
|
+
* the code defaults — the same fail-open direction as before the field
|
|
244
|
+
* existed. Percentages, durations and hashed account keys only; no free
|
|
245
|
+
* text, no emails. Resolve with daemon-core `resolveQuotaReserve`; never
|
|
246
|
+
* read its fields directly.
|
|
247
|
+
*/
|
|
248
|
+
quotaReserve?: {
|
|
249
|
+
version: 1
|
|
250
|
+
defaults?: Record<string, number>
|
|
251
|
+
pools?: Record<string, Record<string, number>>
|
|
252
|
+
accounts?: Record<string, Record<string, Record<string, number>>>
|
|
253
|
+
updatedAt?: string
|
|
254
|
+
}
|
|
237
255
|
/** Future fields ride through opaquely — do not enumerate them in relays. */
|
|
238
256
|
[extra: string]: unknown
|
|
239
257
|
}
|