@gridlock/orchestrator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/LICENSE +21 -0
  2. package/dist/AgentRoute.d.ts +44 -0
  3. package/dist/AgentRoute.d.ts.map +1 -0
  4. package/dist/AgentRoute.js +54 -0
  5. package/dist/AgentRoute.js.map +1 -0
  6. package/dist/CommandRegistry.d.ts +68 -0
  7. package/dist/CommandRegistry.d.ts.map +1 -0
  8. package/dist/CommandRegistry.js +87 -0
  9. package/dist/CommandRegistry.js.map +1 -0
  10. package/dist/ContextFactory.d.ts +62 -0
  11. package/dist/ContextFactory.d.ts.map +1 -0
  12. package/dist/ContextFactory.js +59 -0
  13. package/dist/ContextFactory.js.map +1 -0
  14. package/dist/DialogueGate.d.ts +117 -0
  15. package/dist/DialogueGate.d.ts.map +1 -0
  16. package/dist/DialogueGate.js +101 -0
  17. package/dist/DialogueGate.js.map +1 -0
  18. package/dist/DisclosureEngine.d.ts +160 -0
  19. package/dist/DisclosureEngine.d.ts.map +1 -0
  20. package/dist/DisclosureEngine.js +241 -0
  21. package/dist/DisclosureEngine.js.map +1 -0
  22. package/dist/EvidenceGraph.d.ts +71 -0
  23. package/dist/EvidenceGraph.d.ts.map +1 -0
  24. package/dist/EvidenceGraph.js +177 -0
  25. package/dist/EvidenceGraph.js.map +1 -0
  26. package/dist/InteractionEvaluator.d.ts +50 -0
  27. package/dist/InteractionEvaluator.d.ts.map +1 -0
  28. package/dist/InteractionEvaluator.js +205 -0
  29. package/dist/InteractionEvaluator.js.map +1 -0
  30. package/dist/KnowledgeBoundary.d.ts +74 -0
  31. package/dist/KnowledgeBoundary.d.ts.map +1 -0
  32. package/dist/KnowledgeBoundary.js +76 -0
  33. package/dist/KnowledgeBoundary.js.map +1 -0
  34. package/dist/evaluation/EscalationClock.d.ts +65 -0
  35. package/dist/evaluation/EscalationClock.d.ts.map +1 -0
  36. package/dist/evaluation/EscalationClock.js +106 -0
  37. package/dist/evaluation/EscalationClock.js.map +1 -0
  38. package/dist/evaluation/PerformanceEvaluator.d.ts +54 -0
  39. package/dist/evaluation/PerformanceEvaluator.d.ts.map +1 -0
  40. package/dist/evaluation/PerformanceEvaluator.js +161 -0
  41. package/dist/evaluation/PerformanceEvaluator.js.map +1 -0
  42. package/dist/evaluation/WorldState.d.ts +30 -0
  43. package/dist/evaluation/WorldState.d.ts.map +1 -0
  44. package/dist/evaluation/WorldState.js +43 -0
  45. package/dist/evaluation/WorldState.js.map +1 -0
  46. package/dist/evaluation/index.d.ts +8 -0
  47. package/dist/evaluation/index.d.ts.map +1 -0
  48. package/dist/evaluation/index.js +4 -0
  49. package/dist/evaluation/index.js.map +1 -0
  50. package/dist/evaluation/types.d.ts +26 -0
  51. package/dist/evaluation/types.d.ts.map +1 -0
  52. package/dist/evaluation/types.js +9 -0
  53. package/dist/evaluation/types.js.map +1 -0
  54. package/dist/handlers/AssistantCommandRegistry.d.ts +55 -0
  55. package/dist/handlers/AssistantCommandRegistry.d.ts.map +1 -0
  56. package/dist/handlers/AssistantCommandRegistry.js +59 -0
  57. package/dist/handlers/AssistantCommandRegistry.js.map +1 -0
  58. package/dist/handlers/EvidenceIngestion.d.ts +64 -0
  59. package/dist/handlers/EvidenceIngestion.d.ts.map +1 -0
  60. package/dist/handlers/EvidenceIngestion.js +114 -0
  61. package/dist/handlers/EvidenceIngestion.js.map +1 -0
  62. package/dist/handlers/GameLifecycle.d.ts +71 -0
  63. package/dist/handlers/GameLifecycle.d.ts.map +1 -0
  64. package/dist/handlers/GameLifecycle.js +100 -0
  65. package/dist/handlers/GameLifecycle.js.map +1 -0
  66. package/dist/handlers/GraphPopulation.d.ts +24 -0
  67. package/dist/handlers/GraphPopulation.d.ts.map +1 -0
  68. package/dist/handlers/GraphPopulation.js +21 -0
  69. package/dist/handlers/GraphPopulation.js.map +1 -0
  70. package/dist/handlers/ResolutionGate.d.ts +60 -0
  71. package/dist/handlers/ResolutionGate.d.ts.map +1 -0
  72. package/dist/handlers/ResolutionGate.js +49 -0
  73. package/dist/handlers/ResolutionGate.js.map +1 -0
  74. package/dist/index.d.ts +53 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +54 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/investigation/Analyst.d.ts +80 -0
  79. package/dist/investigation/Analyst.d.ts.map +1 -0
  80. package/dist/investigation/Analyst.js +514 -0
  81. package/dist/investigation/Analyst.js.map +1 -0
  82. package/dist/investigation/AnalystWorkspace.d.ts +182 -0
  83. package/dist/investigation/AnalystWorkspace.d.ts.map +1 -0
  84. package/dist/investigation/AnalystWorkspace.js +405 -0
  85. package/dist/investigation/AnalystWorkspace.js.map +1 -0
  86. package/dist/investigation/CaseFile.d.ts +92 -0
  87. package/dist/investigation/CaseFile.d.ts.map +1 -0
  88. package/dist/investigation/CaseFile.js +117 -0
  89. package/dist/investigation/CaseFile.js.map +1 -0
  90. package/dist/investigation/DiscoveryLayer.d.ts +133 -0
  91. package/dist/investigation/DiscoveryLayer.d.ts.map +1 -0
  92. package/dist/investigation/DiscoveryLayer.js +176 -0
  93. package/dist/investigation/DiscoveryLayer.js.map +1 -0
  94. package/dist/investigation/FactLedger.d.ts +91 -0
  95. package/dist/investigation/FactLedger.d.ts.map +1 -0
  96. package/dist/investigation/FactLedger.js +185 -0
  97. package/dist/investigation/FactLedger.js.map +1 -0
  98. package/dist/investigation/InvestigationTimeline.d.ts +98 -0
  99. package/dist/investigation/InvestigationTimeline.d.ts.map +1 -0
  100. package/dist/investigation/InvestigationTimeline.js +178 -0
  101. package/dist/investigation/InvestigationTimeline.js.map +1 -0
  102. package/dist/investigation/ProfileEngine.d.ts +84 -0
  103. package/dist/investigation/ProfileEngine.d.ts.map +1 -0
  104. package/dist/investigation/ProfileEngine.js +170 -0
  105. package/dist/investigation/ProfileEngine.js.map +1 -0
  106. package/dist/investigation/WorkspaceProjections.d.ts +94 -0
  107. package/dist/investigation/WorkspaceProjections.d.ts.map +1 -0
  108. package/dist/investigation/WorkspaceProjections.js +92 -0
  109. package/dist/investigation/WorkspaceProjections.js.map +1 -0
  110. package/dist/investigation/index.d.ts +18 -0
  111. package/dist/investigation/index.d.ts.map +1 -0
  112. package/dist/investigation/index.js +10 -0
  113. package/dist/investigation/index.js.map +1 -0
  114. package/dist/investigation/types.d.ts +206 -0
  115. package/dist/investigation/types.d.ts.map +1 -0
  116. package/dist/investigation/types.js +20 -0
  117. package/dist/investigation/types.js.map +1 -0
  118. package/dist/types.d.ts +283 -0
  119. package/dist/types.d.ts.map +1 -0
  120. package/dist/types.js +70 -0
  121. package/dist/types.js.map +1 -0
  122. package/package.json +48 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Intelligence Cycle and gridlock contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Agent Route Resolver — maps command types to agent roles (#855).
3
+ *
4
+ * Engine-level utility. Produces a pure data object describing which
5
+ * agent role a command should target. The product layer (e.g. CliRunner)
6
+ * interprets the route and wires execution through AgentOrchestrator.
7
+ *
8
+ * This keeps the engine free of platform-layer dependencies while
9
+ * providing a canonical mapping from command verbs to agent roles.
10
+ */
11
+ /** Context scope determining what knowledge an agent receives. */
12
+ export type ContextScope = 'character' | 'advisor' | 'controller';
13
+ /** Resolved agent route for a command. */
14
+ export interface AgentRoute {
15
+ /** Agent definition key (character id, 'sage', 'c-controller'). */
16
+ role: string;
17
+ /** Unique agent identifier for the request. */
18
+ agentId: string;
19
+ /** Knowledge scope to apply when building context. */
20
+ contextScope: ContextScope;
21
+ /** What to do when agent resolution fails. */
22
+ fallbackMode: 'deterministic';
23
+ }
24
+ /** Minimal game state needed by the route resolver. */
25
+ interface RouteGameState {
26
+ case: {
27
+ characters: Array<{
28
+ id: string;
29
+ name: string;
30
+ }>;
31
+ };
32
+ }
33
+ /**
34
+ * Resolve command verb + args to an agent route.
35
+ * Returns null for commands that don't map to an agent role.
36
+ */
37
+ export declare function resolveAgentRoute(verb: string, args: string[], gameState: RouteGameState): AgentRoute | null;
38
+ /**
39
+ * Resolve the C controller agent route.
40
+ * Called from phase-transition logic, not from command dispatch.
41
+ */
42
+ export declare function resolveControllerRoute(): AgentRoute;
43
+ export {};
44
+ //# sourceMappingURL=AgentRoute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentRoute.d.ts","sourceRoot":"","sources":["../src/AgentRoute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,kEAAkE;AAClE,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC;AAElE,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,YAAY,EAAE,YAAY,CAAC;IAC3B,8CAA8C;IAC9C,YAAY,EAAE,eAAe,CAAC;CAC/B;AAED,uDAAuD;AACvD,UAAU,cAAc;IACtB,IAAI,EAAE;QAAE,UAAU,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;CAC3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,EAAE,cAAc,GACxB,UAAU,GAAG,IAAI,CA+BnB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,UAAU,CAOnD"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Agent Route Resolver — maps command types to agent roles (#855).
3
+ *
4
+ * Engine-level utility. Produces a pure data object describing which
5
+ * agent role a command should target. The product layer (e.g. CliRunner)
6
+ * interprets the route and wires execution through AgentOrchestrator.
7
+ *
8
+ * This keeps the engine free of platform-layer dependencies while
9
+ * providing a canonical mapping from command verbs to agent roles.
10
+ */
11
+ /**
12
+ * Resolve command verb + args to an agent route.
13
+ * Returns null for commands that don't map to an agent role.
14
+ */
15
+ export function resolveAgentRoute(verb, args, gameState) {
16
+ const v = verb.toLowerCase();
17
+ if (v === 'talk') {
18
+ // Parse "talk to <id> [message]" — target is first arg after optional "to"
19
+ const target = (args[0]?.toLowerCase() === 'to' ? args[1] : args[0])?.toLowerCase();
20
+ if (!target)
21
+ return null;
22
+ const character = gameState.case.characters.find(c => c.id === target || c.name.toLowerCase() === target);
23
+ if (!character)
24
+ return null;
25
+ return {
26
+ role: character.id,
27
+ agentId: character.id,
28
+ contextScope: 'character',
29
+ fallbackMode: 'deterministic',
30
+ };
31
+ }
32
+ if (v === 'sage') {
33
+ return {
34
+ role: 'sage',
35
+ agentId: 'sage',
36
+ contextScope: 'advisor',
37
+ fallbackMode: 'deterministic',
38
+ };
39
+ }
40
+ return null;
41
+ }
42
+ /**
43
+ * Resolve the C controller agent route.
44
+ * Called from phase-transition logic, not from command dispatch.
45
+ */
46
+ export function resolveControllerRoute() {
47
+ return {
48
+ role: 'c-controller',
49
+ agentId: 'c-controller',
50
+ contextScope: 'controller',
51
+ fallbackMode: 'deterministic',
52
+ };
53
+ }
54
+ //# sourceMappingURL=AgentRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentRoute.js","sourceRoot":"","sources":["../src/AgentRoute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAsBH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,IAAc,EACd,SAAyB;IAEzB,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAE7B,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;QACjB,2EAA2E;QAC3E,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACpF,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEzB,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAC9C,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,CACxD,CAAC;QACF,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAE5B,OAAO;YACL,IAAI,EAAE,SAAS,CAAC,EAAE;YAClB,OAAO,EAAE,SAAS,CAAC,EAAE;YACrB,YAAY,EAAE,WAAW;YACzB,YAAY,EAAE,eAAe;SAC9B,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;QACjB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,MAAM;YACf,YAAY,EAAE,SAAS;YACvB,YAAY,EAAE,eAAe;SAC9B,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,cAAc;QACvB,YAAY,EAAE,YAAY;QAC1B,YAAY,EAAE,eAAe;KAC9B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * CommandRegistry — generic, extensible command dispatch for the game engine.
3
+ *
4
+ * Engine-level primitive. The Orchestrator owns one instance; product layers
5
+ * (TIC, or any future game) register their commands at startup via
6
+ * `register()`. The Orchestrator calls `dispatch()` in processCommand().
7
+ *
8
+ * This is the Core-Configure pattern applied to command routing:
9
+ * - Engine provides: registry, dispatch, help generation, metadata queries
10
+ * - Product provides: command verbs, handlers, help text, categories
11
+ */
12
+ /** Function that executes when a command is dispatched. */
13
+ export type CommandFn = (args: string[]) => string | Promise<string>;
14
+ /** Metadata for a registered command. */
15
+ export interface CommandRegistration {
16
+ /** The handler function — called with parsed args on dispatch. */
17
+ handler: CommandFn;
18
+ /**
19
+ * Whether this command mutates game state (triggers stateVersion increment,
20
+ * auto-save, milestone checks). Default: false.
21
+ */
22
+ mutating?: boolean;
23
+ /** Help text entry for this command. */
24
+ help?: CommandHelp;
25
+ }
26
+ /** Help entry for a single command. */
27
+ export interface CommandHelp {
28
+ /** Usage text shown in help output, e.g. "talk to <id> [message]" */
29
+ usage: string;
30
+ /** Short description, e.g. "Interview a contact" */
31
+ description: string;
32
+ /** Category for grouping in help output, e.g. "Collection" */
33
+ category: string;
34
+ }
35
+ /**
36
+ * Generic command registry with plugin architecture.
37
+ *
38
+ * Commands are registered by verb (case-insensitive). Dispatch looks up the
39
+ * verb and calls the handler. Unknown verbs return a configurable fallback.
40
+ */
41
+ export declare class CommandRegistry {
42
+ private commands;
43
+ /**
44
+ * Register a command handler for a verb.
45
+ * Overwrites any previous registration for the same verb.
46
+ */
47
+ register(verb: string, registration: CommandRegistration): void;
48
+ /**
49
+ * Register multiple commands at once.
50
+ */
51
+ registerAll(entries: Record<string, CommandRegistration>): void;
52
+ /** Check whether a verb is registered. */
53
+ has(verb: string): boolean;
54
+ /** Get registration metadata for a verb (or undefined). */
55
+ get(verb: string): CommandRegistration | undefined;
56
+ /** Whether the command mutates game state. */
57
+ isMutating(verb: string): boolean;
58
+ /** Dispatch a command. Returns the handler's response or a fallback for unknown verbs. */
59
+ dispatch(verb: string, args: string[]): Promise<string>;
60
+ /** All registered verbs. */
61
+ verbs(): string[];
62
+ /**
63
+ * Generate help text grouped by category.
64
+ * Categories are rendered in insertion order.
65
+ */
66
+ generateHelp(title?: string): string;
67
+ }
68
+ //# sourceMappingURL=CommandRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandRegistry.d.ts","sourceRoot":"","sources":["../src/CommandRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,2DAA2D;AAC3D,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAErE,yCAAyC;AACzC,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,OAAO,EAAE,SAAS,CAAC;IAEnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,wCAAwC;IACxC,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAA0C;IAE1D;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,mBAAmB,GAAG,IAAI;IAI/D;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,GAAG,IAAI;IAM/D,0CAA0C;IAC1C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,2DAA2D;IAC3D,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAIlD,8CAA8C;IAC9C,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC,0FAA0F;IACpF,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ7D,4BAA4B;IAC5B,KAAK,IAAI,MAAM,EAAE;IAIjB;;;OAGG;IACH,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;CAyBrC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * CommandRegistry — generic, extensible command dispatch for the game engine.
3
+ *
4
+ * Engine-level primitive. The Orchestrator owns one instance; product layers
5
+ * (TIC, or any future game) register their commands at startup via
6
+ * `register()`. The Orchestrator calls `dispatch()` in processCommand().
7
+ *
8
+ * This is the Core-Configure pattern applied to command routing:
9
+ * - Engine provides: registry, dispatch, help generation, metadata queries
10
+ * - Product provides: command verbs, handlers, help text, categories
11
+ */
12
+ /**
13
+ * Generic command registry with plugin architecture.
14
+ *
15
+ * Commands are registered by verb (case-insensitive). Dispatch looks up the
16
+ * verb and calls the handler. Unknown verbs return a configurable fallback.
17
+ */
18
+ export class CommandRegistry {
19
+ commands = new Map();
20
+ /**
21
+ * Register a command handler for a verb.
22
+ * Overwrites any previous registration for the same verb.
23
+ */
24
+ register(verb, registration) {
25
+ this.commands.set(verb.toLowerCase(), registration);
26
+ }
27
+ /**
28
+ * Register multiple commands at once.
29
+ */
30
+ registerAll(entries) {
31
+ for (const [verb, reg] of Object.entries(entries)) {
32
+ this.register(verb, reg);
33
+ }
34
+ }
35
+ /** Check whether a verb is registered. */
36
+ has(verb) {
37
+ return this.commands.has(verb.toLowerCase());
38
+ }
39
+ /** Get registration metadata for a verb (or undefined). */
40
+ get(verb) {
41
+ return this.commands.get(verb.toLowerCase());
42
+ }
43
+ /** Whether the command mutates game state. */
44
+ isMutating(verb) {
45
+ return this.commands.get(verb.toLowerCase())?.mutating ?? false;
46
+ }
47
+ /** Dispatch a command. Returns the handler's response or a fallback for unknown verbs. */
48
+ async dispatch(verb, args) {
49
+ const reg = this.commands.get(verb.toLowerCase());
50
+ if (!reg) {
51
+ return `Unknown command: "${verb}". Type 'help' for a list of commands.`;
52
+ }
53
+ return reg.handler(args);
54
+ }
55
+ /** All registered verbs. */
56
+ verbs() {
57
+ return Array.from(this.commands.keys());
58
+ }
59
+ /**
60
+ * Generate help text grouped by category.
61
+ * Categories are rendered in insertion order.
62
+ */
63
+ generateHelp(title) {
64
+ const categories = new Map();
65
+ for (const reg of this.commands.values()) {
66
+ if (!reg.help)
67
+ continue;
68
+ const cat = reg.help.category;
69
+ if (!categories.has(cat))
70
+ categories.set(cat, []);
71
+ categories.get(cat).push(reg.help);
72
+ }
73
+ const lines = [];
74
+ if (title) {
75
+ lines.push(title, '');
76
+ }
77
+ for (const [category, entries] of categories) {
78
+ lines.push(`[${category}]`);
79
+ for (const entry of entries) {
80
+ lines.push(` ${entry.usage.padEnd(28)}— ${entry.description}`);
81
+ }
82
+ lines.push('');
83
+ }
84
+ return lines.join('\n').trimEnd();
85
+ }
86
+ }
87
+ //# sourceMappingURL=CommandRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandRegistry.js","sourceRoot":"","sources":["../src/CommandRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Engine-generic ContextFactory — builds typed context objects for handler
3
+ * modules without coupling to the concrete Orchestrator class.
4
+ *
5
+ * Only engine-generic context builders live here:
6
+ * - `collection()` — for CollectionHandlers (talk, examine, collect)
7
+ * - `rice()` — for RiceHandlers (empathize, gift, flatter, challenge)
8
+ *
9
+ * TIC-specific context builders (`accusation()`, `sage()`) stay in TIC's
10
+ * own ContextFactory because they depend on TIC-only source interfaces
11
+ * (AccusationSource → AnalystWorkspace, SageSource → SageAnalyst).
12
+ *
13
+ * ## Parameterisation
14
+ *
15
+ * The factory is generic over `TState` (defaults to `EngineState`). Product
16
+ * layers that extend the engine state (e.g. TIC's `GameState`) can bind
17
+ * their state type when constructing the factory, and the context objects
18
+ * will carry the narrowed type through to handlers.
19
+ *
20
+ * MS-28 #1116 — Step 5.3 — Engine-generic types boundary.
21
+ */
22
+ import type { EngineState, CollectionSource, RiceSource, DomainInteractionState, RiceGuidanceProvider } from './types.js';
23
+ /**
24
+ * Context passed to engine-generic collection handlers.
25
+ *
26
+ * Contains state, interaction access, LLM hooks, and optional narrative
27
+ * dispatch / RICE guidance providers. No product-specific fields.
28
+ */
29
+ export interface EngineCollectionContext<TState = EngineState> {
30
+ gameState: TState;
31
+ notifications: string[];
32
+ getInteractionState: (playerId: string, characterId: string) => DomainInteractionState;
33
+ getLLMResponse: (character: any, message: string) => Promise<string>;
34
+ summarizeDialogue: (character: any, message: string, response: string) => Promise<string | null>;
35
+ onCharacterDialogue?: (character: any, responseText: string) => void;
36
+ getRiceGuidance?: RiceGuidanceProvider;
37
+ }
38
+ /**
39
+ * Context passed to engine-generic RICE handlers.
40
+ *
41
+ * Minimal shape — state, notifications, and interaction state access.
42
+ */
43
+ export interface EngineRiceContext<TState = EngineState> {
44
+ gameState: TState;
45
+ notifications: string[];
46
+ getInteractionState: (playerId: string, characterId: string) => DomainInteractionState;
47
+ }
48
+ /**
49
+ * Engine-generic context factory.
50
+ *
51
+ * Builds `EngineCollectionContext` and `EngineRiceContext` from a host that
52
+ * implements the corresponding source interfaces. Product layers can extend
53
+ * this class to add product-specific context builders (TIC adds
54
+ * `accusation()` and `sage()`).
55
+ */
56
+ export declare class EngineContextFactory<TState = EngineState> {
57
+ protected readonly source: CollectionSource<TState> & RiceSource<TState>;
58
+ constructor(source: CollectionSource<TState> & RiceSource<TState>);
59
+ collection(): EngineCollectionContext<TState>;
60
+ rice(): EngineRiceContext<TState>;
61
+ }
62
+ //# sourceMappingURL=ContextFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContextFactory.d.ts","sourceRoot":"","sources":["../src/ContextFactory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAUpB;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB,CAAC,MAAM,GAAG,WAAW;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,sBAAsB,CAAC;IACvF,cAAc,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,iBAAiB,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACjG,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,eAAe,CAAC,EAAE,oBAAoB,CAAC;CACxC;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB,CAAC,MAAM,GAAG,WAAW;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,sBAAsB,CAAC;CACxF;AAMD;;;;;;;GAOG;AACH,qBAAa,oBAAoB,CAAC,MAAM,GAAG,WAAW;IAElD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC;gBAArD,MAAM,EAAE,gBAAgB,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC;IAG1E,UAAU,IAAI,uBAAuB,CAAC,MAAM,CAAC;IAa7C,IAAI,IAAI,iBAAiB,CAAC,MAAM,CAAC;CAQlC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Engine-generic ContextFactory — builds typed context objects for handler
3
+ * modules without coupling to the concrete Orchestrator class.
4
+ *
5
+ * Only engine-generic context builders live here:
6
+ * - `collection()` — for CollectionHandlers (talk, examine, collect)
7
+ * - `rice()` — for RiceHandlers (empathize, gift, flatter, challenge)
8
+ *
9
+ * TIC-specific context builders (`accusation()`, `sage()`) stay in TIC's
10
+ * own ContextFactory because they depend on TIC-only source interfaces
11
+ * (AccusationSource → AnalystWorkspace, SageSource → SageAnalyst).
12
+ *
13
+ * ## Parameterisation
14
+ *
15
+ * The factory is generic over `TState` (defaults to `EngineState`). Product
16
+ * layers that extend the engine state (e.g. TIC's `GameState`) can bind
17
+ * their state type when constructing the factory, and the context objects
18
+ * will carry the narrowed type through to handlers.
19
+ *
20
+ * MS-28 #1116 — Step 5.3 — Engine-generic types boundary.
21
+ */
22
+ // ---------------------------------------------------------------------------
23
+ // EngineContextFactory
24
+ // ---------------------------------------------------------------------------
25
+ /**
26
+ * Engine-generic context factory.
27
+ *
28
+ * Builds `EngineCollectionContext` and `EngineRiceContext` from a host that
29
+ * implements the corresponding source interfaces. Product layers can extend
30
+ * this class to add product-specific context builders (TIC adds
31
+ * `accusation()` and `sage()`).
32
+ */
33
+ export class EngineContextFactory {
34
+ source;
35
+ constructor(source) {
36
+ this.source = source;
37
+ }
38
+ collection() {
39
+ const s = this.source;
40
+ return {
41
+ gameState: s.getGameState(),
42
+ notifications: s.getNotifications(),
43
+ getInteractionState: s.getInteractionState.bind(s),
44
+ getLLMResponse: s._getLLMResponse.bind(s),
45
+ summarizeDialogue: s._summarizeDialogue.bind(s),
46
+ onCharacterDialogue: s._onCharacterDialogue?.bind(s),
47
+ getRiceGuidance: s._getRiceGuidance,
48
+ };
49
+ }
50
+ rice() {
51
+ const s = this.source;
52
+ return {
53
+ gameState: s.getGameState(),
54
+ notifications: s.getNotifications(),
55
+ getInteractionState: s.getInteractionState.bind(s),
56
+ };
57
+ }
58
+ }
59
+ //# sourceMappingURL=ContextFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContextFactory.js","sourceRoot":"","sources":["../src/ContextFactory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA6CH,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,OAAO,oBAAoB;IAEV;IADrB,YACqB,MAAqD;QAArD,WAAM,GAAN,MAAM,CAA+C;IACvE,CAAC;IAEJ,UAAU;QACR,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACtB,OAAO;YACL,SAAS,EAAE,CAAC,CAAC,YAAY,EAAE;YAC3B,aAAa,EAAE,CAAC,CAAC,gBAAgB,EAAE;YACnC,mBAAmB,EAAE,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;YAClD,cAAc,EAAE,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;YACzC,iBAAiB,EAAE,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;YAC/C,mBAAmB,EAAE,CAAC,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC,CAAC;YACpD,eAAe,EAAE,CAAC,CAAC,gBAAgB;SACpC,CAAC;IACJ,CAAC;IAED,IAAI;QACF,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACtB,OAAO;YACL,SAAS,EAAE,CAAC,CAAC,YAAY,EAAE;YAC3B,aAAa,EAAE,CAAC,CAAC,gBAAgB,EAAE;YACnC,mBAAmB,EAAE,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;SACnD,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Dialogue Gate — generic gated dialogue with unlock bands and disclosure ceilings.
3
+ *
4
+ * Engine-generic: maps a numeric cooperation score (0–10) to a disclosure
5
+ * posture via configurable threshold bands. The unlock mechanism (e.g.
6
+ * RICE in TIC) is product-specific — the gate just reads a numeric score
7
+ * and determines how open an entity is.
8
+ *
9
+ * No TIC vocabulary: no suspects, crimes, cases, investigations.
10
+ *
11
+ * See issue #718.
12
+ */
13
+ /** A named disclosure posture — controls how much an entity will reveal. */
14
+ export type PostureName = string;
15
+ /**
16
+ * A threshold band definition — maps a score range to a posture.
17
+ * Bands are evaluated in order; the first band whose `maxExclusive`
18
+ * exceeds the score wins. The last band is the catch-all.
19
+ */
20
+ export interface ThresholdBand {
21
+ /** Posture name for this band (e.g. 'locked', 'guarded', 'open'). */
22
+ readonly posture: PostureName;
23
+ /** Upper bound (exclusive). Scores < maxExclusive fall into this band. */
24
+ readonly maxExclusive: number;
25
+ }
26
+ /**
27
+ * A disclosure ceiling — maximum revelation level an entity will reach
28
+ * at a given posture. Ceilings constrain what information can be
29
+ * disclosed even if the entity is willing to talk.
30
+ */
31
+ export interface DisclosureCeiling {
32
+ /** Posture this ceiling applies to. */
33
+ readonly posture: PostureName;
34
+ /** Topics or categories that are forbidden at this posture. */
35
+ readonly forbiddenTopics: readonly string[];
36
+ /** Maximum verbosity level (0–1 normalized). */
37
+ readonly maxVerbosity: number;
38
+ }
39
+ /**
40
+ * Configuration for a DialogueGate instance.
41
+ * Products provide their own bands and ceilings.
42
+ */
43
+ export interface DialogueGateConfig {
44
+ /**
45
+ * Ordered threshold bands. Must be sorted ascending by maxExclusive.
46
+ * The last band's maxExclusive should be +Infinity (catch-all).
47
+ */
48
+ readonly bands: readonly ThresholdBand[];
49
+ /** Optional disclosure ceilings per posture. */
50
+ readonly ceilings?: readonly DisclosureCeiling[];
51
+ }
52
+ /**
53
+ * Result of evaluating a cooperation score against the gate.
54
+ */
55
+ export interface GateResult {
56
+ /** The resolved posture name. */
57
+ readonly posture: PostureName;
58
+ /** The band index (0-based) that matched. */
59
+ readonly bandIndex: number;
60
+ /** Whether the entity is in the lowest (most locked) band. */
61
+ readonly isLocked: boolean;
62
+ /** Whether the entity is in the highest (most open) band. */
63
+ readonly isFullyOpen: boolean;
64
+ /** Applicable disclosure ceiling, if configured. */
65
+ readonly ceiling: DisclosureCeiling | undefined;
66
+ }
67
+ /**
68
+ * Whether an entity meets a minimum cooperation threshold for interaction.
69
+ */
70
+ export interface ThresholdCheck {
71
+ /** Whether the score meets or exceeds the threshold. */
72
+ readonly passes: boolean;
73
+ /** The current score. */
74
+ readonly score: number;
75
+ /** The required threshold. */
76
+ readonly threshold: number;
77
+ /** The shortfall (0 if passes). */
78
+ readonly deficit: number;
79
+ }
80
+ /**
81
+ * Default TIC-style bands on a 0–10 scale:
82
+ * locked: [0, 3)
83
+ * guarded: [3, 6)
84
+ * cooperative: [6, 8)
85
+ * open: [8, +Inf)
86
+ */
87
+ export declare const DEFAULT_BANDS: readonly ThresholdBand[];
88
+ /**
89
+ * Evaluates a cooperation score against a gate configuration.
90
+ *
91
+ * @param score - Numeric cooperation/openness score (typically 0–10).
92
+ * @param config - Gate configuration with threshold bands and optional ceilings.
93
+ * @returns The gate evaluation result.
94
+ */
95
+ export declare function evaluateGate(score: number, config: DialogueGateConfig): GateResult;
96
+ /**
97
+ * Checks whether a cooperation score meets a minimum threshold.
98
+ *
99
+ * @param score - Current cooperation score.
100
+ * @param threshold - Minimum required score.
101
+ * @returns Threshold check result.
102
+ */
103
+ export declare function checkThreshold(score: number, threshold: number): ThresholdCheck;
104
+ /**
105
+ * Convenience: evaluates gate using the default TIC-style bands.
106
+ */
107
+ export declare function evaluateDefaultGate(score: number): GateResult;
108
+ /**
109
+ * Creates a gate configuration from simple posture-threshold pairs.
110
+ *
111
+ * Example:
112
+ * createGateConfig(['locked', 3], ['guarded', 6], ['cooperative', 8], ['open', Infinity])
113
+ *
114
+ * is equivalent to the DEFAULT_BANDS constant.
115
+ */
116
+ export declare function createGateConfig(...entries: Array<[posture: PostureName, maxExclusive: number]>): DialogueGateConfig;
117
+ //# sourceMappingURL=DialogueGate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DialogueGate.d.ts","sourceRoot":"","sources":["../src/DialogueGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,CAAC;CACjD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yBAAyB;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,mCAAmC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,aAAa,EAKxC,CAAC;AAMX;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,UAAU,CAyBlF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAQ/E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAE7D;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,GAC9D,kBAAkB,CAWpB"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Dialogue Gate — generic gated dialogue with unlock bands and disclosure ceilings.
3
+ *
4
+ * Engine-generic: maps a numeric cooperation score (0–10) to a disclosure
5
+ * posture via configurable threshold bands. The unlock mechanism (e.g.
6
+ * RICE in TIC) is product-specific — the gate just reads a numeric score
7
+ * and determines how open an entity is.
8
+ *
9
+ * No TIC vocabulary: no suspects, crimes, cases, investigations.
10
+ *
11
+ * See issue #718.
12
+ */
13
+ // ---------------------------------------------------------------------------
14
+ // Default bands (TIC defaults — products can override)
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Default TIC-style bands on a 0–10 scale:
18
+ * locked: [0, 3)
19
+ * guarded: [3, 6)
20
+ * cooperative: [6, 8)
21
+ * open: [8, +Inf)
22
+ */
23
+ export const DEFAULT_BANDS = [
24
+ { posture: 'locked', maxExclusive: 3 },
25
+ { posture: 'guarded', maxExclusive: 6 },
26
+ { posture: 'cooperative', maxExclusive: 8 },
27
+ { posture: 'open', maxExclusive: Infinity },
28
+ ];
29
+ // ---------------------------------------------------------------------------
30
+ // Core functions
31
+ // ---------------------------------------------------------------------------
32
+ /**
33
+ * Evaluates a cooperation score against a gate configuration.
34
+ *
35
+ * @param score - Numeric cooperation/openness score (typically 0–10).
36
+ * @param config - Gate configuration with threshold bands and optional ceilings.
37
+ * @returns The gate evaluation result.
38
+ */
39
+ export function evaluateGate(score, config) {
40
+ const { bands, ceilings } = config;
41
+ if (bands.length === 0) {
42
+ throw new Error('DialogueGate: bands array must not be empty.');
43
+ }
44
+ let matchedIndex = bands.length - 1; // default to last band
45
+ for (let i = 0; i < bands.length; i++) {
46
+ if (score < bands[i].maxExclusive) {
47
+ matchedIndex = i;
48
+ break;
49
+ }
50
+ }
51
+ const matched = bands[matchedIndex];
52
+ const ceiling = ceilings?.find(c => c.posture === matched.posture);
53
+ return {
54
+ posture: matched.posture,
55
+ bandIndex: matchedIndex,
56
+ isLocked: matchedIndex === 0,
57
+ isFullyOpen: matchedIndex === bands.length - 1,
58
+ ceiling,
59
+ };
60
+ }
61
+ /**
62
+ * Checks whether a cooperation score meets a minimum threshold.
63
+ *
64
+ * @param score - Current cooperation score.
65
+ * @param threshold - Minimum required score.
66
+ * @returns Threshold check result.
67
+ */
68
+ export function checkThreshold(score, threshold) {
69
+ const passes = score >= threshold;
70
+ return {
71
+ passes,
72
+ score,
73
+ threshold,
74
+ deficit: passes ? 0 : threshold - score,
75
+ };
76
+ }
77
+ /**
78
+ * Convenience: evaluates gate using the default TIC-style bands.
79
+ */
80
+ export function evaluateDefaultGate(score) {
81
+ return evaluateGate(score, { bands: DEFAULT_BANDS });
82
+ }
83
+ /**
84
+ * Creates a gate configuration from simple posture-threshold pairs.
85
+ *
86
+ * Example:
87
+ * createGateConfig(['locked', 3], ['guarded', 6], ['cooperative', 8], ['open', Infinity])
88
+ *
89
+ * is equivalent to the DEFAULT_BANDS constant.
90
+ */
91
+ export function createGateConfig(...entries) {
92
+ if (entries.length === 0) {
93
+ throw new Error('DialogueGate: at least one band entry is required.');
94
+ }
95
+ const bands = entries.map(([posture, maxExclusive]) => ({
96
+ posture,
97
+ maxExclusive,
98
+ }));
99
+ return { bands };
100
+ }
101
+ //# sourceMappingURL=DialogueGate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DialogueGate.js","sourceRoot":"","sources":["../src/DialogueGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA+EH,8EAA8E;AAC9E,uDAAuD;AACvD,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAA6B;IACrD,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,EAAE;IACtC,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,EAAE;IACvC,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,EAAE;IAC3C,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE;CACnC,CAAC;AAEX,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,MAA0B;IACpE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;IAEnC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,YAAY,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,uBAAuB;IAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;YAClC,YAAY,GAAG,CAAC,CAAC;YACjB,MAAM;QACR,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAEnE,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS,EAAE,YAAY;QACvB,QAAQ,EAAE,YAAY,KAAK,CAAC;QAC5B,WAAW,EAAE,YAAY,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;QAC9C,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,SAAiB;IAC7D,MAAM,MAAM,GAAG,KAAK,IAAI,SAAS,CAAC;IAClC,OAAO;QACL,MAAM;QACN,KAAK;QACL,SAAS;QACT,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,KAAK;KACxC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,YAAY,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAG,OAA4D;IAE/D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,KAAK,GAAoB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC;QACvE,OAAO;QACP,YAAY;KACb,CAAC,CAAC,CAAC;IAEJ,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC"}