@xenosystem/agent-interface-core 0.1.3

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.
Files changed (122) hide show
  1. package/LICENSE +67 -0
  2. package/dist/agentDiscovery.d.ts +97 -0
  3. package/dist/agentDiscovery.d.ts.map +1 -0
  4. package/dist/agentDiscovery.js +93 -0
  5. package/dist/agentDiscovery.js.map +1 -0
  6. package/dist/capabilityRouting.d.ts +72 -0
  7. package/dist/capabilityRouting.d.ts.map +1 -0
  8. package/dist/capabilityRouting.js +124 -0
  9. package/dist/capabilityRouting.js.map +1 -0
  10. package/dist/capabilityTier.d.ts +105 -0
  11. package/dist/capabilityTier.d.ts.map +1 -0
  12. package/dist/capabilityTier.js +120 -0
  13. package/dist/capabilityTier.js.map +1 -0
  14. package/dist/combinationVerification.d.ts +101 -0
  15. package/dist/combinationVerification.d.ts.map +1 -0
  16. package/dist/combinationVerification.js +115 -0
  17. package/dist/combinationVerification.js.map +1 -0
  18. package/dist/context/agentAttachedContextPrompt.d.ts +13 -0
  19. package/dist/context/agentAttachedContextPrompt.d.ts.map +1 -0
  20. package/dist/context/agentAttachedContextPrompt.js +50 -0
  21. package/dist/context/agentAttachedContextPrompt.js.map +1 -0
  22. package/dist/context/agentModelContext.d.ts +77 -0
  23. package/dist/context/agentModelContext.d.ts.map +1 -0
  24. package/dist/context/agentModelContext.js +297 -0
  25. package/dist/context/agentModelContext.js.map +1 -0
  26. package/dist/fanOutPlanner.d.ts +65 -0
  27. package/dist/fanOutPlanner.d.ts.map +1 -0
  28. package/dist/fanOutPlanner.js +78 -0
  29. package/dist/fanOutPlanner.js.map +1 -0
  30. package/dist/fleetBoardProjection.d.ts +143 -0
  31. package/dist/fleetBoardProjection.d.ts.map +1 -0
  32. package/dist/fleetBoardProjection.js +156 -0
  33. package/dist/fleetBoardProjection.js.map +1 -0
  34. package/dist/fleetProjection.d.ts +63 -0
  35. package/dist/fleetProjection.d.ts.map +1 -0
  36. package/dist/fleetProjection.js +86 -0
  37. package/dist/fleetProjection.js.map +1 -0
  38. package/dist/hostBackedCapabilities.d.ts +50 -0
  39. package/dist/hostBackedCapabilities.d.ts.map +1 -0
  40. package/dist/hostBackedCapabilities.js +66 -0
  41. package/dist/hostBackedCapabilities.js.map +1 -0
  42. package/dist/index.d.ts +54 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +134 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/intakeBoardProjection.d.ts +75 -0
  47. package/dist/intakeBoardProjection.d.ts.map +1 -0
  48. package/dist/intakeBoardProjection.js +90 -0
  49. package/dist/intakeBoardProjection.js.map +1 -0
  50. package/dist/intakeClaim.d.ts +156 -0
  51. package/dist/intakeClaim.d.ts.map +1 -0
  52. package/dist/intakeClaim.js +190 -0
  53. package/dist/intakeClaim.js.map +1 -0
  54. package/dist/knowledgeBoardProjection.d.ts +57 -0
  55. package/dist/knowledgeBoardProjection.d.ts.map +1 -0
  56. package/dist/knowledgeBoardProjection.js +74 -0
  57. package/dist/knowledgeBoardProjection.js.map +1 -0
  58. package/dist/landingOverlap.d.ts +127 -0
  59. package/dist/landingOverlap.d.ts.map +1 -0
  60. package/dist/landingOverlap.js +107 -0
  61. package/dist/landingOverlap.js.map +1 -0
  62. package/dist/landingQueue.d.ts +152 -0
  63. package/dist/landingQueue.d.ts.map +1 -0
  64. package/dist/landingQueue.js +258 -0
  65. package/dist/landingQueue.js.map +1 -0
  66. package/dist/markdown/markdownWindowsPaths.d.ts +20 -0
  67. package/dist/markdown/markdownWindowsPaths.d.ts.map +1 -0
  68. package/dist/markdown/markdownWindowsPaths.js +208 -0
  69. package/dist/markdown/markdownWindowsPaths.js.map +1 -0
  70. package/dist/reviewProjection.d.ts +118 -0
  71. package/dist/reviewProjection.d.ts.map +1 -0
  72. package/dist/reviewProjection.js +133 -0
  73. package/dist/reviewProjection.js.map +1 -0
  74. package/dist/runDiff.d.ts +86 -0
  75. package/dist/runDiff.d.ts.map +1 -0
  76. package/dist/runDiff.js +103 -0
  77. package/dist/runDiff.js.map +1 -0
  78. package/dist/runtime/agentReasoningEffort.d.ts +22 -0
  79. package/dist/runtime/agentReasoningEffort.d.ts.map +1 -0
  80. package/dist/runtime/agentReasoningEffort.js +76 -0
  81. package/dist/runtime/agentReasoningEffort.js.map +1 -0
  82. package/dist/runtime/agentRuntimeProvider.d.ts +12 -0
  83. package/dist/runtime/agentRuntimeProvider.d.ts.map +1 -0
  84. package/dist/runtime/agentRuntimeProvider.js +294 -0
  85. package/dist/runtime/agentRuntimeProvider.js.map +1 -0
  86. package/dist/runtime/agentRuntimeProviderTypes.d.ts +100 -0
  87. package/dist/runtime/agentRuntimeProviderTypes.d.ts.map +1 -0
  88. package/dist/runtime/agentRuntimeProviderTypes.js +2 -0
  89. package/dist/runtime/agentRuntimeProviderTypes.js.map +1 -0
  90. package/dist/runtime/conversationRuntime.d.ts +53 -0
  91. package/dist/runtime/conversationRuntime.d.ts.map +1 -0
  92. package/dist/runtime/conversationRuntime.js +207 -0
  93. package/dist/runtime/conversationRuntime.js.map +1 -0
  94. package/dist/runtime/legacyAgentRuntimeEvents.d.ts +65 -0
  95. package/dist/runtime/legacyAgentRuntimeEvents.d.ts.map +1 -0
  96. package/dist/runtime/legacyAgentRuntimeEvents.js +104 -0
  97. package/dist/runtime/legacyAgentRuntimeEvents.js.map +1 -0
  98. package/dist/runtimeProjection.d.ts +19 -0
  99. package/dist/runtimeProjection.d.ts.map +1 -0
  100. package/dist/runtimeProjection.js +133 -0
  101. package/dist/runtimeProjection.js.map +1 -0
  102. package/dist/sessionBoardProjection.d.ts +84 -0
  103. package/dist/sessionBoardProjection.d.ts.map +1 -0
  104. package/dist/sessionBoardProjection.js +103 -0
  105. package/dist/sessionBoardProjection.js.map +1 -0
  106. package/dist/sessionMode.d.ts +115 -0
  107. package/dist/sessionMode.d.ts.map +1 -0
  108. package/dist/sessionMode.js +98 -0
  109. package/dist/sessionMode.js.map +1 -0
  110. package/dist/workspace/workspaceSelectionContinuation.d.ts +8 -0
  111. package/dist/workspace/workspaceSelectionContinuation.d.ts.map +1 -0
  112. package/dist/workspace/workspaceSelectionContinuation.js +18 -0
  113. package/dist/workspace/workspaceSelectionContinuation.js.map +1 -0
  114. package/dist/workspaceKnowledge.d.ts +90 -0
  115. package/dist/workspaceKnowledge.d.ts.map +1 -0
  116. package/dist/workspaceKnowledge.js +103 -0
  117. package/dist/workspaceKnowledge.js.map +1 -0
  118. package/dist/writeLease.d.ts +92 -0
  119. package/dist/writeLease.d.ts.map +1 -0
  120. package/dist/writeLease.js +108 -0
  121. package/dist/writeLease.js.map +1 -0
  122. package/package.json +29 -0
@@ -0,0 +1,84 @@
1
+ /**
2
+ * What a session surface may SHOW โ€” ADE ยง5.5 attach and takeover.
3
+ *
4
+ * `session.list` answers what exists; this decides what a person is told about
5
+ * their own relationship to each session, and what they may do about it. Pure,
6
+ * in `core`, for the reason `reviewProjection` and `fleetBoardProjection` are:
7
+ * an honesty rule written in JSX is enforced by whoever writes the next
8
+ * component.
9
+ *
10
+ * ## ๐Ÿ”ด The lease has THREE states, not two
11
+ *
12
+ * "Locked" is not enough. *You* hold it, *another human* holds it, or the
13
+ * *agent* holds it โ€” and each implies a different action: keep typing, go find a
14
+ * colleague, or take over. A surface that renders the first two the same way
15
+ * tells one person their keystrokes are landing when they are being refused.
16
+ *
17
+ * ## Taking over is ADVICE here, never the decision
18
+ *
19
+ * `canTakeOver` exists so a button can be disabled, and that is all. The host
20
+ * arbitrates, and a surface that treated this as the gate would be a second
21
+ * implementation of the arbitration โ€” which is how the two come to disagree,
22
+ * always in the direction of the optimistic one.
23
+ */
24
+ /** Mirrors `AgentSessionSummary` on the wire, redeclared so `core` stays free of
25
+ * the contract package in the direction that matters. */
26
+ export interface SessionBoardInput {
27
+ sessionId: string;
28
+ runId: string;
29
+ mode: string;
30
+ switchable: boolean;
31
+ hasProtocolChannel: boolean;
32
+ openedAt: number;
33
+ viewers: string[];
34
+ lease: {
35
+ holder: string | null;
36
+ heldSince: number | null;
37
+ interventions: number;
38
+ };
39
+ }
40
+ export type SessionLeaseRelation = 'agent' | 'you' | 'other-human';
41
+ export interface SessionBoardRow {
42
+ sessionId: string;
43
+ runId: string;
44
+ mode: string;
45
+ /** Who may write, relative to the person looking at this. */
46
+ lease: SessionLeaseRelation;
47
+ /** The other human's id, when one holds the lease. Named, never "someone". */
48
+ heldBy?: string;
49
+ /** How many times a human has taken this session over, ever. */
50
+ interventions: number;
51
+ viewers: number;
52
+ /** True when the person looking is one of them. */
53
+ youAreWatching: boolean;
54
+ /** Someone ELSE is watching. Worth knowing before you type into a terminal. */
55
+ othersWatching: number;
56
+ /** Advice for enabling a control โ€” the host still arbitrates. */
57
+ canTakeOver: boolean;
58
+ canRelease: boolean;
59
+ /** One line a person can act on. */
60
+ headline: string;
61
+ }
62
+ export interface SessionBoard {
63
+ rows: SessionBoardRow[];
64
+ notice?: string;
65
+ }
66
+ export declare function projectSessionBoard(sessions: SessionBoardInput[], viewerId: string): SessionBoard;
67
+ /**
68
+ * What to say about a snapshot of terminal output.
69
+ *
70
+ * ๐Ÿ”ด Truncation and emptiness are different, and neither is an error. Output
71
+ * that begins mid-sentence with no explanation reads as corruption; an empty
72
+ * terminal for a session that has genuinely printed nothing is just the truth.
73
+ * Only `available: false` means something went wrong.
74
+ */
75
+ export declare function describeSessionOutput(snapshot: {
76
+ available: boolean;
77
+ output: string;
78
+ truncated: boolean;
79
+ reason?: string;
80
+ }): {
81
+ text: string;
82
+ notice?: string;
83
+ };
84
+ //# sourceMappingURL=sessionBoardProjection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionBoardProjection.d.ts","sourceRoot":"","sources":["../src/sessionBoardProjection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;0DAC0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,OAAO,CAAA;IACnB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAA;CAClF;AAED,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,KAAK,GAAG,aAAa,CAAA;AAElE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,KAAK,EAAE,oBAAoB,CAAA;IAC3B,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,mDAAmD;IACnD,cAAc,EAAE,OAAO,CAAA;IACvB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAA;IACtB,iEAAiE;IACjE,WAAW,EAAE,OAAO,CAAA;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,EAAE,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,QAAQ,EAAE,MAAM,GACf,YAAY,CAgDd;AAcD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE;IAC9C,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAapC"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * What a session surface may SHOW โ€” ADE ยง5.5 attach and takeover.
3
+ *
4
+ * `session.list` answers what exists; this decides what a person is told about
5
+ * their own relationship to each session, and what they may do about it. Pure,
6
+ * in `core`, for the reason `reviewProjection` and `fleetBoardProjection` are:
7
+ * an honesty rule written in JSX is enforced by whoever writes the next
8
+ * component.
9
+ *
10
+ * ## ๐Ÿ”ด The lease has THREE states, not two
11
+ *
12
+ * "Locked" is not enough. *You* hold it, *another human* holds it, or the
13
+ * *agent* holds it โ€” and each implies a different action: keep typing, go find a
14
+ * colleague, or take over. A surface that renders the first two the same way
15
+ * tells one person their keystrokes are landing when they are being refused.
16
+ *
17
+ * ## Taking over is ADVICE here, never the decision
18
+ *
19
+ * `canTakeOver` exists so a button can be disabled, and that is all. The host
20
+ * arbitrates, and a surface that treated this as the gate would be a second
21
+ * implementation of the arbitration โ€” which is how the two come to disagree,
22
+ * always in the direction of the optimistic one.
23
+ */
24
+ export function projectSessionBoard(sessions, viewerId) {
25
+ const rows = sessions.map((session) => {
26
+ const lease = session.lease.holder === null
27
+ ? 'agent'
28
+ : session.lease.holder === viewerId
29
+ ? 'you'
30
+ : 'other-human';
31
+ const youAreWatching = session.viewers.includes(viewerId);
32
+ const othersWatching = session.viewers.filter((viewer) => viewer !== viewerId).length;
33
+ return {
34
+ sessionId: session.sessionId,
35
+ runId: session.runId,
36
+ mode: session.mode,
37
+ lease,
38
+ ...(lease === 'other-human' && session.lease.holder
39
+ ? { heldBy: session.lease.holder }
40
+ : {}),
41
+ interventions: session.lease.interventions,
42
+ viewers: session.viewers.length,
43
+ youAreWatching,
44
+ othersWatching,
45
+ // ๐Ÿ”ด Refused only when ANOTHER human holds it. The agent holding the lease
46
+ // is the ordinary case that takeover exists for, and a surface that
47
+ // disabled the control there would remove the feature.
48
+ canTakeOver: lease !== 'other-human',
49
+ canRelease: lease === 'you',
50
+ headline: headlineFor(lease, session),
51
+ };
52
+ });
53
+ // Newest first. A session list is read to find what is happening NOW, and the
54
+ // most recently opened session is the one most likely to be it.
55
+ rows.sort((left, right) => {
56
+ const leftAt = sessions.find((session) => session.sessionId === left.sessionId)?.openedAt ?? 0;
57
+ const rightAt = sessions.find((session) => session.sessionId === right.sessionId)?.openedAt ?? 0;
58
+ return rightAt === leftAt ? left.sessionId.localeCompare(right.sessionId) : rightAt - leftAt;
59
+ });
60
+ const contended = rows.filter((row) => row.lease === 'other-human').length;
61
+ return {
62
+ rows,
63
+ ...(contended > 0
64
+ ? {
65
+ notice: `${contended} session${contended === 1 ? ' is' : 's are'} being typed into by someone else. Your keystrokes there will be refused.`,
66
+ }
67
+ : {}),
68
+ };
69
+ }
70
+ function headlineFor(lease, session) {
71
+ if (lease === 'you') {
72
+ return 'You are typing. The agent cannot write until you hand it back.';
73
+ }
74
+ if (lease === 'other-human') {
75
+ return `${session.lease.holder} is typing in this session.`;
76
+ }
77
+ return session.lease.interventions > 0
78
+ ? `The agent is driving. Taken over ${session.lease.interventions} time${session.lease.interventions === 1 ? '' : 's'} so far.`
79
+ : 'The agent is driving.';
80
+ }
81
+ /**
82
+ * What to say about a snapshot of terminal output.
83
+ *
84
+ * ๐Ÿ”ด Truncation and emptiness are different, and neither is an error. Output
85
+ * that begins mid-sentence with no explanation reads as corruption; an empty
86
+ * terminal for a session that has genuinely printed nothing is just the truth.
87
+ * Only `available: false` means something went wrong.
88
+ */
89
+ export function describeSessionOutput(snapshot) {
90
+ if (!snapshot.available) {
91
+ return { text: '', notice: snapshot.reason ?? 'This session could not be read.' };
92
+ }
93
+ if (snapshot.output.length === 0) {
94
+ return { text: '', notice: 'This session has printed nothing yet.' };
95
+ }
96
+ return {
97
+ text: snapshot.output,
98
+ ...(snapshot.truncated
99
+ ? { notice: 'Earlier output has been dropped โ€” this is the most recent part only.' }
100
+ : {}),
101
+ };
102
+ }
103
+ //# sourceMappingURL=sessionBoardProjection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionBoardProjection.js","sourceRoot":"","sources":["../src/sessionBoardProjection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AA4CH,MAAM,UAAU,mBAAmB,CACjC,QAA6B,EAC7B,QAAgB;IAEhB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAmB,EAAE;QACrD,MAAM,KAAK,GAAyB,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI;YAC/D,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ;gBACjC,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,aAAa,CAAA;QACnB,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACzD,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAA;QAErF,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK;YACL,GAAG,CAAC,KAAK,KAAK,aAAa,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM;gBACjD,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE;gBAClC,CAAC,CAAC,EAAE,CAAC;YACP,aAAa,EAAE,OAAO,CAAC,KAAK,CAAC,aAAa;YAC1C,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM;YAC/B,cAAc;YACd,cAAc;YACd,2EAA2E;YAC3E,oEAAoE;YACpE,uDAAuD;YACvD,WAAW,EAAE,KAAK,KAAK,aAAa;YACpC,UAAU,EAAE,KAAK,KAAK,KAAK;YAC3B,QAAQ,EAAE,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC;SACtC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,8EAA8E;IAC9E,gEAAgE;IAChE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACxB,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,IAAI,CAAC,CAAA;QAC9F,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,CAAC,EAAE,QAAQ,IAAI,CAAC,CAAA;QAChG,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,MAAM,CAAA;IAC9F,CAAC,CAAC,CAAA;IAEF,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,aAAa,CAAC,CAAC,MAAM,CAAA;IAC1E,OAAO;QACL,IAAI;QACJ,GAAG,CAAC,SAAS,GAAG,CAAC;YACf,CAAC,CAAC;gBACE,MAAM,EAAE,GAAG,SAAS,WAAW,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,2EAA2E;aAC5I;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAA2B,EAAE,OAA0B;IAC1E,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QACpB,OAAO,gEAAgE,CAAA;IACzE,CAAC;IACD,IAAI,KAAK,KAAK,aAAa,EAAE,CAAC;QAC5B,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,6BAA6B,CAAA;IAC7D,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC;QACpC,CAAC,CAAC,oCAAoC,OAAO,CAAC,KAAK,CAAC,aAAa,QAAQ,OAAO,CAAC,KAAK,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU;QAC/H,CAAC,CAAC,uBAAuB,CAAA;AAC7B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAKrC;IACC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,iCAAiC,EAAE,CAAA;IACnF,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,uCAAuC,EAAE,CAAA;IACtE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,MAAM;QACrB,GAAG,CAAC,QAAQ,CAAC,SAAS;YACpB,CAAC,CAAC,EAAE,MAAM,EAAE,sEAAsE,EAAE;YACpF,CAAC,CAAC,EAAE,CAAC;KACR,CAAA;AACH,CAAC"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Session render mode and input routing โ€” ADE spec ยง2.8.
3
+ *
4
+ * โœ… CONSUMED since 2026-08-13 by `host/session/AgentSessionService`, the ยง2.8
5
+ * substrate these rules were written for. It carried an `@unwired-by-design`
6
+ * marker until that consumer existed; wiring it was the point, so the marker is
7
+ * gone rather than updated.
8
+ *
9
+ * ## 1. The modes are not simultaneous
10
+ *
11
+ * ยง2.8: "The two modes are not simultaneous for one process: a CLI in
12
+ * interactive TUI mode is not also serving ACP. Where an agent supports both,
13
+ * the user switches."
14
+ *
15
+ * So selection returns exactly ONE mode. An agent that supports both is
16
+ * *switchable*, which is a different statement from *running both* โ€” and a
17
+ * caller handed `{nativeTui: true, acp: true}` would otherwise be free to
18
+ * believe the second one.
19
+ *
20
+ * ## 2. Typing never falls into a void
21
+ *
22
+ * ยง2.8: "Input is routed by the host: mid-turn steering where the agent accepts
23
+ * it, queued as the next turn where it does not. Typing never falls into a void,
24
+ * and human input is always recorded as a human intervention."
25
+ *
26
+ * `InputRouting` has no `drop` case. Not "we decided not to drop input" โ€” there
27
+ * is no value that means it, so a caller cannot silently discard a keystroke and
28
+ * a future contributor cannot add that path without changing this type. Every
29
+ * outcome is also `recordedAs: 'human-intervention'`, because ยง2.8 says human
30
+ * input is ALWAYS recorded as one, and an unrecorded intervention is a change in
31
+ * the run that the timeline cannot explain.
32
+ */
33
+ /** What renders into the session's PTY. */
34
+ export type SessionRenderMode = 'native-tui' | 'acp';
35
+ /** What an agent is capable of, not what it is doing. */
36
+ export interface AgentRenderSupport {
37
+ /** The agent ships its own interactive TUI (Claude Code, Codex). */
38
+ nativeTui: boolean;
39
+ /** The agent can be driven headless over the protocol. */
40
+ acp: boolean;
41
+ }
42
+ export type SessionModeSelection = {
43
+ ok: true;
44
+ mode: SessionRenderMode;
45
+ /** True when the user may switch; ยง2.8 switching, never simultaneity. */
46
+ switchable: boolean;
47
+ reason: string;
48
+ } | {
49
+ ok: false;
50
+ reason: string;
51
+ };
52
+ /**
53
+ * Chooses the mode a session runs in.
54
+ *
55
+ * ยง2.8: "For a third-party agent with a good TUI, `native-tui` is the default
56
+ * and the right answer. Their interface is the product they built; reproducing
57
+ * it from protocol events yields a worse imitation of something a vendor
58
+ * invested years in, and it rots every time they ship an improvement."
59
+ *
60
+ * An agent supporting neither is a REFUSAL, not a fallback. Quietly picking
61
+ * `acp` for an agent that cannot serve it produces a session that renders
62
+ * nothing and reports no error โ€” the failure mode where a caller believes it has
63
+ * a working terminal.
64
+ */
65
+ export declare function selectSessionRenderMode(support: AgentRenderSupport, preference?: SessionRenderMode): SessionModeSelection;
66
+ /**
67
+ * Where a keystroke goes.
68
+ *
69
+ * There is deliberately no `drop`. ยง2.8 is unambiguous that typing never falls
70
+ * into a void, and the strongest way to hold that is to leave no value that
71
+ * could express it.
72
+ */
73
+ export type InputRouting = {
74
+ disposition: 'steer';
75
+ recordedAs: 'human-intervention';
76
+ } | {
77
+ disposition: 'queue';
78
+ recordedAs: 'human-intervention';
79
+ reason: string;
80
+ };
81
+ export interface InputRoutingContext {
82
+ /** True while the agent is mid-turn. */
83
+ turnInFlight: boolean;
84
+ /** Whether this agent accepts input during a turn. Assumption 3 PROVED this
85
+ * is achievable through a PTY we own โ€” see docs/evidence/PTY_STEERING_2026-08-11.md
86
+ * โ€” but not every agent accepts it, and claiming otherwise for one that does
87
+ * not would lose the input we promised never to lose. */
88
+ acceptsMidTurnSteering: boolean;
89
+ }
90
+ /**
91
+ * Where the keystrokes physically GO once routing has decided to steer.
92
+ *
93
+ * ๐Ÿ”ด Routing and delivery are different questions, and conflating them put
94
+ * typing into exactly the void `InputRouting` was shaped to forbid.
95
+ *
96
+ * In `native-tui` the PTY is the agent's own terminal: writing to it IS the
97
+ * steer, and it has happened by the time the call returns. In `acp` there is no
98
+ * process behind the PTY at all โ€” it is a render target for the structured
99
+ * stream โ€” so a write there reaches nobody. The steer has to travel the way
100
+ * every other hostโ†’agent instruction travels, through `turn.steer`, which the
101
+ * caller owns because that is where acknowledgement and idempotency live.
102
+ *
103
+ * So a caller cannot act on the disposition alone: doing the right thing for one
104
+ * mode is either a double-delivery or a dropped keystroke in the other. It has
105
+ * to be told which sink was used.
106
+ */
107
+ export type InputSink = 'pty' | 'turn.steer' | 'turn.queue';
108
+ export interface InputDelivery {
109
+ /** True when the session has ALREADY put the keystrokes in front of the agent. */
110
+ delivered: boolean;
111
+ sink: InputSink;
112
+ }
113
+ export declare function deliveryFor(mode: SessionRenderMode, routing: InputRouting): InputDelivery;
114
+ export declare function routeHumanInput(context: InputRoutingContext): InputRouting;
115
+ //# sourceMappingURL=sessionMode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionMode.d.ts","sourceRoot":"","sources":["../src/sessionMode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,2CAA2C;AAC3C,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,KAAK,CAAA;AAEpD,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAA;IAClB,0DAA0D;IAC1D,GAAG,EAAE,OAAO,CAAA;CACb;AAED,MAAM,MAAM,oBAAoB,GAC5B;IACE,EAAE,EAAE,IAAI,CAAA;IACR,IAAI,EAAE,iBAAiB,CAAA;IACvB,yEAAyE;IACzE,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjC;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,kBAAkB,EAC3B,UAAU,CAAC,EAAE,iBAAiB,GAC7B,oBAAoB,CAwCtB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,oBAAoB,CAAA;CAAE,GAC1D;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9E,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,YAAY,EAAE,OAAO,CAAA;IACrB;;;8DAG0D;IAC1D,sBAAsB,EAAE,OAAO,CAAA;CAChC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,YAAY,GAAG,YAAY,CAAA;AAE3D,MAAM,WAAW,aAAa;IAC5B,kFAAkF;IAClF,SAAS,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;CAChB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,YAAY,GAAG,aAAa,CAKzF;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAS1E"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Session render mode and input routing โ€” ADE spec ยง2.8.
3
+ *
4
+ * โœ… CONSUMED since 2026-08-13 by `host/session/AgentSessionService`, the ยง2.8
5
+ * substrate these rules were written for. It carried an `@unwired-by-design`
6
+ * marker until that consumer existed; wiring it was the point, so the marker is
7
+ * gone rather than updated.
8
+ *
9
+ * ## 1. The modes are not simultaneous
10
+ *
11
+ * ยง2.8: "The two modes are not simultaneous for one process: a CLI in
12
+ * interactive TUI mode is not also serving ACP. Where an agent supports both,
13
+ * the user switches."
14
+ *
15
+ * So selection returns exactly ONE mode. An agent that supports both is
16
+ * *switchable*, which is a different statement from *running both* โ€” and a
17
+ * caller handed `{nativeTui: true, acp: true}` would otherwise be free to
18
+ * believe the second one.
19
+ *
20
+ * ## 2. Typing never falls into a void
21
+ *
22
+ * ยง2.8: "Input is routed by the host: mid-turn steering where the agent accepts
23
+ * it, queued as the next turn where it does not. Typing never falls into a void,
24
+ * and human input is always recorded as a human intervention."
25
+ *
26
+ * `InputRouting` has no `drop` case. Not "we decided not to drop input" โ€” there
27
+ * is no value that means it, so a caller cannot silently discard a keystroke and
28
+ * a future contributor cannot add that path without changing this type. Every
29
+ * outcome is also `recordedAs: 'human-intervention'`, because ยง2.8 says human
30
+ * input is ALWAYS recorded as one, and an unrecorded intervention is a change in
31
+ * the run that the timeline cannot explain.
32
+ */
33
+ /**
34
+ * Chooses the mode a session runs in.
35
+ *
36
+ * ยง2.8: "For a third-party agent with a good TUI, `native-tui` is the default
37
+ * and the right answer. Their interface is the product they built; reproducing
38
+ * it from protocol events yields a worse imitation of something a vendor
39
+ * invested years in, and it rots every time they ship an improvement."
40
+ *
41
+ * An agent supporting neither is a REFUSAL, not a fallback. Quietly picking
42
+ * `acp` for an agent that cannot serve it produces a session that renders
43
+ * nothing and reports no error โ€” the failure mode where a caller believes it has
44
+ * a working terminal.
45
+ */
46
+ export function selectSessionRenderMode(support, preference) {
47
+ const switchable = support.nativeTui && support.acp;
48
+ if (!support.nativeTui && !support.acp) {
49
+ return {
50
+ ok: false,
51
+ reason: 'the agent declares neither a native TUI nor ACP, so nothing can render into its session',
52
+ };
53
+ }
54
+ if (preference) {
55
+ const supported = preference === 'native-tui' ? support.nativeTui : support.acp;
56
+ if (!supported) {
57
+ // Honouring an impossible preference silently would hand back a mode the
58
+ // agent cannot serve; refusing names which half is missing.
59
+ return {
60
+ ok: false,
61
+ reason: `the agent does not support ${preference}`,
62
+ };
63
+ }
64
+ return {
65
+ ok: true,
66
+ mode: preference,
67
+ switchable,
68
+ reason: 'explicit user preference',
69
+ };
70
+ }
71
+ if (support.nativeTui) {
72
+ return {
73
+ ok: true,
74
+ mode: 'native-tui',
75
+ switchable,
76
+ reason: "the agent's own TUI is the product its vendor built; rendering it from protocol events would be a worse imitation that rots on every upstream release",
77
+ };
78
+ }
79
+ return { ok: true, mode: 'acp', switchable, reason: 'the agent is headless-only' };
80
+ }
81
+ export function deliveryFor(mode, routing) {
82
+ if (routing.disposition === 'queue')
83
+ return { delivered: false, sink: 'turn.queue' };
84
+ return mode === 'native-tui'
85
+ ? { delivered: true, sink: 'pty' }
86
+ : { delivered: false, sink: 'turn.steer' };
87
+ }
88
+ export function routeHumanInput(context) {
89
+ if (context.turnInFlight && !context.acceptsMidTurnSteering) {
90
+ return {
91
+ disposition: 'queue',
92
+ recordedAs: 'human-intervention',
93
+ reason: 'the agent does not accept input mid-turn; delivered as the next turn',
94
+ };
95
+ }
96
+ return { disposition: 'steer', recordedAs: 'human-intervention' };
97
+ }
98
+ //# sourceMappingURL=sessionMode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionMode.js","sourceRoot":"","sources":["../src/sessionMode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAuBH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAA2B,EAC3B,UAA8B;IAE9B,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAA;IAEnD,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACvC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EACJ,yFAAyF;SAC5F,CAAA;IACH,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,UAAU,KAAK,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAA;QAC/E,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,yEAAyE;YACzE,4DAA4D;YAC5D,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,8BAA8B,UAAU,EAAE;aACnD,CAAA;QACH,CAAC;QACD,OAAO;YACL,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,UAAU;YAChB,UAAU;YACV,MAAM,EAAE,0BAA0B;SACnC,CAAA;IACH,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,OAAO;YACL,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,YAAY;YAClB,UAAU;YACV,MAAM,EACJ,uJAAuJ;SAC1J,CAAA;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAA;AACpF,CAAC;AAgDD,MAAM,UAAU,WAAW,CAAC,IAAuB,EAAE,OAAqB;IACxE,IAAI,OAAO,CAAC,WAAW,KAAK,OAAO;QAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;IACpF,OAAO,IAAI,KAAK,YAAY;QAC1B,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE;QAClC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;AAC9C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAA4B;IAC1D,IAAI,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC;QAC5D,OAAO;YACL,WAAW,EAAE,OAAO;YACpB,UAAU,EAAE,oBAAoB;YAChC,MAAM,EAAE,sEAAsE;SAC/E,CAAA;IACH,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAA;AACnE,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type WorkspaceSelectionChoice = 'inbox' | 'reuse' | 'create';
2
+ export interface WorkspaceSelectionContinuationInput {
3
+ choice: WorkspaceSelectionChoice;
4
+ directory: string;
5
+ result: string;
6
+ }
7
+ export declare function buildWorkspaceSelectionContinuationPrompt(input: WorkspaceSelectionContinuationInput): string;
8
+ //# sourceMappingURL=workspaceSelectionContinuation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceSelectionContinuation.d.ts","sourceRoot":"","sources":["../../src/workspace/workspaceSelectionContinuation.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEnE,MAAM,WAAW,mCAAmC;IAClD,MAAM,EAAE,wBAAwB,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,yCAAyC,CACvD,KAAK,EAAE,mCAAmC,GACzC,MAAM,CAiBR"}
@@ -0,0 +1,18 @@
1
+ export function buildWorkspaceSelectionContinuationPrompt(input) {
2
+ const payload = JSON.stringify({
3
+ type: 'workspace_selection.completed',
4
+ status: 'completed',
5
+ choice: input.choice,
6
+ directory: input.directory,
7
+ result: input.result,
8
+ });
9
+ return [
10
+ 'This is an internal XENO Hub continuation event, not a new user request.',
11
+ '<xeno_workspace_selection_result>',
12
+ payload,
13
+ '</xeno_workspace_selection_result>',
14
+ 'Acknowledge the completed workspace-placement result naturally and briefly.',
15
+ 'Do not call tools, ask the user to choose again, repeat the available choices, or restart the original request.',
16
+ ].join('\n');
17
+ }
18
+ //# sourceMappingURL=workspaceSelectionContinuation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceSelectionContinuation.js","sourceRoot":"","sources":["../../src/workspace/workspaceSelectionContinuation.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,yCAAyC,CACvD,KAA0C;IAE1C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,IAAI,EAAE,+BAA+B;QACrC,MAAM,EAAE,WAAW;QACnB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAA;IAEF,OAAO;QACL,0EAA0E;QAC1E,mCAAmC;QACnC,OAAO;QACP,oCAAoC;QACpC,6EAA6E;QAC7E,iHAAiH;KAClH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Workspace knowledge โ€” ADE ยง5.8 LEARN.
3
+ *
4
+ * The workspace getting better at *this* codebase over time, without the user
5
+ * re-explaining it every session.
6
+ *
7
+ * ## ๐Ÿ”ด The gate is CROSS-PROVIDER, and that is the whole design
8
+ *
9
+ * ยง5.8: *"a fact established in one run is available to a different provider in
10
+ * a later run without the user restating it."*
11
+ *
12
+ * So provenance is RECORDED and never CONSULTED for selection. A fact learned
13
+ * by Claude must reach a GPT run, and an implementation that filtered by
14
+ * provider โ€” even reasonably, even to avoid "contaminating" a lane โ€” would pass
15
+ * every test written from the inside and fail the one property the pillar
16
+ * exists for. Selection here does not receive a provider id at all; that is the
17
+ * simplest way to make the mistake unrepresentable.
18
+ *
19
+ * ## Boundary
20
+ *
21
+ * This is *workspace* knowledge โ€” conventions, architecture, prior decisions.
22
+ * Agent-owned earned memory (the Soul model) belongs to `xeno-anima`. A fact
23
+ * here describes the CODEBASE, not the agent.
24
+ *
25
+ * ## Superseded facts are kept, and not injected
26
+ *
27
+ * "We use npm" then "we moved to pnpm" must not both reach a prompt: an agent
28
+ * given both will pick one at random and be right half the time. The later fact
29
+ * about a subject wins. The earlier one stays in the record, because "when did
30
+ * this change, and who decided?" is a question people actually ask.
31
+ */
32
+ export interface KnowledgeProvenance {
33
+ /** The run that established it โ€” so "why does it think that?" is answerable. */
34
+ runId: string;
35
+ /** RECORDED for provenance. Never used to decide what a later run sees. */
36
+ providerId?: string;
37
+ at: number;
38
+ }
39
+ export interface WorkspaceKnowledgeEntry {
40
+ id: string;
41
+ workspaceId: string;
42
+ /**
43
+ * What the fact is ABOUT โ€” `build.package-manager`, `testing.framework`.
44
+ * Supersession is per subject, so this is what makes "we moved to pnpm"
45
+ * replace "we use npm" rather than sit beside it.
46
+ */
47
+ subject: string;
48
+ fact: string;
49
+ /**
50
+ * Always included, regardless of budget. For foundational conventions that
51
+ * stop being followed the moment they fall out of a prompt.
52
+ */
53
+ pinned?: boolean;
54
+ provenance: KnowledgeProvenance;
55
+ }
56
+ export interface KnowledgeSelection {
57
+ /** What should go into the prompt, in the order it should appear. */
58
+ entries: WorkspaceKnowledgeEntry[];
59
+ /** Facts left out for budget. Named, never silently dropped. */
60
+ omitted: Array<{
61
+ subject: string;
62
+ reason: string;
63
+ }>;
64
+ /** Superseded by a later fact about the same subject. Kept for the record. */
65
+ superseded: WorkspaceKnowledgeEntry[];
66
+ /** True when everything current fitted. */
67
+ complete: boolean;
68
+ }
69
+ export interface KnowledgeSelectionOptions {
70
+ /**
71
+ * Rough character budget for the injected block.
72
+ *
73
+ * Characters rather than tokens on purpose: a token count needs a tokenizer
74
+ * per provider, and this must not vary by provider โ€” see the header. Characters
75
+ * are provider-neutral and wrong by a constant factor, which a caller can size
76
+ * around.
77
+ */
78
+ maxChars?: number;
79
+ }
80
+ /**
81
+ * Chooses which facts reach a prompt.
82
+ *
83
+ * ๐Ÿ”ด Takes NO provider argument. See the header: the gate is that a fact crosses
84
+ * provider lanes, and a signature that cannot express "filter by provider"
85
+ * cannot accidentally do it.
86
+ */
87
+ export declare function selectWorkspaceKnowledge(entries: readonly WorkspaceKnowledgeEntry[], options?: KnowledgeSelectionOptions): KnowledgeSelection;
88
+ /** Renders the selection as the block that goes into a prompt. */
89
+ export declare function renderWorkspaceKnowledge(selection: KnowledgeSelection): string;
90
+ //# sourceMappingURL=workspaceKnowledge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceKnowledge.d.ts","sourceRoot":"","sources":["../src/workspaceKnowledge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,MAAM,WAAW,mBAAmB;IAClC,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAA;IACb,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,mBAAmB,CAAA;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,OAAO,EAAE,uBAAuB,EAAE,CAAA;IAClC,gEAAgE;IAChE,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACnD,8EAA8E;IAC9E,UAAU,EAAE,uBAAuB,EAAE,CAAA;IACrC,2CAA2C;IAC3C,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAID;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,uBAAuB,EAAE,EAC3C,OAAO,GAAE,yBAA8B,GACtC,kBAAkB,CAsDpB;AAED,kEAAkE;AAClE,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,kBAAkB,GAAG,MAAM,CAS9E"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Workspace knowledge โ€” ADE ยง5.8 LEARN.
3
+ *
4
+ * The workspace getting better at *this* codebase over time, without the user
5
+ * re-explaining it every session.
6
+ *
7
+ * ## ๐Ÿ”ด The gate is CROSS-PROVIDER, and that is the whole design
8
+ *
9
+ * ยง5.8: *"a fact established in one run is available to a different provider in
10
+ * a later run without the user restating it."*
11
+ *
12
+ * So provenance is RECORDED and never CONSULTED for selection. A fact learned
13
+ * by Claude must reach a GPT run, and an implementation that filtered by
14
+ * provider โ€” even reasonably, even to avoid "contaminating" a lane โ€” would pass
15
+ * every test written from the inside and fail the one property the pillar
16
+ * exists for. Selection here does not receive a provider id at all; that is the
17
+ * simplest way to make the mistake unrepresentable.
18
+ *
19
+ * ## Boundary
20
+ *
21
+ * This is *workspace* knowledge โ€” conventions, architecture, prior decisions.
22
+ * Agent-owned earned memory (the Soul model) belongs to `xeno-anima`. A fact
23
+ * here describes the CODEBASE, not the agent.
24
+ *
25
+ * ## Superseded facts are kept, and not injected
26
+ *
27
+ * "We use npm" then "we moved to pnpm" must not both reach a prompt: an agent
28
+ * given both will pick one at random and be right half the time. The later fact
29
+ * about a subject wins. The earlier one stays in the record, because "when did
30
+ * this change, and who decided?" is a question people actually ask.
31
+ */
32
+ const DEFAULT_MAX_CHARS = 4_000;
33
+ /**
34
+ * Chooses which facts reach a prompt.
35
+ *
36
+ * ๐Ÿ”ด Takes NO provider argument. See the header: the gate is that a fact crosses
37
+ * provider lanes, and a signature that cannot express "filter by provider"
38
+ * cannot accidentally do it.
39
+ */
40
+ export function selectWorkspaceKnowledge(entries, options = {}) {
41
+ const maxChars = options.maxChars ?? DEFAULT_MAX_CHARS;
42
+ // Latest per subject wins. Ties go to the later id so the choice is stable
43
+ // rather than dependent on input order.
44
+ const currentBySubject = new Map();
45
+ const superseded = [];
46
+ for (const entry of [...entries].sort((left, right) => left.provenance.at === right.provenance.at
47
+ ? left.id.localeCompare(right.id)
48
+ : left.provenance.at - right.provenance.at)) {
49
+ const existing = currentBySubject.get(entry.subject);
50
+ if (existing)
51
+ superseded.push(existing);
52
+ currentBySubject.set(entry.subject, entry);
53
+ }
54
+ const current = [...currentBySubject.values()];
55
+ // Pinned first, then newest. Pinned exists because a foundational convention
56
+ // is usually the OLDEST fact on record, and a pure recency order drops exactly
57
+ // those first โ€” the conventions stop being followed and nobody knows why.
58
+ const ordered = current.sort((left, right) => {
59
+ if (Boolean(left.pinned) !== Boolean(right.pinned))
60
+ return left.pinned ? -1 : 1;
61
+ return right.provenance.at - left.provenance.at;
62
+ });
63
+ const selected = [];
64
+ const omitted = [];
65
+ let used = 0;
66
+ for (const entry of ordered) {
67
+ const cost = entry.subject.length + entry.fact.length + 2;
68
+ // Pinned bypasses the budget rather than competing for it. A budget that
69
+ // could drop a pinned convention would make `pinned` a suggestion.
70
+ if (entry.pinned || used + cost <= maxChars) {
71
+ selected.push(entry);
72
+ used += cost;
73
+ continue;
74
+ }
75
+ omitted.push({
76
+ subject: entry.subject,
77
+ reason: 'left out of this prompt for space',
78
+ });
79
+ }
80
+ return {
81
+ entries: selected,
82
+ omitted,
83
+ superseded,
84
+ // ๐Ÿ”ด Complete means every CURRENT fact was included. A prompt missing
85
+ // knowledge makes an agent look like it forgot, with nothing on screen to
86
+ // explain why โ€” so the omission is reported rather than inferred from a
87
+ // shorter block nobody counted.
88
+ complete: omitted.length === 0,
89
+ };
90
+ }
91
+ /** Renders the selection as the block that goes into a prompt. */
92
+ export function renderWorkspaceKnowledge(selection) {
93
+ if (selection.entries.length === 0)
94
+ return '';
95
+ const lines = selection.entries.map((entry) => `- ${entry.subject}: ${entry.fact}`);
96
+ if (!selection.complete) {
97
+ // Stated IN the prompt, not only to the surface: the agent should know its
98
+ // context was trimmed, so it can ask rather than assume.
99
+ lines.push(`- (${selection.omitted.length} further fact(s) omitted for space)`);
100
+ }
101
+ return lines.join('\n');
102
+ }
103
+ //# sourceMappingURL=workspaceKnowledge.js.map