@rmrdeveloper/sideroom-pi 9.1.0 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -34
- package/extensions/done/guard.ts +1 -38
- package/extensions/done/model.ts +1 -28
- package/extensions/explain/index.ts +4 -6
- package/extensions/explain/prompt.ts +13 -0
- package/extensions/shared/settle.ts +1 -1
- package/package.json +2 -2
- package/skills/sideroom-persona/SKILL.md +1 -1
- package/extensions/explain/guard.ts +0 -60
- package/extensions/explain/model.ts +0 -66
package/README.md
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@rmrdeveloper/sideroom-pi)
|
|
10
10
|
|
|
11
11
|
**The open-source quality layer for Pi.** Your agent asks before it guesses,
|
|
12
|
-
follows your code rules on the lines it writes, and
|
|
13
|
-
|
|
12
|
+
follows your code rules on the lines it writes, and reviews its changes
|
|
13
|
+
before finishing.
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
pi install npm:@rmrdeveloper/sideroom-pi
|
|
@@ -26,8 +26,8 @@ pi install npm:@rmrdeveloper/sideroom-pi
|
|
|
26
26
|
|
|
27
27
|
For developers who chose Pi for control or cost and need the result to be
|
|
28
28
|
actually ready: Sideroom is the quality layer that makes Pi follow your
|
|
29
|
-
rules, ask when there are two reasonable paths, and
|
|
30
|
-
|
|
29
|
+
rules, ask when there are two reasonable paths, and review its changes
|
|
30
|
+
against the loaded guide before finishing.
|
|
31
31
|
|
|
32
32
|
## Why Sideroom exists
|
|
33
33
|
|
|
@@ -61,8 +61,8 @@ Sideroom answers each one with a small, opinionated surface:
|
|
|
61
61
|
| Unapplied guidelines | `sideroom_rules` — mechanical checks that block or flag the lines you add |
|
|
62
62
|
| Unchecked judgment rules | `jev` — asks a decision model about guide rules with visible evidence |
|
|
63
63
|
| Unclear answers | `sideroom_persona` — one voice: direct, plain, and free of unnecessary technical words |
|
|
64
|
-
| Premature completion |
|
|
65
|
-
| Work left unexplained | `explain` —
|
|
64
|
+
| Premature completion | Guidelines review — asks for relevant checks and reuses valid results |
|
|
65
|
+
| Work left unexplained | `explain` — invites a walkthrough in the final response after meaningful work |
|
|
66
66
|
|
|
67
67
|
## What it feels like
|
|
68
68
|
|
|
@@ -101,9 +101,9 @@ wall of tool calls, it:
|
|
|
101
101
|
conditionals and swallowed errors block the mutation; vague names, stale
|
|
102
102
|
`TODO`s, commented-out code, and debug output are appended as notes to the
|
|
103
103
|
result. A rule that keeps firing degrades instead of trapping the agent.
|
|
104
|
-
- **
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
- **Reviews before finishing.** The guidelines review asks for missing,
|
|
105
|
+
failed or stale checks and reuses valid results. Check observation never
|
|
106
|
+
forces another response just to run a command.
|
|
107
107
|
|
|
108
108
|
## What's inside
|
|
109
109
|
|
|
@@ -273,24 +273,25 @@ symbols in the lines a `write`/`edit` adds block the mutation; flattering
|
|
|
273
273
|
openers, hedging, automatic apologies, and AI meta-commentary are answered
|
|
274
274
|
with a capped steer. No profiles to switch and no profile selection to store.
|
|
275
275
|
|
|
276
|
-
### Done —
|
|
276
|
+
### Done — passive check observation
|
|
277
277
|
|
|
278
278
|
`sideroom_done` detects the project's check command — `package.json` scripts
|
|
279
279
|
(`check` → `test` → `lint` → `typecheck` → `types`) with the right
|
|
280
280
|
package manager, `pytest`, `go test ./...`, `cargo test`, or a `make check`
|
|
281
|
-
target — and
|
|
282
|
-
|
|
283
|
-
|
|
281
|
+
target — and observes checks the agent chooses to run. It shares successful
|
|
282
|
+
results with guidelines review, so that review can reuse them. It never requests
|
|
283
|
+
a continuation to run checks. A coverage notice can join an existing review or
|
|
284
|
+
style continuation, but never opens one on its own.
|
|
284
285
|
|
|
285
|
-
### Explain — the walkthrough
|
|
286
|
+
### Explain — the walkthrough invitation
|
|
286
287
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
288
|
+
After meaningful changes, review and checks are complete, `explain` lets the
|
|
289
|
+
agent end its final response with a short invitation to explain the changes
|
|
290
|
+
or how to test them. It skips trivial work and explanations already given.
|
|
291
|
+
There is no automatic questionnaire, file-count threshold or extra model turn.
|
|
292
|
+
Only after you accept, the agent may clarify the scope through `sideroom_ask`
|
|
293
|
+
in the TUI; if your request is clear, it explains directly. A fixed reminder
|
|
294
|
+
keeps the system prompt stable across turns. No tool, widget or persisted state.
|
|
294
295
|
|
|
295
296
|
## Quick path
|
|
296
297
|
|
|
@@ -455,22 +456,20 @@ itself.
|
|
|
455
456
|
`cargo test`, or `make check`. Detection is cached per working directory.
|
|
456
457
|
- Green means that command ran with a zero exit in this run. A later
|
|
457
458
|
successful `write`/`edit` clears green again.
|
|
458
|
-
-
|
|
459
|
+
- Observation only: no standalone check or coverage continuation. Coverage
|
|
460
|
+
notices join another necessary continuation at most once per user turn.
|
|
459
461
|
|
|
460
462
|
### Explain contract
|
|
461
463
|
|
|
462
|
-
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
- At most one offer per turn. The flag is set only when the supplement is
|
|
472
|
-
appended; the offer never triggers its own continuation.
|
|
473
|
-
- No green-check requirement: red checks still produce the offer.
|
|
464
|
+
- Delivery: a fixed, idempotent reminder on `before_agent_start`; no per-turn
|
|
465
|
+
state is interpolated into the system prompt.
|
|
466
|
+
- After meaningful work, review and checks, the agent may include one short
|
|
467
|
+
invitation in the final response, in the user's language. Trivial work,
|
|
468
|
+
explanations already provided and requests for no follow-up skip it.
|
|
469
|
+
- No file-count threshold, automatic questionnaire, closing hook or extra turn.
|
|
470
|
+
- After explicit acceptance, clarify scope through `sideroom_ask` only when
|
|
471
|
+
needed in the TUI. Otherwise explain directly, or clarify in ordinary
|
|
472
|
+
conversation outside the TUI.
|
|
474
473
|
|
|
475
474
|
### Grill contract
|
|
476
475
|
|
package/extensions/done/guard.ts
CHANGED
|
@@ -7,23 +7,15 @@ import {
|
|
|
7
7
|
isWriteToolResult,
|
|
8
8
|
} from '@earendil-works/pi-coding-agent';
|
|
9
9
|
import { registerCheckStatus } from '../shared/check-status.ts';
|
|
10
|
-
import {
|
|
11
|
-
registerSettleGuard,
|
|
12
|
-
registerSettleSupplement,
|
|
13
|
-
SETTLE_PRIORITY,
|
|
14
|
-
withHiddenSteer,
|
|
15
|
-
} from '../shared/settle.ts';
|
|
10
|
+
import { registerSettleSupplement } from '../shared/settle.ts';
|
|
16
11
|
import { type CheckCommand, commandMatches } from './detect.ts';
|
|
17
12
|
import {
|
|
18
|
-
DONE_GATE_TYPE,
|
|
19
13
|
type DoneState,
|
|
20
|
-
formatDoneSteer,
|
|
21
14
|
formatMissingTestNotice,
|
|
22
15
|
isSourcePath,
|
|
23
16
|
isTestPath,
|
|
24
17
|
MISSING_TEST_NOTICE_TYPE,
|
|
25
18
|
shouldNoticeMissingTest,
|
|
26
|
-
shouldSteerDone,
|
|
27
19
|
} from './model.ts';
|
|
28
20
|
|
|
29
21
|
export type ResolveCommand = (
|
|
@@ -82,7 +74,6 @@ export function registerDoneGuard({
|
|
|
82
74
|
if (event.isError) {
|
|
83
75
|
return;
|
|
84
76
|
}
|
|
85
|
-
state.mutated = true;
|
|
86
77
|
state.checksGreen = false;
|
|
87
78
|
recordMutationPath(state, path);
|
|
88
79
|
return;
|
|
@@ -105,34 +96,6 @@ export function registerDoneGuard({
|
|
|
105
96
|
content: formatMissingTestNotice(),
|
|
106
97
|
};
|
|
107
98
|
});
|
|
108
|
-
|
|
109
|
-
registerSettleGuard(pi, {
|
|
110
|
-
priority: SETTLE_PRIORITY.done,
|
|
111
|
-
pending: (ctx) =>
|
|
112
|
-
shouldSteerDone(state, resolveCommand(ctx) !== undefined) ||
|
|
113
|
-
shouldNoticeMissingTest(state, resolveTestSetup(ctx)),
|
|
114
|
-
handle: (event, ctx) => {
|
|
115
|
-
const check = resolveCommand(ctx);
|
|
116
|
-
if (check !== undefined && shouldSteerDone(state, true)) {
|
|
117
|
-
state.steerCount += 1;
|
|
118
|
-
return withHiddenSteer({
|
|
119
|
-
event,
|
|
120
|
-
customType: DONE_GATE_TYPE,
|
|
121
|
-
content: formatDoneSteer(check.display),
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
if (!shouldNoticeMissingTest(state, resolveTestSetup(ctx))) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
state.noticedMissingTest = true;
|
|
128
|
-
state.steerCount += 1;
|
|
129
|
-
return withHiddenSteer({
|
|
130
|
-
event,
|
|
131
|
-
customType: MISSING_TEST_NOTICE_TYPE,
|
|
132
|
-
content: formatMissingTestNotice(),
|
|
133
|
-
});
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
99
|
}
|
|
137
100
|
|
|
138
101
|
function recordMutationPath(state: DoneState, path: string | undefined): void {
|
package/extensions/done/model.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
export interface DoneState {
|
|
2
|
-
mutated: boolean;
|
|
3
2
|
checksGreen: boolean;
|
|
4
|
-
steerCount: number;
|
|
5
3
|
mutatedSource: boolean;
|
|
6
4
|
mutatedTest: boolean;
|
|
7
5
|
noticedMissingTest: boolean;
|
|
8
6
|
}
|
|
9
7
|
|
|
10
|
-
export const MAX_DONE_STEERS = 2;
|
|
11
|
-
|
|
12
|
-
export const DONE_GATE_TYPE = 'sideroom-done-gate';
|
|
13
|
-
|
|
14
8
|
export const MISSING_TEST_NOTICE_TYPE = 'sideroom-missing-test-notice';
|
|
15
9
|
|
|
16
10
|
const TEST_DIRECTORY = /(?:^|\/)(?:__tests__|tests?|specs?)(?:\/|$)/;
|
|
@@ -22,9 +16,7 @@ const SOURCE_FILE = /\.(?:[cm]?js|jsx|ts|tsx|go|java|php|py|rs)$/i;
|
|
|
22
16
|
|
|
23
17
|
export function createDoneState(): DoneState {
|
|
24
18
|
return {
|
|
25
|
-
mutated: false,
|
|
26
19
|
checksGreen: false,
|
|
27
|
-
steerCount: 0,
|
|
28
20
|
mutatedSource: false,
|
|
29
21
|
mutatedTest: false,
|
|
30
22
|
noticedMissingTest: false,
|
|
@@ -32,9 +24,7 @@ export function createDoneState(): DoneState {
|
|
|
32
24
|
}
|
|
33
25
|
|
|
34
26
|
export function resetDoneRun(state: DoneState): void {
|
|
35
|
-
state.mutated = false;
|
|
36
27
|
state.checksGreen = false;
|
|
37
|
-
state.steerCount = 0;
|
|
38
28
|
state.mutatedSource = false;
|
|
39
29
|
state.mutatedTest = false;
|
|
40
30
|
state.noticedMissingTest = false;
|
|
@@ -50,18 +40,6 @@ export function isSourcePath(path: string): boolean {
|
|
|
50
40
|
return SOURCE_FILE.test(normalized);
|
|
51
41
|
}
|
|
52
42
|
|
|
53
|
-
export function shouldSteerDone(
|
|
54
|
-
state: DoneState,
|
|
55
|
-
hasCommand: boolean,
|
|
56
|
-
): boolean {
|
|
57
|
-
return (
|
|
58
|
-
hasCommand &&
|
|
59
|
-
state.mutated &&
|
|
60
|
-
!state.checksGreen &&
|
|
61
|
-
state.steerCount < MAX_DONE_STEERS
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
43
|
export function shouldNoticeMissingTest(
|
|
66
44
|
state: DoneState,
|
|
67
45
|
hasTests: boolean,
|
|
@@ -70,15 +48,10 @@ export function shouldNoticeMissingTest(
|
|
|
70
48
|
hasTests &&
|
|
71
49
|
state.mutatedSource &&
|
|
72
50
|
!state.mutatedTest &&
|
|
73
|
-
!state.noticedMissingTest
|
|
74
|
-
state.steerCount < MAX_DONE_STEERS
|
|
51
|
+
!state.noticedMissingTest
|
|
75
52
|
);
|
|
76
53
|
}
|
|
77
54
|
|
|
78
|
-
export function formatDoneSteer(display: string): string {
|
|
79
|
-
return `Run \`${display}\` and make it pass before finishing.`;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
55
|
export function formatMissingTestNotice(): string {
|
|
83
56
|
return 'This run changed code files and no test file. Check whether existing tests cover the changed behavior; add or update a test if coverage is missing, reuse relevant checks that already passed after the latest mutation, and run missing, failed, or stale checks before finishing. Any code or test edit makes earlier checks stale.';
|
|
84
57
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
|
|
2
|
-
import {
|
|
3
|
-
import { createExplainState, resetExplainTurn } from './model.ts';
|
|
2
|
+
import { appendExplainReminder } from './prompt.ts';
|
|
4
3
|
|
|
5
4
|
export default function registerExplain(pi: ExtensionAPI): void {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
pi.on('session_start', () => resetExplainTurn(state));
|
|
5
|
+
pi.on('before_agent_start', (event) => ({
|
|
6
|
+
systemPrompt: appendExplainReminder(event.systemPrompt),
|
|
7
|
+
}));
|
|
10
8
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const EXPLAIN_REMINDER_HEADING = 'Sideroom walkthrough invitation:';
|
|
2
|
+
|
|
3
|
+
export const EXPLAIN_REMINDER = `${EXPLAIN_REMINDER_HEADING}
|
|
4
|
+
After completing meaningful changes, review, and checks, you may end the final response with one short sentence in the user's language offering to explain the changes or how to test them. Offer only when it adds value; omit it for trivial work, when the requested explanation is already provided, or when the user asks for no follow-up. Do not ask an automatic question or call sideroom_ask just to offer a walkthrough. Only after the user explicitly accepts the invitation, use sideroom_ask in the TUI if clarification is needed about changes, test steps, or both; otherwise explain directly. Outside the TUI, clarify in ordinary conversation when needed.`;
|
|
5
|
+
|
|
6
|
+
export function appendExplainReminder(systemPrompt: string): string {
|
|
7
|
+
if (systemPrompt.includes(EXPLAIN_REMINDER_HEADING)) {
|
|
8
|
+
return systemPrompt;
|
|
9
|
+
}
|
|
10
|
+
return systemPrompt.length === 0
|
|
11
|
+
? EXPLAIN_REMINDER
|
|
12
|
+
: `${systemPrompt}\n\n${EXPLAIN_REMINDER}`;
|
|
13
|
+
}
|
|
@@ -39,7 +39,7 @@ async function waitForSettle(pi: ExtensionAPI, ctx: ExtensionContext): Promise<v
|
|
|
39
39
|
await Promise.all(request.waits);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export const SETTLE_PRIORITY = { review: 0, persona: 1
|
|
42
|
+
export const SETTLE_PRIORITY = { review: 0, persona: 1 } as const;
|
|
43
43
|
|
|
44
44
|
interface SettleSupplement {
|
|
45
45
|
readonly customType: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rmrdeveloper/sideroom-pi",
|
|
3
|
-
"version": "9.
|
|
4
|
-
"description": "Make \"done\" mean done for Pi. Asks before it guesses, enforces your coding rules, and
|
|
3
|
+
"version": "9.2.0",
|
|
4
|
+
"description": "Make \"done\" mean done for Pi. Asks before it guesses, enforces your coding rules, and reviews changes before finishing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"extensions",
|
|
@@ -104,7 +104,7 @@ At most three steers are sent per agent run.
|
|
|
104
104
|
- No persisted profile state, no profiles, no switching: the persona ships with the package.
|
|
105
105
|
- Nothing is written to the target repository.
|
|
106
106
|
- The persona governs wording. It never relaxes the coding guidelines, the
|
|
107
|
-
added-line rules, or the
|
|
107
|
+
added-line rules, or the project's verification requirements.
|
|
108
108
|
|
|
109
109
|
## References
|
|
110
110
|
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ExtensionAPI,
|
|
3
|
-
isEditToolResult,
|
|
4
|
-
isWriteToolResult,
|
|
5
|
-
} from '@earendil-works/pi-coding-agent';
|
|
6
|
-
import { registerSettleSupplement, startsUserTurn } from '../shared/settle.ts';
|
|
7
|
-
import {
|
|
8
|
-
applyOfferDecision,
|
|
9
|
-
decideOffer,
|
|
10
|
-
EXPLAIN_DECISION,
|
|
11
|
-
EXPLAIN_OFFER,
|
|
12
|
-
EXPLAIN_OFFER_TYPE,
|
|
13
|
-
type ExplainState,
|
|
14
|
-
mutationPathKey,
|
|
15
|
-
recordMutation,
|
|
16
|
-
resetExplainTurn,
|
|
17
|
-
} from './model.ts';
|
|
18
|
-
|
|
19
|
-
interface FileToolInput {
|
|
20
|
-
readonly path: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function registerExplainGuard(
|
|
24
|
-
pi: ExtensionAPI,
|
|
25
|
-
state: ExplainState,
|
|
26
|
-
): void {
|
|
27
|
-
pi.on('input', (event) => {
|
|
28
|
-
if (!startsUserTurn(event)) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
resetExplainTurn(state);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
pi.on('tool_result', (event, ctx) => {
|
|
35
|
-
if (event.isError) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
if (!isEditToolResult(event) && !isWriteToolResult(event)) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const input = event.input as unknown as FileToolInput;
|
|
43
|
-
const pathKey = mutationPathKey(ctx.cwd, input.path);
|
|
44
|
-
if (pathKey === undefined) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
recordMutation(state, pathKey);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
registerSettleSupplement(pi, (ctx) => {
|
|
51
|
-
if (decideOffer(state, ctx.mode) !== EXPLAIN_DECISION.send) {
|
|
52
|
-
return undefined;
|
|
53
|
-
}
|
|
54
|
-
applyOfferDecision(state, EXPLAIN_DECISION.send);
|
|
55
|
-
return {
|
|
56
|
-
customType: EXPLAIN_OFFER_TYPE,
|
|
57
|
-
content: `After finishing the requested work, review, and checks: ${EXPLAIN_OFFER}`,
|
|
58
|
-
};
|
|
59
|
-
});
|
|
60
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { resolveFileToolPath } from '../shared/file-path.ts';
|
|
2
|
-
|
|
3
|
-
export const EXPLAIN_OFFER_TYPE = 'sideroom-explain-offer';
|
|
4
|
-
|
|
5
|
-
export const EXPLAIN_FILE_THRESHOLD = 5;
|
|
6
|
-
|
|
7
|
-
const TUI_MODE = 'tui';
|
|
8
|
-
|
|
9
|
-
export const EXPLAIN_OFFER =
|
|
10
|
-
"Use sideroom_ask for one question in the user's language with four parallel options: changes only, test steps only, both, or no explanation. Recommend changes only.";
|
|
11
|
-
|
|
12
|
-
export const EXPLAIN_DECISION = {
|
|
13
|
-
send: 'send',
|
|
14
|
-
none: 'none',
|
|
15
|
-
} as const;
|
|
16
|
-
|
|
17
|
-
export type ExplainDecision =
|
|
18
|
-
(typeof EXPLAIN_DECISION)[keyof typeof EXPLAIN_DECISION];
|
|
19
|
-
|
|
20
|
-
export interface ExplainState {
|
|
21
|
-
mutatedFilesThisTurn: Set<string>;
|
|
22
|
-
offeredThisTurn: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function createExplainState(): ExplainState {
|
|
26
|
-
return {
|
|
27
|
-
mutatedFilesThisTurn: new Set(),
|
|
28
|
-
offeredThisTurn: false,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function resetExplainTurn(state: ExplainState): void {
|
|
33
|
-
state.mutatedFilesThisTurn.clear();
|
|
34
|
-
state.offeredThisTurn = false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function mutationPathKey(cwd: string, path: string): string | undefined {
|
|
38
|
-
return resolveFileToolPath(cwd, path);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function recordMutation(state: ExplainState, pathKey: string): void {
|
|
42
|
-
state.mutatedFilesThisTurn.add(pathKey);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function decideOffer(
|
|
46
|
-
state: ExplainState,
|
|
47
|
-
mode: string,
|
|
48
|
-
): ExplainDecision {
|
|
49
|
-
const thresholdReached =
|
|
50
|
-
mode === TUI_MODE &&
|
|
51
|
-
!state.offeredThisTurn &&
|
|
52
|
-
state.mutatedFilesThisTurn.size >= EXPLAIN_FILE_THRESHOLD;
|
|
53
|
-
if (thresholdReached) {
|
|
54
|
-
return EXPLAIN_DECISION.send;
|
|
55
|
-
}
|
|
56
|
-
return EXPLAIN_DECISION.none;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function applyOfferDecision(
|
|
60
|
-
state: ExplainState,
|
|
61
|
-
decision: ExplainDecision,
|
|
62
|
-
): void {
|
|
63
|
-
if (decision === EXPLAIN_DECISION.send) {
|
|
64
|
-
state.offeredThisTurn = true;
|
|
65
|
-
}
|
|
66
|
-
}
|