@akagilnc/pi-workflow-roles 0.1.2026 → 0.1.2033
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compliance-transport.js +24 -19
- package/dist/evidence-child-executor.js +4 -0
- package/dist/package-owned-tool-idle.js +66 -4
- package/dist/public-cli/main.js +4 -0
- package/package.json +1 -1
- package/src/compliance-transport.ts +24 -19
- package/src/evidence-child-executor.ts +4 -0
- package/src/package-owned-tool-idle.ts +64 -7
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { executeAuditorChild, } from "./evidence-child-executor.js";
|
|
3
3
|
import { createAuditorDossierTool } from "./auditor-dossier-tool.js";
|
|
4
|
+
import { withPackageOwnedToolIdleSuspended } from "./package-owned-tool-idle.js";
|
|
4
5
|
/** Zero-projection kickoff — soul already carries dossier-fetch duty; no hand-delivered materials. */
|
|
5
6
|
export const AUDITOR_DOSSIER_PROMPT = "Audit the current run dossier.";
|
|
6
7
|
const nonblank = Type.String({ minLength: 1, pattern: "\\S" });
|
|
@@ -61,24 +62,28 @@ export function readComplianceCandidate(arguments_, usage) {
|
|
|
61
62
|
return { status: "audit-incomplete", observation: { kind: "object-status-unreadable", status: status === undefined ? "missing" : "unknown" }, candidate: arguments_, ...(usage === undefined ? {} : { usage }) };
|
|
62
63
|
}
|
|
63
64
|
export async function runComplianceAudit(options) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
// #339: only the real compliance-audit await leaves the outer package-owned
|
|
66
|
+
// idle owner. Pre/post-audit work stays under the single outer backstop.
|
|
67
|
+
return withPackageOwnedToolIdleSuspended(async () => {
|
|
68
|
+
const prompt = options.serializedInput ?? AUDITOR_DOSSIER_PROMPT;
|
|
69
|
+
const receipt = await executeAuditorChild({
|
|
70
|
+
tool: options.tool,
|
|
71
|
+
dossierTool: createAuditorDossierTool(options.runDirectory),
|
|
72
|
+
systemPrompt: options.systemPrompt,
|
|
73
|
+
prompt,
|
|
74
|
+
roleLabel: options.roleLabel,
|
|
75
|
+
context: options.context,
|
|
76
|
+
retainResponse: (response) => retainComplianceResponse(options.context, response),
|
|
77
|
+
...(options.runCompletion === undefined ? {} : { runCompletion: options.runCompletion }),
|
|
78
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
79
|
+
});
|
|
80
|
+
if (receipt.noReceiptLifecycle !== undefined) {
|
|
81
|
+
return {
|
|
82
|
+
status: "no-receipt",
|
|
83
|
+
...receipt.noReceiptLifecycle,
|
|
84
|
+
...(receipt.response.usage === undefined ? {} : { usage: receipt.response.usage }),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return readComplianceCandidate(receipt.decision, receipt.response.usage);
|
|
75
88
|
});
|
|
76
|
-
if (receipt.noReceiptLifecycle !== undefined) {
|
|
77
|
-
return {
|
|
78
|
-
status: "no-receipt",
|
|
79
|
-
...receipt.noReceiptLifecycle,
|
|
80
|
-
...(receipt.response.usage === undefined ? {} : { usage: receipt.response.usage }),
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
return readComplianceCandidate(receipt.decision, receipt.response.usage);
|
|
84
89
|
}
|
|
@@ -296,6 +296,10 @@ export async function createInheritedRuntime(options) {
|
|
|
296
296
|
},
|
|
297
297
|
};
|
|
298
298
|
runtime.registerNativeProvider(provider);
|
|
299
|
+
// registerNativeProvider fires a background refresh; await it so child
|
|
300
|
+
// AgentSession.prompt sees configured auth without racing void refresh
|
|
301
|
+
// (mock timers / slow CI otherwise stall before the compliance stream).
|
|
302
|
+
await runtime.refresh({ allowNetwork: false });
|
|
299
303
|
return state;
|
|
300
304
|
}
|
|
301
305
|
function numericHttpStatus(value) {
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #102 package-owned tool idle backstop.
|
|
3
|
+
*
|
|
4
|
+
* Fixed 183000ms silence clock on package-owned tool execute only.
|
|
5
|
+
* Real producing onUpdate resets; final resolve/reject clears; timeout throws so
|
|
6
|
+
* Pi settles the current call as an LLM-visible isError tool result. No retry,
|
|
7
|
+
* role failure, process termination, signal abort, config, or Pi built-in coverage.
|
|
8
|
+
*
|
|
9
|
+
* #339: do not name-exempt whole terminating tools. Outer idle stays armed for
|
|
10
|
+
* pre/post-audit work. Only the real compliance-audit await suspends this single
|
|
11
|
+
* layer (ADR 0059 owns that interval); resume re-arms the same outer backstop.
|
|
12
|
+
*/
|
|
13
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
1
14
|
import { DEFAULT_STREAM_IDLE_TIMEOUT_MS, createStreamIdleGuard, } from "./stream-idle-guard.js";
|
|
2
15
|
import { isProducingToolUpdate } from "./tool-execution-observation.js";
|
|
3
16
|
export const PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_MS = DEFAULT_STREAM_IDLE_TIMEOUT_MS;
|
|
4
17
|
export const PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_CODE = "AK_PACKAGE_OWNED_TOOL_IDLE_TIMEOUT";
|
|
5
18
|
const WRAPPED = Symbol.for("ak.packageOwnedToolIdleWrapped");
|
|
19
|
+
/**
|
|
20
|
+
* Active outer package-owned execute idle, if any. Nested tool executes install
|
|
21
|
+
* their own store; compliance audit only suspends the store visible at await time.
|
|
22
|
+
*/
|
|
23
|
+
const packageOwnedToolIdleScope = new AsyncLocalStorage();
|
|
6
24
|
export class PackageOwnedToolIdleTimeoutError extends Error {
|
|
7
25
|
code = PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_CODE;
|
|
8
26
|
idleTimeoutMs = PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_MS;
|
|
@@ -33,6 +51,23 @@ function isPackageOwnedToolActivityUpdate(partialResult) {
|
|
|
33
51
|
return Reflect.ownKeys(details).length > 0;
|
|
34
52
|
return true;
|
|
35
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* #339: suspend the active package-owned execute idle for one real compliance
|
|
56
|
+
* audit await. Single-layer only — production has one runComplianceAudit seam.
|
|
57
|
+
* No-op outside a wrapped package-owned execute. No second timeout or retry.
|
|
58
|
+
*/
|
|
59
|
+
export async function withPackageOwnedToolIdleSuspended(run) {
|
|
60
|
+
const scope = packageOwnedToolIdleScope.getStore();
|
|
61
|
+
if (scope === undefined)
|
|
62
|
+
return run();
|
|
63
|
+
scope.suspend();
|
|
64
|
+
try {
|
|
65
|
+
return await run();
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
scope.resume();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
36
71
|
/**
|
|
37
72
|
* Single shared execute wrapper for package-owned tool definitions.
|
|
38
73
|
* Idempotent: wrapping twice returns the same protected definition.
|
|
@@ -48,7 +83,8 @@ export function wrapPackageOwnedToolDefinition(tool) {
|
|
|
48
83
|
const onUpdate = args[3];
|
|
49
84
|
return new Promise((resolve, reject) => {
|
|
50
85
|
let settled = false;
|
|
51
|
-
|
|
86
|
+
let suspended = false;
|
|
87
|
+
let idle = createStreamIdleGuard({
|
|
52
88
|
idleTimeoutMs: PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_MS,
|
|
53
89
|
});
|
|
54
90
|
const settle = (deliver) => {
|
|
@@ -63,6 +99,26 @@ export function wrapPackageOwnedToolDefinition(tool) {
|
|
|
63
99
|
settle(() => reject(new PackageOwnedToolIdleTimeoutError()));
|
|
64
100
|
};
|
|
65
101
|
idle.signal.addEventListener("abort", onIdle, { once: true });
|
|
102
|
+
const suspension = {
|
|
103
|
+
suspend() {
|
|
104
|
+
if (settled || suspended)
|
|
105
|
+
return;
|
|
106
|
+
suspended = true;
|
|
107
|
+
// ADR 0059 owns the audit interval — drop this layer until audit returns.
|
|
108
|
+
idle.signal.removeEventListener("abort", onIdle);
|
|
109
|
+
idle.dispose();
|
|
110
|
+
},
|
|
111
|
+
resume() {
|
|
112
|
+
if (settled || !suspended)
|
|
113
|
+
return;
|
|
114
|
+
suspended = false;
|
|
115
|
+
// Fresh single-layer silence window for post-audit work (e.g. cleanup).
|
|
116
|
+
idle = createStreamIdleGuard({
|
|
117
|
+
idleTimeoutMs: PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_MS,
|
|
118
|
+
});
|
|
119
|
+
idle.signal.addEventListener("abort", onIdle, { once: true });
|
|
120
|
+
},
|
|
121
|
+
};
|
|
66
122
|
const guardedOnUpdate = onUpdate === undefined
|
|
67
123
|
? undefined
|
|
68
124
|
: (partialResult) => {
|
|
@@ -76,9 +132,15 @@ export function wrapPackageOwnedToolDefinition(tool) {
|
|
|
76
132
|
// Preserve the original signal at args[2]; timeout must not abort it.
|
|
77
133
|
callArgs[2] = signal;
|
|
78
134
|
callArgs[3] = guardedOnUpdate;
|
|
79
|
-
void
|
|
80
|
-
|
|
81
|
-
|
|
135
|
+
void packageOwnedToolIdleScope.run(suspension, async () => {
|
|
136
|
+
try {
|
|
137
|
+
const result = await originalExecute(...callArgs);
|
|
138
|
+
settle(() => resolve(result));
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
settle(() => reject(error));
|
|
142
|
+
}
|
|
143
|
+
});
|
|
82
144
|
});
|
|
83
145
|
};
|
|
84
146
|
wrappedExecute[WRAPPED] = true;
|
package/dist/public-cli/main.js
CHANGED
|
@@ -18448,11 +18448,14 @@ var init_tool_execution_observation = __esm({
|
|
|
18448
18448
|
});
|
|
18449
18449
|
|
|
18450
18450
|
// src/package-owned-tool-idle.ts
|
|
18451
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
18452
|
+
var packageOwnedToolIdleScope;
|
|
18451
18453
|
var init_package_owned_tool_idle = __esm({
|
|
18452
18454
|
"src/package-owned-tool-idle.ts"() {
|
|
18453
18455
|
"use strict";
|
|
18454
18456
|
init_stream_idle_guard();
|
|
18455
18457
|
init_tool_execution_observation();
|
|
18458
|
+
packageOwnedToolIdleScope = new AsyncLocalStorage();
|
|
18456
18459
|
}
|
|
18457
18460
|
});
|
|
18458
18461
|
|
|
@@ -18524,6 +18527,7 @@ var init_compliance_transport = __esm({
|
|
|
18524
18527
|
init_build();
|
|
18525
18528
|
init_evidence_child_executor();
|
|
18526
18529
|
init_auditor_dossier_tool();
|
|
18530
|
+
init_package_owned_tool_idle();
|
|
18527
18531
|
nonblank2 = typebox_exports.String({ minLength: 1, pattern: "\\S" });
|
|
18528
18532
|
decisionGateSchema = typebox_exports.Object({ question: nonblank2, options: typebox_exports.Array(nonblank2, { minItems: 1 }) }, { additionalProperties: false });
|
|
18529
18533
|
complianceDecisionSchema = typebox_exports.Object({ status: typebox_exports.Unknown({ description: "Auditor decision status." }), violations: typebox_exports.Array(nonblank2, { description: "Observed compliance violations." }), conflicts: typebox_exports.Array(nonblank2, { description: "Unresolved authority or execution conflicts." }), decisionGate: typebox_exports.Union([decisionGateSchema, typebox_exports.Null()], { description: "Escalation question and available options." }) }, { additionalProperties: true, required: [] });
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from "./evidence-child-executor.ts";
|
|
8
8
|
import { createAuditorDossierTool } from "./auditor-dossier-tool.ts";
|
|
9
9
|
import type { DossierObservation } from "./dossier-resolution.ts";
|
|
10
|
+
import { withPackageOwnedToolIdleSuspended } from "./package-owned-tool-idle.ts";
|
|
10
11
|
import type { NoReceiptLifecycleFacts } from "./receipt-delivery-policy.ts";
|
|
11
12
|
|
|
12
13
|
export type ComplianceCompletion = AuditorCompletion;
|
|
@@ -116,24 +117,28 @@ export type RunComplianceAuditOptions = {
|
|
|
116
117
|
};
|
|
117
118
|
|
|
118
119
|
export async function runComplianceAudit(options: RunComplianceAuditOptions): Promise<ComplianceDecision> {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
// #339: only the real compliance-audit await leaves the outer package-owned
|
|
121
|
+
// idle owner. Pre/post-audit work stays under the single outer backstop.
|
|
122
|
+
return withPackageOwnedToolIdleSuspended(async () => {
|
|
123
|
+
const prompt = options.serializedInput ?? AUDITOR_DOSSIER_PROMPT;
|
|
124
|
+
const receipt = await executeAuditorChild({
|
|
125
|
+
tool: options.tool,
|
|
126
|
+
dossierTool: createAuditorDossierTool(options.runDirectory),
|
|
127
|
+
systemPrompt: options.systemPrompt,
|
|
128
|
+
prompt,
|
|
129
|
+
roleLabel: options.roleLabel,
|
|
130
|
+
context: options.context,
|
|
131
|
+
retainResponse: (response) => retainComplianceResponse(options.context, response),
|
|
132
|
+
...(options.runCompletion === undefined ? {} : { runCompletion: options.runCompletion }),
|
|
133
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
134
|
+
});
|
|
135
|
+
if (receipt.noReceiptLifecycle !== undefined) {
|
|
136
|
+
return {
|
|
137
|
+
status: "no-receipt",
|
|
138
|
+
...receipt.noReceiptLifecycle,
|
|
139
|
+
...(receipt.response.usage === undefined ? {} : { usage: receipt.response.usage }),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return readComplianceCandidate(receipt.decision, receipt.response.usage);
|
|
130
143
|
});
|
|
131
|
-
if (receipt.noReceiptLifecycle !== undefined) {
|
|
132
|
-
return {
|
|
133
|
-
status: "no-receipt",
|
|
134
|
-
...receipt.noReceiptLifecycle,
|
|
135
|
-
...(receipt.response.usage === undefined ? {} : { usage: receipt.response.usage }),
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
return readComplianceCandidate(receipt.decision, receipt.response.usage);
|
|
139
144
|
}
|
|
@@ -381,6 +381,10 @@ export async function createInheritedRuntime(options: InheritedRuntimeOptions):
|
|
|
381
381
|
};
|
|
382
382
|
|
|
383
383
|
runtime.registerNativeProvider(provider);
|
|
384
|
+
// registerNativeProvider fires a background refresh; await it so child
|
|
385
|
+
// AgentSession.prompt sees configured auth without racing void refresh
|
|
386
|
+
// (mock timers / slow CI otherwise stall before the compliance stream).
|
|
387
|
+
await runtime.refresh({ allowNetwork: false });
|
|
384
388
|
return state;
|
|
385
389
|
}
|
|
386
390
|
|
|
@@ -5,12 +5,18 @@
|
|
|
5
5
|
* Real producing onUpdate resets; final resolve/reject clears; timeout throws so
|
|
6
6
|
* Pi settles the current call as an LLM-visible isError tool result. No retry,
|
|
7
7
|
* role failure, process termination, signal abort, config, or Pi built-in coverage.
|
|
8
|
+
*
|
|
9
|
+
* #339: do not name-exempt whole terminating tools. Outer idle stays armed for
|
|
10
|
+
* pre/post-audit work. Only the real compliance-audit await suspends this single
|
|
11
|
+
* layer (ADR 0059 owns that interval); resume re-arms the same outer backstop.
|
|
8
12
|
*/
|
|
13
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
14
|
import type { ExtensionAPI, ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
10
15
|
|
|
11
16
|
import {
|
|
12
17
|
DEFAULT_STREAM_IDLE_TIMEOUT_MS,
|
|
13
18
|
createStreamIdleGuard,
|
|
19
|
+
type StreamIdleGuard,
|
|
14
20
|
} from "./stream-idle-guard.ts";
|
|
15
21
|
import { isProducingToolUpdate } from "./tool-execution-observation.ts";
|
|
16
22
|
|
|
@@ -19,6 +25,17 @@ export const PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_CODE = "AK_PACKAGE_OWNED_TOOL_IDLE_
|
|
|
19
25
|
|
|
20
26
|
const WRAPPED = Symbol.for("ak.packageOwnedToolIdleWrapped");
|
|
21
27
|
|
|
28
|
+
type PackageOwnedToolIdleSuspension = {
|
|
29
|
+
suspend(): void;
|
|
30
|
+
resume(): void;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Active outer package-owned execute idle, if any. Nested tool executes install
|
|
35
|
+
* their own store; compliance audit only suspends the store visible at await time.
|
|
36
|
+
*/
|
|
37
|
+
const packageOwnedToolIdleScope = new AsyncLocalStorage<PackageOwnedToolIdleSuspension>();
|
|
38
|
+
|
|
22
39
|
export class PackageOwnedToolIdleTimeoutError extends Error {
|
|
23
40
|
readonly code = PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_CODE;
|
|
24
41
|
readonly idleTimeoutMs = PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_MS;
|
|
@@ -52,6 +69,24 @@ function isPackageOwnedToolActivityUpdate(partialResult: unknown): boolean {
|
|
|
52
69
|
return true;
|
|
53
70
|
}
|
|
54
71
|
|
|
72
|
+
/**
|
|
73
|
+
* #339: suspend the active package-owned execute idle for one real compliance
|
|
74
|
+
* audit await. Single-layer only — production has one runComplianceAudit seam.
|
|
75
|
+
* No-op outside a wrapped package-owned execute. No second timeout or retry.
|
|
76
|
+
*/
|
|
77
|
+
export async function withPackageOwnedToolIdleSuspended<T>(
|
|
78
|
+
run: () => Promise<T>,
|
|
79
|
+
): Promise<T> {
|
|
80
|
+
const scope = packageOwnedToolIdleScope.getStore();
|
|
81
|
+
if (scope === undefined) return run();
|
|
82
|
+
scope.suspend();
|
|
83
|
+
try {
|
|
84
|
+
return await run();
|
|
85
|
+
} finally {
|
|
86
|
+
scope.resume();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
55
90
|
/**
|
|
56
91
|
* Single shared execute wrapper for package-owned tool definitions.
|
|
57
92
|
* Idempotent: wrapping twice returns the same protected definition.
|
|
@@ -72,7 +107,8 @@ export function wrapPackageOwnedToolDefinition<T extends PackageOwnedToolLike>(t
|
|
|
72
107
|
const onUpdate = args[3] as ((partialResult: unknown) => void) | undefined;
|
|
73
108
|
return new Promise((resolve, reject) => {
|
|
74
109
|
let settled = false;
|
|
75
|
-
|
|
110
|
+
let suspended = false;
|
|
111
|
+
let idle: StreamIdleGuard = createStreamIdleGuard({
|
|
76
112
|
idleTimeoutMs: PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_MS,
|
|
77
113
|
});
|
|
78
114
|
|
|
@@ -88,6 +124,25 @@ export function wrapPackageOwnedToolDefinition<T extends PackageOwnedToolLike>(t
|
|
|
88
124
|
};
|
|
89
125
|
idle.signal.addEventListener("abort", onIdle, { once: true });
|
|
90
126
|
|
|
127
|
+
const suspension: PackageOwnedToolIdleSuspension = {
|
|
128
|
+
suspend(): void {
|
|
129
|
+
if (settled || suspended) return;
|
|
130
|
+
suspended = true;
|
|
131
|
+
// ADR 0059 owns the audit interval — drop this layer until audit returns.
|
|
132
|
+
idle.signal.removeEventListener("abort", onIdle);
|
|
133
|
+
idle.dispose();
|
|
134
|
+
},
|
|
135
|
+
resume(): void {
|
|
136
|
+
if (settled || !suspended) return;
|
|
137
|
+
suspended = false;
|
|
138
|
+
// Fresh single-layer silence window for post-audit work (e.g. cleanup).
|
|
139
|
+
idle = createStreamIdleGuard({
|
|
140
|
+
idleTimeoutMs: PACKAGE_OWNED_TOOL_IDLE_TIMEOUT_MS,
|
|
141
|
+
});
|
|
142
|
+
idle.signal.addEventListener("abort", onIdle, { once: true });
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
|
|
91
146
|
const guardedOnUpdate = onUpdate === undefined
|
|
92
147
|
? undefined
|
|
93
148
|
: (partialResult: unknown) => {
|
|
@@ -101,12 +156,14 @@ export function wrapPackageOwnedToolDefinition<T extends PackageOwnedToolLike>(t
|
|
|
101
156
|
callArgs[2] = signal;
|
|
102
157
|
callArgs[3] = guardedOnUpdate;
|
|
103
158
|
|
|
104
|
-
void
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
159
|
+
void packageOwnedToolIdleScope.run(suspension, async () => {
|
|
160
|
+
try {
|
|
161
|
+
const result = await originalExecute(...callArgs);
|
|
162
|
+
settle(() => resolve(result));
|
|
163
|
+
} catch (error) {
|
|
164
|
+
settle(() => reject(error));
|
|
165
|
+
}
|
|
166
|
+
});
|
|
110
167
|
});
|
|
111
168
|
};
|
|
112
169
|
(wrappedExecute as { [WRAPPED]?: boolean })[WRAPPED] = true;
|