@adhdev/mesh-shared 1.0.82-rc.34 → 1.0.82-rc.36
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 +7 -2
- package/dist/decision-push-relay.d.ts +20 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +425 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +388 -11
- package/dist/index.mjs.map +1 -1
- package/dist/mission-items.d.ts +202 -0
- package/dist/protocol/daemon-server.d.ts +27 -2
- package/dist/protocol/dashboard-server.d.ts +2 -2
- package/dist/session-launch.d.ts +7 -0
- package/dist/turn-ipc-mission.d.ts +59 -1
- package/dist/worker-protocol.d.ts +1 -1
- package/package.json +1 -1
- package/src/assistant-protocol.ts +29 -2
- package/src/decision-push-relay.ts +23 -0
- package/src/index.ts +2 -0
- package/src/mission-items.ts +421 -0
- package/src/protocol/daemon-server.ts +26 -0
- package/src/session-launch.ts +9 -0
- package/src/turn-ipc-mission.ts +108 -9
- package/src/worker-protocol.ts +4 -0
package/dist/index.mjs
CHANGED
|
@@ -1109,9 +1109,15 @@ var DAEMON_STATUS_EVENT_NAMES = [
|
|
|
1109
1109
|
"agent:waiting_choice",
|
|
1110
1110
|
"agent:generating_completed",
|
|
1111
1111
|
"agent:stopped",
|
|
1112
|
-
"monitor:no_progress"
|
|
1112
|
+
"monitor:no_progress",
|
|
1113
|
+
// An owner decision (structured missions) needs the owner. Server-bound for the push only;
|
|
1114
|
+
// the dashboard learns about decisions over P2P (`mission_decisions_list`).
|
|
1115
|
+
"agent:decision_needed"
|
|
1113
1116
|
];
|
|
1114
1117
|
var isDaemonStatusEventName = makeTypeGuard(DAEMON_STATUS_EVENT_NAMES);
|
|
1118
|
+
var DECISION_PUSH_QUESTION_MAX = 80;
|
|
1119
|
+
var DECISION_PUSH_OPTION_LABEL_MAX = 24;
|
|
1120
|
+
var DECISION_PUSH_OPTIONS_MAX = 3;
|
|
1115
1121
|
var RELEASE_CHANNELS = ["stable", "preview"];
|
|
1116
1122
|
var NPM_UPDATE_TAGS = ["latest", "next"];
|
|
1117
1123
|
var VERSION_UPDATE_REASONS = ["force_update_below", "major_minor_mismatch", "patch_mismatch", "daemon_ahead"];
|
|
@@ -1685,6 +1691,10 @@ var WORKER_TOOLS = [
|
|
|
1685
1691
|
"driver_list",
|
|
1686
1692
|
"driver_describe",
|
|
1687
1693
|
"driver_invoke",
|
|
1694
|
+
"driver_scaffold",
|
|
1695
|
+
"driver_validate",
|
|
1696
|
+
"driver_export",
|
|
1697
|
+
"driver_install",
|
|
1688
1698
|
"artifact_register",
|
|
1689
1699
|
"artifact_list",
|
|
1690
1700
|
"artifact_read",
|
|
@@ -1795,7 +1805,9 @@ var ASSISTANT_TOOLS = [
|
|
|
1795
1805
|
"driver_list",
|
|
1796
1806
|
"driver_describe",
|
|
1797
1807
|
"artifact_list",
|
|
1798
|
-
"artifact_read"
|
|
1808
|
+
"artifact_read",
|
|
1809
|
+
"decision_answer",
|
|
1810
|
+
"decision_request"
|
|
1799
1811
|
];
|
|
1800
1812
|
var ASSISTANT_TOOL_SET = new Set(ASSISTANT_TOOLS);
|
|
1801
1813
|
function isAssistantTool(value) {
|
|
@@ -1825,6 +1837,10 @@ var ASSISTANT_VERB = {
|
|
|
1825
1837
|
launchDefaultsSet: "assistant_launch_defaults_set",
|
|
1826
1838
|
artifactList: "assistant_artifact_list",
|
|
1827
1839
|
artifactRead: "assistant_artifact_read",
|
|
1840
|
+
/** Owner-decision inbox (structured-missions design 2026-10-28 §6.3): the owner's words recorded as answers. */
|
|
1841
|
+
decisionAnswer: "assistant_decision_answer",
|
|
1842
|
+
/** Register a plain-text question a coordinator put to the owner as a decision item (§5.2). */
|
|
1843
|
+
decisionRequest: "assistant_decision_request",
|
|
1828
1844
|
// assistant-side daemon verbs without a tool of the same name
|
|
1829
1845
|
launch: "launch_assistant",
|
|
1830
1846
|
pendingRelays: "assistant_pending_relays",
|
|
@@ -1856,9 +1872,11 @@ var ASSISTANT_TOOL_VERBS = {
|
|
|
1856
1872
|
launch_defaults: ASSISTANT_VERB.launchDefaults,
|
|
1857
1873
|
launch_defaults_set: ASSISTANT_VERB.launchDefaultsSet,
|
|
1858
1874
|
artifact_list: ASSISTANT_VERB.artifactList,
|
|
1859
|
-
artifact_read: ASSISTANT_VERB.artifactRead
|
|
1875
|
+
artifact_read: ASSISTANT_VERB.artifactRead,
|
|
1876
|
+
decision_answer: ASSISTANT_VERB.decisionAnswer,
|
|
1877
|
+
decision_request: ASSISTANT_VERB.decisionRequest
|
|
1860
1878
|
};
|
|
1861
|
-
var ASSISTANT_WRITE_TOOLS = ["project_watch", "assistant_action", "memory", "skill_manage", "project_note", "project_send", "project_add", "project_attach_remote", "launch_defaults_set"];
|
|
1879
|
+
var ASSISTANT_WRITE_TOOLS = ["project_watch", "assistant_action", "memory", "skill_manage", "project_note", "project_send", "project_add", "project_attach_remote", "launch_defaults_set", "decision_answer", "decision_request"];
|
|
1862
1880
|
var ASSISTANT_OWNER_VERBS = [
|
|
1863
1881
|
ASSISTANT_VERB.executionSettings,
|
|
1864
1882
|
ASSISTANT_VERB.stagedResolve,
|
|
@@ -1879,11 +1897,22 @@ var ASSISTANT_REMOTE_PROJECT_COMMAND = "assistant_remote_project";
|
|
|
1879
1897
|
var ASSISTANT_REMOTE_PROJECT_CATALOG_COMMAND = "assistant_remote_project_catalog";
|
|
1880
1898
|
var ASSISTANT_REMOTE_PROJECT_ACCESS_COMMAND = "assistant_remote_project_access";
|
|
1881
1899
|
var ASSISTANT_REMOTE_FOLLOW_COMMAND = "assistant_remote_follow";
|
|
1882
|
-
var ASSISTANT_FOLLOWER_ALLOWED_OPS = ["status", "read", "poll", "report", "send", "artifact_list", "artifact_read"];
|
|
1900
|
+
var ASSISTANT_FOLLOWER_ALLOWED_OPS = ["status", "read", "poll", "report", "send", "artifact_list", "artifact_read", "decision_list", "decision_answer", "decision_request"];
|
|
1883
1901
|
var ASSISTANT_FOLLOWER_ALLOWED_OP_SET = new Set(ASSISTANT_FOLLOWER_ALLOWED_OPS);
|
|
1884
1902
|
function isAssistantFollowerAllowedOp(value) {
|
|
1885
1903
|
return typeof value === "string" && ASSISTANT_FOLLOWER_ALLOWED_OP_SET.has(value);
|
|
1886
1904
|
}
|
|
1905
|
+
var DECISION_OP_IMPLIED_BY = {
|
|
1906
|
+
decision_list: "status",
|
|
1907
|
+
decision_answer: "send",
|
|
1908
|
+
decision_request: "send"
|
|
1909
|
+
};
|
|
1910
|
+
function followerOpPermitted(op, allowedOps) {
|
|
1911
|
+
if (!isAssistantFollowerAllowedOp(op)) return false;
|
|
1912
|
+
if (allowedOps.includes(op)) return true;
|
|
1913
|
+
const implied = DECISION_OP_IMPLIED_BY[op];
|
|
1914
|
+
return implied !== void 0 && allowedOps.includes(implied);
|
|
1915
|
+
}
|
|
1887
1916
|
function followedRemoteProjectKey(hostDaemonId, meshId) {
|
|
1888
1917
|
const canonHost = canonicalDaemonId(hostDaemonId) ?? hostDaemonId.trim();
|
|
1889
1918
|
return `${canonHost}::${meshId.trim()}`;
|
|
@@ -2462,6 +2491,7 @@ function parseModelSelection(raw) {
|
|
|
2462
2491
|
const current = readString(record2.current);
|
|
2463
2492
|
const observed = readString(record2.observed);
|
|
2464
2493
|
const observedAt = readFiniteNumber(record2.observedAt);
|
|
2494
|
+
const fallback = record2.fallback === true;
|
|
2465
2495
|
return {
|
|
2466
2496
|
source: isModelAxisSource(record2.source) ? record2.source : "unspecified",
|
|
2467
2497
|
...requested ? { requested } : {},
|
|
@@ -2470,6 +2500,7 @@ function parseModelSelection(raw) {
|
|
|
2470
2500
|
...current ? { current } : {},
|
|
2471
2501
|
...observed ? { observed } : {},
|
|
2472
2502
|
...observedAt !== void 0 ? { observedAt } : {},
|
|
2503
|
+
...fallback ? { fallback } : {},
|
|
2473
2504
|
history: history.slice(-MODEL_SELECTION_HISTORY_LIMIT)
|
|
2474
2505
|
};
|
|
2475
2506
|
}
|
|
@@ -2782,8 +2813,23 @@ function isMissionBriefWire(value) {
|
|
|
2782
2813
|
}
|
|
2783
2814
|
return true;
|
|
2784
2815
|
}
|
|
2816
|
+
var STRUCTURED_MISSION_KEYS = ["summary", "outcome", "outcomeReason", "version", "carryOver", "openItems"];
|
|
2817
|
+
function isOpenItemCountsWire(value) {
|
|
2818
|
+
if (!isRecord(value) || !hasOnlyKeys2(value, ["remaining", "live_check", "decision", "evidence"])) return false;
|
|
2819
|
+
return ["remaining", "live_check", "decision", "evidence"].every((k) => isNonNegativeInt(value[k]));
|
|
2820
|
+
}
|
|
2821
|
+
function isStructuredMissionFields(value) {
|
|
2822
|
+
for (const k of ["summary", "outcome", "outcomeReason"]) {
|
|
2823
|
+
if (value[k] !== void 0 && typeof value[k] !== "string") return false;
|
|
2824
|
+
}
|
|
2825
|
+
if (value.version !== void 0 && !isNonNegativeInt(value.version)) return false;
|
|
2826
|
+
if (value.carryOver !== void 0 && typeof value.carryOver !== "boolean") return false;
|
|
2827
|
+
if (value.openItems !== void 0 && !isOpenItemCountsWire(value.openItems)) return false;
|
|
2828
|
+
return true;
|
|
2829
|
+
}
|
|
2785
2830
|
function isMeshMissionRecordWire(value) {
|
|
2786
|
-
if (!isRecord(value) || !hasOnlyKeys2(value, ["id", "meshId", "title", "goal", "status", "brief"])) return false;
|
|
2831
|
+
if (!isRecord(value) || !hasOnlyKeys2(value, ["id", "meshId", "title", "goal", "status", "brief", ...STRUCTURED_MISSION_KEYS])) return false;
|
|
2832
|
+
if (!isStructuredMissionFields(value)) return false;
|
|
2787
2833
|
if (!isEvidenceIdentifier(value.id) || !isEvidenceIdentifier(value.meshId)) return false;
|
|
2788
2834
|
if (typeof value.title !== "string" || typeof value.goal !== "string") return false;
|
|
2789
2835
|
if (!isMeshMissionStatusValue(value.status)) return false;
|
|
@@ -2791,11 +2837,22 @@ function isMeshMissionRecordWire(value) {
|
|
|
2791
2837
|
return true;
|
|
2792
2838
|
}
|
|
2793
2839
|
function isMissionUpsertRequest(value) {
|
|
2794
|
-
if (!isRecord(value) || !hasOnlyKeys2(value, ["v", "meshId", "id", "title", "goal", "status", "brief"])) return false;
|
|
2840
|
+
if (!isRecord(value) || !hasOnlyKeys2(value, ["v", "meshId", "id", "title", "goal", "status", "brief", "structured", "summary", "outcome", "outcomeReason", "carryOverTo", "toCarryOver", "itemsAdd", "itemsUpdate"])) return false;
|
|
2795
2841
|
if (value.v !== TURN_IPC_PROTOCOL_VERSION) return false;
|
|
2796
2842
|
if (!isEvidenceIdentifier(value.meshId)) return false;
|
|
2797
2843
|
if (value.id !== void 0 && !isEvidenceIdentifier(value.id)) return false;
|
|
2798
|
-
if (typeof value.title !== "string"
|
|
2844
|
+
if (typeof value.title !== "string") return false;
|
|
2845
|
+
if (value.title.trim().length === 0 && value.toCarryOver !== true && value.id === void 0) return false;
|
|
2846
|
+
if (value.structured !== void 0 && typeof value.structured !== "boolean") return false;
|
|
2847
|
+
if (value.toCarryOver !== void 0 && typeof value.toCarryOver !== "boolean") return false;
|
|
2848
|
+
for (const k of ["summary", "outcome", "outcomeReason"]) {
|
|
2849
|
+
if (value[k] !== void 0 && typeof value[k] !== "string") return false;
|
|
2850
|
+
}
|
|
2851
|
+
if (value.carryOverTo !== void 0 && !isEvidenceIdentifier(value.carryOverTo)) return false;
|
|
2852
|
+
for (const k of ["itemsAdd", "itemsUpdate"]) {
|
|
2853
|
+
const list = value[k];
|
|
2854
|
+
if (list !== void 0 && (!Array.isArray(list) || list.length > 500 || !list.every(isRecord))) return false;
|
|
2855
|
+
}
|
|
2799
2856
|
if (value.goal !== void 0 && typeof value.goal !== "string") return false;
|
|
2800
2857
|
if (value.status !== void 0 && !isMeshMissionStatusValue(value.status)) return false;
|
|
2801
2858
|
if (value.brief !== void 0 && value.brief !== null && !isMissionBriefWire(value.brief)) return false;
|
|
@@ -2805,7 +2862,7 @@ function decodeMissionUpsertRequest(value) {
|
|
|
2805
2862
|
return isMissionUpsertRequest(value) ? value : null;
|
|
2806
2863
|
}
|
|
2807
2864
|
function isMissionUpsertResponse(value) {
|
|
2808
|
-
return isRecord(value) && hasOnlyKeys2(value, ["mission"]) && isMeshMissionRecordWire(value.mission);
|
|
2865
|
+
return isRecord(value) && hasOnlyKeys2(value, ["mission", "result"]) && isMeshMissionRecordWire(value.mission) && (value.result === void 0 || isRecord(value.result));
|
|
2809
2866
|
}
|
|
2810
2867
|
function decodeMissionUpsertResponse(value) {
|
|
2811
2868
|
return isMissionUpsertResponse(value) ? value : null;
|
|
@@ -2831,7 +2888,10 @@ function decodeMissionQueryResponse(value) {
|
|
|
2831
2888
|
return isMissionQueryResponse(value) ? value : null;
|
|
2832
2889
|
}
|
|
2833
2890
|
function isMissionListQueryRequest(value) {
|
|
2834
|
-
if (!isRecord(value) || !hasOnlyKeys2(value, ["v", "meshId", "statuses", "verbose", "withStats", "limit", "historyIdLimit", "meshStatusView"])) return false;
|
|
2891
|
+
if (!isRecord(value) || !hasOnlyKeys2(value, ["v", "meshId", "statuses", "verbose", "withStats", "limit", "historyIdLimit", "meshStatusView", "structured", "items", "history"])) return false;
|
|
2892
|
+
for (const k of ["structured", "items", "history"]) {
|
|
2893
|
+
if (value[k] !== void 0 && typeof value[k] !== "boolean") return false;
|
|
2894
|
+
}
|
|
2835
2895
|
if (value.meshStatusView !== void 0 && value.meshStatusView !== "compact" && value.meshStatusView !== "verbose") return false;
|
|
2836
2896
|
if (value.v !== TURN_IPC_PROTOCOL_VERSION) return false;
|
|
2837
2897
|
if (!isEvidenceIdentifier(value.meshId)) return false;
|
|
@@ -2873,7 +2933,7 @@ function isMissionListSummaryWire(value) {
|
|
|
2873
2933
|
const hasGoal = "goal" in value;
|
|
2874
2934
|
const hasPreview = "goalPreview" in value && "goalTruncated" in value;
|
|
2875
2935
|
if (hasGoal === hasPreview) return false;
|
|
2876
|
-
const baseKeys = ["id", "meshId", "title", "status", "tasks", "stats", "brief", "createdAt", "updatedAt", "closeCandidateEmittedAt"];
|
|
2936
|
+
const baseKeys = ["id", "meshId", "title", "status", "tasks", "stats", "brief", "createdAt", "updatedAt", "closeCandidateEmittedAt", ...STRUCTURED_MISSION_KEYS, "items", "history"];
|
|
2877
2937
|
const allowed = hasGoal ? [...baseKeys, "goal"] : [...baseKeys, "goalPreview", "goalTruncated"];
|
|
2878
2938
|
if (!hasOnlyKeys2(value, allowed)) return false;
|
|
2879
2939
|
if (!isEvidenceIdentifier(value.id) || !isEvidenceIdentifier(value.meshId)) return false;
|
|
@@ -2887,6 +2947,10 @@ function isMissionListSummaryWire(value) {
|
|
|
2887
2947
|
if (value.createdAt !== void 0 && typeof value.createdAt !== "string") return false;
|
|
2888
2948
|
if (value.updatedAt !== void 0 && typeof value.updatedAt !== "string") return false;
|
|
2889
2949
|
if (value.closeCandidateEmittedAt !== void 0 && value.closeCandidateEmittedAt !== null && typeof value.closeCandidateEmittedAt !== "string") return false;
|
|
2950
|
+
if (!isStructuredMissionFields(value)) return false;
|
|
2951
|
+
for (const k of ["items", "history"]) {
|
|
2952
|
+
if (value[k] !== void 0 && (!Array.isArray(value[k]) || !value[k].every(isRecord))) return false;
|
|
2953
|
+
}
|
|
2890
2954
|
return true;
|
|
2891
2955
|
}
|
|
2892
2956
|
function isMeshMissionHistoryFoldWire(value) {
|
|
@@ -3409,6 +3473,282 @@ function touchedFilesOutsideOwnership(touched, owned) {
|
|
|
3409
3473
|
return { undeclaredTouched, unusedDeclarations };
|
|
3410
3474
|
}
|
|
3411
3475
|
|
|
3476
|
+
// src/mission-items.ts
|
|
3477
|
+
var MISSION_ITEM_KINDS = ["remaining", "live_check", "decision", "evidence"];
|
|
3478
|
+
var MISSION_ITEM_STATES = ["open", "done", "dropped", "moved", "answered", "expired", "withdrawn", "superseded"];
|
|
3479
|
+
var COORDINATOR_SETTABLE_ITEM_STATES = {
|
|
3480
|
+
remaining: ["open", "done", "dropped"],
|
|
3481
|
+
live_check: ["open", "done", "dropped"],
|
|
3482
|
+
evidence: ["open", "done", "dropped"],
|
|
3483
|
+
decision: ["open", "withdrawn", "superseded"]
|
|
3484
|
+
};
|
|
3485
|
+
var MISSION_OUTCOMES = ["merged", "verified_live", "superseded", "not_needed", "owner_abandoned", "unspecified"];
|
|
3486
|
+
function isMissionOutcome(value) {
|
|
3487
|
+
return typeof value === "string" && MISSION_OUTCOMES.includes(value);
|
|
3488
|
+
}
|
|
3489
|
+
var MISSION_REF_KINDS = ["commit", "branch", "pr", "task", "artifact", "mission", "url"];
|
|
3490
|
+
var MISSION_LIMITS = {
|
|
3491
|
+
summary: 300,
|
|
3492
|
+
outcomeReason: 500,
|
|
3493
|
+
itemText: 300,
|
|
3494
|
+
machine: 80,
|
|
3495
|
+
refs: 8,
|
|
3496
|
+
refValue: 300,
|
|
3497
|
+
refRepo: 120,
|
|
3498
|
+
refNote: 200,
|
|
3499
|
+
dedupeKey: 400,
|
|
3500
|
+
question: 300,
|
|
3501
|
+
context: 600,
|
|
3502
|
+
options: 5,
|
|
3503
|
+
optionLabel: 60,
|
|
3504
|
+
optionDetail: 200,
|
|
3505
|
+
/** Open items per mission before the oldest `remaining` fold into a "N more" summary item. */
|
|
3506
|
+
openItemsPerMission: 200,
|
|
3507
|
+
/** One event payload (serialized). */
|
|
3508
|
+
eventPayloadBytes: 16 * 1024,
|
|
3509
|
+
/** items_add / items_update entries honoured per call (extra entries are reported, not applied). */
|
|
3510
|
+
itemsPerCall: 50
|
|
3511
|
+
};
|
|
3512
|
+
var MISSION_DECISION_OPTION_IDS = ["a", "b", "c", "d", "e"];
|
|
3513
|
+
var MISSION_DECISION_URGENCIES = ["normal", "blocking"];
|
|
3514
|
+
var MISSION_DECISION_ON_DUE = ["remind", "apply_recommended"];
|
|
3515
|
+
function truncateMissionText(value, max) {
|
|
3516
|
+
if (value.length <= max) return value;
|
|
3517
|
+
return `${value.slice(0, max - 1).trimEnd()}\u2026`;
|
|
3518
|
+
}
|
|
3519
|
+
function str(value) {
|
|
3520
|
+
return typeof value === "string" ? value.trim() : "";
|
|
3521
|
+
}
|
|
3522
|
+
function collapse(value) {
|
|
3523
|
+
return value.replace(/\s+/g, " ").trim();
|
|
3524
|
+
}
|
|
3525
|
+
function normalizeMissionSummary(value) {
|
|
3526
|
+
if (typeof value !== "string") return null;
|
|
3527
|
+
const text = collapse(value);
|
|
3528
|
+
return { value: truncateMissionText(text, MISSION_LIMITS.summary), truncated: text.length > MISSION_LIMITS.summary };
|
|
3529
|
+
}
|
|
3530
|
+
function normalizeOutcomeReason(value) {
|
|
3531
|
+
if (typeof value !== "string") return null;
|
|
3532
|
+
const text = value.trim();
|
|
3533
|
+
return { value: truncateMissionText(text, MISSION_LIMITS.outcomeReason), truncated: text.length > MISSION_LIMITS.outcomeReason };
|
|
3534
|
+
}
|
|
3535
|
+
function normalizeMissionRefs(value) {
|
|
3536
|
+
if (!Array.isArray(value)) return { refs: [], truncated: false };
|
|
3537
|
+
const refs = [];
|
|
3538
|
+
let truncated = false;
|
|
3539
|
+
for (const raw of value) {
|
|
3540
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
3541
|
+
const r = raw;
|
|
3542
|
+
const kind = str(r.kind);
|
|
3543
|
+
const refValue = str(r.value);
|
|
3544
|
+
if (!MISSION_REF_KINDS.includes(kind) || !refValue) continue;
|
|
3545
|
+
if (refs.length >= MISSION_LIMITS.refs) {
|
|
3546
|
+
truncated = true;
|
|
3547
|
+
break;
|
|
3548
|
+
}
|
|
3549
|
+
const repo = str(r.repo);
|
|
3550
|
+
const note = str(r.note);
|
|
3551
|
+
refs.push({
|
|
3552
|
+
kind,
|
|
3553
|
+
...repo ? { repo: truncateMissionText(repo, MISSION_LIMITS.refRepo) } : {},
|
|
3554
|
+
value: truncateMissionText(refValue, MISSION_LIMITS.refValue),
|
|
3555
|
+
...note ? { note: truncateMissionText(note, MISSION_LIMITS.refNote) } : {}
|
|
3556
|
+
});
|
|
3557
|
+
}
|
|
3558
|
+
return { refs, truncated };
|
|
3559
|
+
}
|
|
3560
|
+
function normalizeOptions(value, truncated) {
|
|
3561
|
+
if (!Array.isArray(value)) return [];
|
|
3562
|
+
const out = [];
|
|
3563
|
+
for (const raw of value) {
|
|
3564
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
3565
|
+
if (out.length >= MISSION_LIMITS.options) {
|
|
3566
|
+
truncated.push("options");
|
|
3567
|
+
break;
|
|
3568
|
+
}
|
|
3569
|
+
out.push({ id: MISSION_DECISION_OPTION_IDS[out.length], label: truncateMissionText(raw.trim(), MISSION_LIMITS.optionLabel) });
|
|
3570
|
+
continue;
|
|
3571
|
+
}
|
|
3572
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
3573
|
+
const o = raw;
|
|
3574
|
+
const label = collapse(str(o.label));
|
|
3575
|
+
if (!label) continue;
|
|
3576
|
+
if (out.length >= MISSION_LIMITS.options) {
|
|
3577
|
+
truncated.push("options");
|
|
3578
|
+
break;
|
|
3579
|
+
}
|
|
3580
|
+
const detail = str(o.detail);
|
|
3581
|
+
out.push({
|
|
3582
|
+
id: MISSION_DECISION_OPTION_IDS[out.length],
|
|
3583
|
+
label: truncateMissionText(label, MISSION_LIMITS.optionLabel),
|
|
3584
|
+
...detail ? { detail: truncateMissionText(detail, MISSION_LIMITS.optionDetail) } : {}
|
|
3585
|
+
});
|
|
3586
|
+
}
|
|
3587
|
+
return out;
|
|
3588
|
+
}
|
|
3589
|
+
function normalizeDueAt(value) {
|
|
3590
|
+
if (typeof value !== "string" || !value.trim()) return void 0;
|
|
3591
|
+
const ms2 = Date.parse(value);
|
|
3592
|
+
return Number.isNaN(ms2) ? void 0 : new Date(ms2).toISOString();
|
|
3593
|
+
}
|
|
3594
|
+
function normalizeDecisionInput(raw, truncated) {
|
|
3595
|
+
const questionSource = collapse(str(raw.question) || str(raw.text));
|
|
3596
|
+
if (!questionSource) return null;
|
|
3597
|
+
if (questionSource.length > MISSION_LIMITS.question) truncated.push("question");
|
|
3598
|
+
const question = truncateMissionText(questionSource, MISSION_LIMITS.question);
|
|
3599
|
+
const contextSource = str(raw.context);
|
|
3600
|
+
if (contextSource.length > MISSION_LIMITS.context) truncated.push("context");
|
|
3601
|
+
const options = normalizeOptions(raw.options, truncated);
|
|
3602
|
+
const recommendedRaw = str(raw.recommended);
|
|
3603
|
+
const recommended = recommendedRaw && options.some((o) => o.id === recommendedRaw) ? recommendedRaw : options.find((o) => recommendedRaw && o.label.toLowerCase() === recommendedRaw.toLowerCase())?.id;
|
|
3604
|
+
const dueAt = normalizeDueAt(raw.dueAt ?? raw.due_at);
|
|
3605
|
+
const onDueRaw = str(raw.onDue ?? raw.on_due);
|
|
3606
|
+
const urgencyRaw = str(raw.urgency);
|
|
3607
|
+
const allowFreeTextRaw = raw.allowFreeText ?? raw.allow_free_text;
|
|
3608
|
+
return {
|
|
3609
|
+
question,
|
|
3610
|
+
...contextSource ? { context: truncateMissionText(contextSource, MISSION_LIMITS.context) } : {},
|
|
3611
|
+
options,
|
|
3612
|
+
...recommended ? { recommended } : {},
|
|
3613
|
+
allowFreeText: typeof allowFreeTextRaw === "boolean" ? allowFreeTextRaw : true,
|
|
3614
|
+
...dueAt ? { dueAt } : {},
|
|
3615
|
+
// apply_recommended without a recommended option has nothing to apply — fall back to remind.
|
|
3616
|
+
onDue: onDueRaw === "apply_recommended" && recommended ? "apply_recommended" : "remind",
|
|
3617
|
+
urgency: urgencyRaw === "blocking" ? "blocking" : "normal"
|
|
3618
|
+
};
|
|
3619
|
+
}
|
|
3620
|
+
function normalizeForDedupe(text) {
|
|
3621
|
+
return collapse(text).toLowerCase().replace(/[\s.!?。]+$/u, "");
|
|
3622
|
+
}
|
|
3623
|
+
function deriveItemDedupeKey(kind, parts) {
|
|
3624
|
+
const explicit = str(parts.explicit);
|
|
3625
|
+
if (explicit) return truncateMissionText(`k:${explicit}`, MISSION_LIMITS.dedupeKey);
|
|
3626
|
+
if (kind === "decision") return truncateMissionText(`decision:${normalizeForDedupe(parts.question ?? parts.text ?? "")}`, MISSION_LIMITS.dedupeKey);
|
|
3627
|
+
if (kind === "evidence") {
|
|
3628
|
+
const ref2 = parts.refs?.[0];
|
|
3629
|
+
if (ref2) return truncateMissionText(`evidence:${ref2.kind}:${ref2.repo ?? ""}:${ref2.value}`, MISSION_LIMITS.dedupeKey);
|
|
3630
|
+
}
|
|
3631
|
+
const machine = parts.machine ? `@${normalizeForDedupe(parts.machine)}` : "";
|
|
3632
|
+
return truncateMissionText(`${kind}${machine}:${normalizeForDedupe(parts.text ?? "")}`, MISSION_LIMITS.dedupeKey);
|
|
3633
|
+
}
|
|
3634
|
+
function normalizeMissionItemInput(raw) {
|
|
3635
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { error: "item must be an object" };
|
|
3636
|
+
const r = raw;
|
|
3637
|
+
const kind = str(r.kind) || "remaining";
|
|
3638
|
+
if (!MISSION_ITEM_KINDS.includes(kind)) {
|
|
3639
|
+
return { error: `invalid kind '${kind}' (valid: ${MISSION_ITEM_KINDS.join(", ")})` };
|
|
3640
|
+
}
|
|
3641
|
+
const truncated = [];
|
|
3642
|
+
const { refs, truncated: refsTruncated } = normalizeMissionRefs(r.refs);
|
|
3643
|
+
if (refsTruncated) truncated.push("refs");
|
|
3644
|
+
const machineRaw = collapse(str(r.machine));
|
|
3645
|
+
const machine = machineRaw ? truncateMissionText(machineRaw, MISSION_LIMITS.machine) : void 0;
|
|
3646
|
+
const explicitKey = str(r.dedupe_key ?? r.dedupeKey);
|
|
3647
|
+
if (kind === "decision") {
|
|
3648
|
+
const decisionRaw = r.decision && typeof r.decision === "object" && !Array.isArray(r.decision) ? r.decision : r;
|
|
3649
|
+
const decision = normalizeDecisionInput({ ...decisionRaw, question: decisionRaw.question ?? r.question ?? r.text }, truncated);
|
|
3650
|
+
if (!decision) return { error: "decision item needs a question" };
|
|
3651
|
+
return {
|
|
3652
|
+
item: {
|
|
3653
|
+
kind,
|
|
3654
|
+
text: decision.question,
|
|
3655
|
+
...machine ? { machine } : {},
|
|
3656
|
+
refs,
|
|
3657
|
+
decision,
|
|
3658
|
+
dedupeKey: deriveItemDedupeKey("decision", { question: decision.question, explicit: explicitKey }),
|
|
3659
|
+
truncated
|
|
3660
|
+
}
|
|
3661
|
+
};
|
|
3662
|
+
}
|
|
3663
|
+
const textSource = collapse(str(r.text));
|
|
3664
|
+
if (!textSource && !(kind === "evidence" && refs.length > 0)) return { error: `${kind} item needs text` };
|
|
3665
|
+
if (textSource.length > MISSION_LIMITS.itemText) truncated.push("text");
|
|
3666
|
+
const text = truncateMissionText(textSource || `${refs[0].kind}: ${refs[0].value}`, MISSION_LIMITS.itemText);
|
|
3667
|
+
return {
|
|
3668
|
+
item: {
|
|
3669
|
+
kind,
|
|
3670
|
+
text,
|
|
3671
|
+
...machine ? { machine } : {},
|
|
3672
|
+
refs,
|
|
3673
|
+
dedupeKey: deriveItemDedupeKey(kind, { text, machine, refs, explicit: explicitKey }),
|
|
3674
|
+
truncated
|
|
3675
|
+
}
|
|
3676
|
+
};
|
|
3677
|
+
}
|
|
3678
|
+
function normalizeMissionItemUpdate(raw) {
|
|
3679
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { error: "update must be an object" };
|
|
3680
|
+
const r = raw;
|
|
3681
|
+
const id2 = str(r.id ?? r.item_id ?? r.itemId);
|
|
3682
|
+
if (!id2) return { error: "update needs an item id" };
|
|
3683
|
+
const truncated = [];
|
|
3684
|
+
const update = { id: id2 };
|
|
3685
|
+
if (r.state !== void 0) {
|
|
3686
|
+
const state = str(r.state);
|
|
3687
|
+
if (!MISSION_ITEM_STATES.includes(state)) return { error: `invalid state '${state}'` };
|
|
3688
|
+
update.state = state;
|
|
3689
|
+
}
|
|
3690
|
+
if (typeof r.text === "string") {
|
|
3691
|
+
const text = collapse(r.text);
|
|
3692
|
+
if (text.length > MISSION_LIMITS.itemText) truncated.push("text");
|
|
3693
|
+
if (text) update.text = truncateMissionText(text, MISSION_LIMITS.itemText);
|
|
3694
|
+
}
|
|
3695
|
+
if (r.machine === null) update.machine = null;
|
|
3696
|
+
else if (typeof r.machine === "string") {
|
|
3697
|
+
const machine = collapse(r.machine);
|
|
3698
|
+
update.machine = machine ? truncateMissionText(machine, MISSION_LIMITS.machine) : null;
|
|
3699
|
+
}
|
|
3700
|
+
if (r.refs !== void 0) {
|
|
3701
|
+
const { refs, truncated: t } = normalizeMissionRefs(r.refs);
|
|
3702
|
+
if (t) truncated.push("refs");
|
|
3703
|
+
update.refs = refs;
|
|
3704
|
+
}
|
|
3705
|
+
return { update, truncated };
|
|
3706
|
+
}
|
|
3707
|
+
function boundEventPayload(payload) {
|
|
3708
|
+
let json = JSON.stringify(payload);
|
|
3709
|
+
if (json.length <= MISSION_LIMITS.eventPayloadBytes) return json;
|
|
3710
|
+
const shrunk = {};
|
|
3711
|
+
for (const [k, v] of Object.entries(payload)) {
|
|
3712
|
+
shrunk[k] = typeof v === "string" && v.length > 4e3 ? `${v.slice(0, 4e3)}\u2026` : v;
|
|
3713
|
+
}
|
|
3714
|
+
shrunk.payloadTruncated = true;
|
|
3715
|
+
json = JSON.stringify(shrunk);
|
|
3716
|
+
if (json.length <= MISSION_LIMITS.eventPayloadBytes) return json;
|
|
3717
|
+
return JSON.stringify({ payloadTruncated: true, keys: Object.keys(payload).slice(0, 20) });
|
|
3718
|
+
}
|
|
3719
|
+
var CARRY_OVER_MISSION_TITLE = "Carry-over \u2014 open items from closed missions";
|
|
3720
|
+
var LEGACY_CARRY_OVER_MISSION_TITLE = "\uC774\uC6D4 \u2014 \uB2EB\uD78C \uBBF8\uC158\uC5D0\uC11C \uB118\uC5B4\uC628 \uD56D\uBAA9";
|
|
3721
|
+
var CARRY_OVER_MISSION_GOAL = "Open items carried over from closed missions, and decisions requested without a mission. Managed automatically \u2014 do not close.";
|
|
3722
|
+
function isCarryOverMissionRecord(m) {
|
|
3723
|
+
return !!m && (m.isCarryOver === true || isCarryOverMissionTitle(m.title));
|
|
3724
|
+
}
|
|
3725
|
+
function isCarryOverMissionTitle(title) {
|
|
3726
|
+
if (typeof title !== "string") return false;
|
|
3727
|
+
const t = title.trim();
|
|
3728
|
+
return t === CARRY_OVER_MISSION_TITLE || t === LEGACY_CARRY_OVER_MISSION_TITLE;
|
|
3729
|
+
}
|
|
3730
|
+
var OWNER_ABANDON_CONFIRM_KEY_PREFIX = "owner-abandon-confirm:";
|
|
3731
|
+
var OWNER_ABANDON_CONFIRM_QUESTION = "The coordinator closed this as 'owner abandoned' \u2014 correct?";
|
|
3732
|
+
var OWNER_ABANDON_CONFIRM_OPTIONS = ["Correct", "Reopen"];
|
|
3733
|
+
var WORKER_DECISIONS_NEEDED_MAX = 3;
|
|
3734
|
+
var WORKER_COMMITS_MAX = 20;
|
|
3735
|
+
var SHA_RE = /^[0-9a-f]{7,64}$/i;
|
|
3736
|
+
function normalizeReportCommits(value) {
|
|
3737
|
+
if (!Array.isArray(value)) return null;
|
|
3738
|
+
const out = [];
|
|
3739
|
+
for (const v of value) {
|
|
3740
|
+
if (typeof v !== "string") return null;
|
|
3741
|
+
const sha = v.trim();
|
|
3742
|
+
if (!SHA_RE.test(sha)) return null;
|
|
3743
|
+
if (!out.includes(sha.toLowerCase())) out.push(sha.toLowerCase());
|
|
3744
|
+
}
|
|
3745
|
+
return out;
|
|
3746
|
+
}
|
|
3747
|
+
|
|
3748
|
+
// src/decision-push-relay.ts
|
|
3749
|
+
var DECISION_PUSH_RELAY_COMMAND = "mission_decision_push_relay_answer";
|
|
3750
|
+
var DECISION_PUSH_RELAY_SOURCE = "push_relay";
|
|
3751
|
+
|
|
3412
3752
|
// src/keyed-doc-delta.ts
|
|
3413
3753
|
function sig(value) {
|
|
3414
3754
|
if (value === void 0) return void 0;
|
|
@@ -3870,12 +4210,15 @@ export {
|
|
|
3870
4210
|
CANCEL_REASONS,
|
|
3871
4211
|
CANONICAL_MESH_TOOL_COUNT,
|
|
3872
4212
|
CANONICAL_MESH_TOOL_NAMES,
|
|
4213
|
+
CARRY_OVER_MISSION_GOAL,
|
|
4214
|
+
CARRY_OVER_MISSION_TITLE,
|
|
3873
4215
|
CLAUDE_TUI_REVIEW_PAGE_NOT_FOCUSED_PREFIX,
|
|
3874
4216
|
CLAUDE_TUI_REVIEW_UNCONFIRMED_PREFIX,
|
|
3875
4217
|
CLI_SLOT_RECIPES,
|
|
3876
4218
|
COMMIT_STRENGTHS,
|
|
3877
4219
|
CONSUME_PROFILES,
|
|
3878
4220
|
COORDINATOR_ACK_OUTCOMES,
|
|
4221
|
+
COORDINATOR_SETTABLE_ITEM_STATES,
|
|
3879
4222
|
DAEMON_METADATA_DOC_SPEC,
|
|
3880
4223
|
DAEMON_P2P_SIGNAL_TYPES,
|
|
3881
4224
|
DAEMON_STATUS_EVENT_NAMES,
|
|
@@ -3888,6 +4231,11 @@ export {
|
|
|
3888
4231
|
DASHBOARD_TO_DAEMON_P2P_TYPES,
|
|
3889
4232
|
DASHBOARD_TO_USER_SESSION_TYPES,
|
|
3890
4233
|
DASHBOARD_WIRE_VERSION,
|
|
4234
|
+
DECISION_PUSH_OPTIONS_MAX,
|
|
4235
|
+
DECISION_PUSH_OPTION_LABEL_MAX,
|
|
4236
|
+
DECISION_PUSH_QUESTION_MAX,
|
|
4237
|
+
DECISION_PUSH_RELAY_COMMAND,
|
|
4238
|
+
DECISION_PUSH_RELAY_SOURCE,
|
|
3891
4239
|
DEFAULT_DIFFICULTY_BRAINS,
|
|
3892
4240
|
DELIVERY_OUTCOMES,
|
|
3893
4241
|
DELIVERY_VIAS,
|
|
@@ -3899,6 +4247,7 @@ export {
|
|
|
3899
4247
|
LAUNCH_DEFAULT_ERROR_CODES,
|
|
3900
4248
|
LAUNCH_DEFAULT_ROLES,
|
|
3901
4249
|
LAUNCH_DEFAULT_SOURCES,
|
|
4250
|
+
LEGACY_CARRY_OVER_MISSION_TITLE,
|
|
3902
4251
|
LIVENESS_RESULTS,
|
|
3903
4252
|
MAX_MESH_RECORD_STRING,
|
|
3904
4253
|
MAX_OWNED_PATHS,
|
|
@@ -3924,6 +4273,14 @@ export {
|
|
|
3924
4273
|
MESH_TOPIC_ENTRY_KINDS,
|
|
3925
4274
|
MESH_TOPIC_PROTOCOL_VERSION,
|
|
3926
4275
|
MISSION_BRIEF_RENDER_MAX_CHARS,
|
|
4276
|
+
MISSION_DECISION_ON_DUE,
|
|
4277
|
+
MISSION_DECISION_OPTION_IDS,
|
|
4278
|
+
MISSION_DECISION_URGENCIES,
|
|
4279
|
+
MISSION_ITEM_KINDS,
|
|
4280
|
+
MISSION_ITEM_STATES,
|
|
4281
|
+
MISSION_LIMITS,
|
|
4282
|
+
MISSION_OUTCOMES,
|
|
4283
|
+
MISSION_REF_KINDS,
|
|
3927
4284
|
MODEL_AXIS_SOURCES,
|
|
3928
4285
|
MODEL_SELECTION_HISTORY_LIMIT,
|
|
3929
4286
|
MeshChunkAssembler,
|
|
@@ -3937,6 +4294,9 @@ export {
|
|
|
3937
4294
|
OPERATOR_STATUS_REASON_VALUES,
|
|
3938
4295
|
OPERATOR_STATUS_VALUES,
|
|
3939
4296
|
OUTBOUND_MESSAGE_ORIGINS,
|
|
4297
|
+
OWNER_ABANDON_CONFIRM_KEY_PREFIX,
|
|
4298
|
+
OWNER_ABANDON_CONFIRM_OPTIONS,
|
|
4299
|
+
OWNER_ABANDON_CONFIRM_QUESTION,
|
|
3940
4300
|
P2P_SIGNAL_TYPES,
|
|
3941
4301
|
PROVIDER_FAILURES,
|
|
3942
4302
|
QUOTA_BACKFILL_HORIZON_MS,
|
|
@@ -3988,6 +4348,8 @@ export {
|
|
|
3988
4348
|
VERSION_UPDATE_REASONS,
|
|
3989
4349
|
VIEWER_TO_SHARED_SESSION_TYPES,
|
|
3990
4350
|
WORKER_BRANCH_STATES,
|
|
4351
|
+
WORKER_COMMITS_MAX,
|
|
4352
|
+
WORKER_DECISIONS_NEEDED_MAX,
|
|
3991
4353
|
WORKER_PROTOCOL_FOOTER_MARKER,
|
|
3992
4354
|
WORKER_REPORT_OUTCOMES,
|
|
3993
4355
|
WORKER_REPORT_SUMMARY_MAX_CHARS,
|
|
@@ -3995,6 +4357,7 @@ export {
|
|
|
3995
4357
|
appendWorkerProtocolFooter,
|
|
3996
4358
|
argsCarryStatusProbeMarker,
|
|
3997
4359
|
assessQuotaFreshness,
|
|
4360
|
+
boundEventPayload,
|
|
3998
4361
|
buildSlotProposal,
|
|
3999
4362
|
canonicalDaemonId,
|
|
4000
4363
|
classifySessionStatus,
|
|
@@ -4064,6 +4427,7 @@ export {
|
|
|
4064
4427
|
decodeUserSessionToDashboard,
|
|
4065
4428
|
decodeViewerToSharedSession,
|
|
4066
4429
|
defaultProviderPriorityFromNodeFacts,
|
|
4430
|
+
deriveItemDedupeKey,
|
|
4067
4431
|
deriveProviderPriorityFromSlots,
|
|
4068
4432
|
deriveSlotsFromLegacy,
|
|
4069
4433
|
describeModelSelection,
|
|
@@ -4075,6 +4439,7 @@ export {
|
|
|
4075
4439
|
findOwnershipConflicts,
|
|
4076
4440
|
foldKeyedDoc,
|
|
4077
4441
|
followedRemoteProjectKey,
|
|
4442
|
+
followerOpPermitted,
|
|
4078
4443
|
formatQuotaAccount,
|
|
4079
4444
|
hasGitStatusEvidence,
|
|
4080
4445
|
hasWorkerProtocolFooter,
|
|
@@ -4084,6 +4449,8 @@ export {
|
|
|
4084
4449
|
isAssistantTool,
|
|
4085
4450
|
isBlockedStatus,
|
|
4086
4451
|
isBusyStatus,
|
|
4452
|
+
isCarryOverMissionRecord,
|
|
4453
|
+
isCarryOverMissionTitle,
|
|
4087
4454
|
isChunkType,
|
|
4088
4455
|
isCommitStrength,
|
|
4089
4456
|
isDaemonDirectCommandType,
|
|
@@ -4116,6 +4483,7 @@ export {
|
|
|
4116
4483
|
isMeshTerminalTaskStatus,
|
|
4117
4484
|
isMeshTopicEntry,
|
|
4118
4485
|
isMessageId,
|
|
4486
|
+
isMissionOutcome,
|
|
4119
4487
|
isMissionUpsertResponse,
|
|
4120
4488
|
isModelAxisSource,
|
|
4121
4489
|
isNativeMarkerRef,
|
|
@@ -4166,16 +4534,24 @@ export {
|
|
|
4166
4534
|
minutesUntilQuotaCheck,
|
|
4167
4535
|
normalizeAuthOkLimits,
|
|
4168
4536
|
normalizeBrainSlot,
|
|
4537
|
+
normalizeDecisionInput,
|
|
4169
4538
|
normalizeDifficultyBrainMap,
|
|
4539
|
+
normalizeForDedupe,
|
|
4170
4540
|
normalizeGitStatus,
|
|
4171
4541
|
normalizeMeshNodeFacts,
|
|
4172
4542
|
normalizeMeshNodeId,
|
|
4173
4543
|
normalizeMeshSessionRecord,
|
|
4174
4544
|
normalizeMeshWorkspaceForCompare,
|
|
4175
4545
|
normalizeMissionBrief,
|
|
4546
|
+
normalizeMissionItemInput,
|
|
4547
|
+
normalizeMissionItemUpdate,
|
|
4548
|
+
normalizeMissionRefs,
|
|
4549
|
+
normalizeMissionSummary,
|
|
4176
4550
|
normalizeNodeCapabilitySlot,
|
|
4177
4551
|
normalizeNodeCapabilitySlots,
|
|
4552
|
+
normalizeOutcomeReason,
|
|
4178
4553
|
normalizeOwnedPaths,
|
|
4554
|
+
normalizeReportCommits,
|
|
4179
4555
|
normalizeSessionStatus,
|
|
4180
4556
|
normalizeThinkingLevel,
|
|
4181
4557
|
orderProvidersByBuiltinPreference,
|
|
@@ -4215,6 +4591,7 @@ export {
|
|
|
4215
4591
|
summarizeGitShape,
|
|
4216
4592
|
supportsQuota,
|
|
4217
4593
|
touchedFilesOutsideOwnership,
|
|
4594
|
+
truncateMissionText,
|
|
4218
4595
|
unwrapPastedContent,
|
|
4219
4596
|
withStatusProbeMarker
|
|
4220
4597
|
};
|