bareloop 0.1.0 → 0.3.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/CHANGELOG.md +425 -2
- package/NOTICE +13 -0
- package/README.md +8 -6
- package/bareloop.context.md +334 -19
- package/package.json +4 -3
- package/src/extract.js +14 -6
- package/src/index.js +16 -2
- package/src/interpret.js +538 -46
- package/src/job.js +368 -0
- package/src/ledger.js +266 -0
- package/src/ralph.js +251 -14
- package/src/run.js +478 -0
- package/src/text.js +65 -8
- package/src/validate.js +175 -16
- package/types/extract.d.ts +4 -2
- package/types/index.d.ts +5 -2
- package/types/interpret.d.ts +44 -6
- package/types/job.d.ts +88 -0
- package/types/ledger.d.ts +76 -0
- package/types/ralph.d.ts +123 -17
- package/types/run.d.ts +58 -0
- package/types/text.d.ts +35 -1
- package/types/validate.d.ts +51 -7
package/types/ralph.d.ts
CHANGED
|
@@ -1,23 +1,86 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Run a close command; its exit code is the verdict (hard green, PRD §4).
|
|
3
|
-
*
|
|
3
|
+
* `expect` → satisfied; any other exit → needs_revision (gap fed back).
|
|
4
|
+
*
|
|
5
|
+
* THE FORBIDDEN ZONE (PRD v1.11, F17; adaptlearn F25/V10). The two clean bands
|
|
6
|
+
* are green (exit == expect, judgment rendered) and red (exit != expect,
|
|
7
|
+
* judgment rendered). Every other outcome rendered NO JUDGMENT and is therefore
|
|
8
|
+
* NOT A VERDICT — it gets its own name and escalates; coercing one into a
|
|
9
|
+
* verdict IS the instrument fault (law #8 generalized):
|
|
10
|
+
* - `failed` — the close cannot RUN (spawn error). → broken-close
|
|
11
|
+
* - `timed-out` — it ran and never finished judging. → close-timeout
|
|
12
|
+
* - `killed` — it died by signal (status null, no spawn error). → close-killed
|
|
13
|
+
* - `crashed` — it ran, exited, and judged nothing. → close-crashed
|
|
14
|
+
* `timed-out` is split OUT of `failed` deliberately: "raise the timeout" and
|
|
15
|
+
* "fix the argv" are different human decisions, so pooling them erases the
|
|
16
|
+
* decision information the escalation exists to carry.
|
|
17
|
+
*
|
|
18
|
+
* `judged` is the judgment-rendered signal, and it is the hard one. Exit code
|
|
19
|
+
* ALONE cannot separate a crash-at-load from an honest red — they are
|
|
20
|
+
* byte-identical at this seam, and against `node --test` so are the test counts
|
|
21
|
+
* (node synthesizes ONE failing test for the file that crashed, so a crash
|
|
22
|
+
* reports `tests 1 / fail 1`, exactly like a one-assertion failure). So the
|
|
23
|
+
* signal cannot be "zero judged"; it must be a FLOOR against a declared
|
|
24
|
+
* baseline: litectx runs ~390 tests, and a run claiming it judged 1 did not
|
|
25
|
+
* judge. `judged.pattern` extracts one integer from the close's own (redacted)
|
|
26
|
+
* output; below `judged.min` the close crashed, WHATEVER its exit code says —
|
|
27
|
+
* and that check runs on the GREEN side too: a close that exits 0 having judged
|
|
28
|
+
* nothing is a confident fake green, the only real failure there is (law #8).
|
|
29
|
+
* `judged` is OPTIONAL — a linter or a hitl close may have no count to give —
|
|
30
|
+
* and its absence stamps `unaudited: true` so the blind spot is NAMED on the
|
|
31
|
+
* record rather than passed off as a trustworthy exit code.
|
|
32
|
+
*
|
|
33
|
+
* `redact` scrubs the close's own output at the SOURCE — before the gap becomes
|
|
34
|
+
* a spine event or a worker prompt — so a secret a checked command echoes
|
|
35
|
+
* (a 401 dumping an `Authorization: Bearer …` header) never enters the
|
|
36
|
+
* append-only spine (the hard line). It is INJECTED, not imported: the shell
|
|
37
|
+
* stays stdlib-only and un-gameable, and the redactor is a fixed shell
|
|
38
|
+
* primitive (bareguard's, wired by the interpreter), never an emergent
|
|
39
|
+
* component — so V4 holds. The shell's canonical emission IS the redacted text;
|
|
40
|
+
* a benign gap is returned byte-identical (default: identity).
|
|
41
|
+
* `cwd` is where the close RUNS, and it is load-bearing (F8): a close is a
|
|
42
|
+
* command in a repository — `npm test`, `make check` — and every one of them is
|
|
43
|
+
* cwd-relative. Run it anywhere but the workdir and the arbiter judges the wrong
|
|
44
|
+
* tree: exit-code-is-truth silently becomes exit-code-of-some-other-repo-is-truth.
|
|
45
|
+
* The default (the runner's own cwd) exists only for callers with an absolute
|
|
46
|
+
* close; the runner and the interpreter always pass the workdir.
|
|
47
|
+
*
|
|
48
|
+
* `gapKeep` (F28) is a regex SOURCE whose matching lines are PRESERVED through
|
|
49
|
+
* the gap bound in addition to the head/tail sample: a large TAP suite prints
|
|
50
|
+
* its `not ok` lines in the middle of the stream, exactly where `boundGap`
|
|
51
|
+
* elides — so the failing-test NAMES (the causal input the worker navigates on)
|
|
52
|
+
* were deleted in transit and the worker was told "5 fail" and never WHICH. It
|
|
53
|
+
* is arbiter territory like the rest here: the drafted config cannot express it.
|
|
54
|
+
*
|
|
4
55
|
* @param {string[]} close argv, e.g. ['node', '--test', 'close/']
|
|
56
|
+
* @param {(s: string) => string} [redact] source scrubber; identity by default
|
|
57
|
+
* @param {{ timeoutMs?: number, cwd?: string, expect?: number, judged?: {pattern: string, min: number}, gapKeep?: string }} [opts]
|
|
58
|
+
* close wall-clock cap (operator-set via the runner, never the config's — the
|
|
59
|
+
* agent must not author its arbiter's clock), the directory the close runs in
|
|
60
|
+
* (the workdir — the tree it is judging), the exit code the SIGNED spec calls
|
|
61
|
+
* success, the judgment-rendered signal, and the kept-failures pattern. All
|
|
62
|
+
* five are arbiter territory: the drafted workflow config cannot express any.
|
|
63
|
+
* @returns {{verdict: 'satisfied'|'needs_revision'|'failed'|'timed-out'|'killed'|'crashed',
|
|
64
|
+
* gap?: string, exitCode?: number, signal?: string, detail?: string,
|
|
65
|
+
* judgedCount?: number|null, unaudited?: boolean}}
|
|
5
66
|
*/
|
|
6
|
-
export function runClose(close: string[]
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
detail?:
|
|
67
|
+
export function runClose(close: string[], redact?: (s: string) => string, { timeoutMs, cwd, expect, judged, gapKeep }?: {
|
|
68
|
+
timeoutMs?: number;
|
|
69
|
+
cwd?: string;
|
|
70
|
+
expect?: number;
|
|
71
|
+
judged?: {
|
|
72
|
+
pattern: string;
|
|
73
|
+
min: number;
|
|
74
|
+
};
|
|
75
|
+
gapKeep?: string;
|
|
76
|
+
}): {
|
|
77
|
+
verdict: "satisfied" | "needs_revision" | "failed" | "timed-out" | "killed" | "crashed";
|
|
78
|
+
gap?: string;
|
|
79
|
+
exitCode?: number;
|
|
80
|
+
signal?: string;
|
|
81
|
+
detail?: string;
|
|
82
|
+
judgedCount?: number | null;
|
|
83
|
+
unaudited?: boolean;
|
|
21
84
|
};
|
|
22
85
|
/**
|
|
23
86
|
* The loop: `while close-red and under-cap: run the middle`. Stops at first
|
|
@@ -38,11 +101,54 @@ export function runClose(close: string[]): {
|
|
|
38
101
|
* @param {string[]} opts.close argv whose exit code is truth
|
|
39
102
|
* @param {number} opts.capRuns budget: max middle runs
|
|
40
103
|
* @param {(type: string, data?: object) => object} opts.emit a spine emitter
|
|
104
|
+
* @param {(s: string) => string} [opts.redact] source scrubber for close output
|
|
105
|
+
* (secrets never enter the spine); injected so the shell stays stdlib-only
|
|
106
|
+
* @param {number} [opts.closeTimeoutMs] close wall-clock cap (shell/operator
|
|
107
|
+
* territory — the workflow config cannot express it)
|
|
108
|
+
* @param {string} [opts.cwd] the directory every close runs in — the tree it is
|
|
109
|
+
* judging (F8: a cwd-relative close run elsewhere judges the wrong repository)
|
|
110
|
+
* @param {number} [opts.expect] the exit code the SIGNED spec calls success
|
|
111
|
+
* @param {{pattern: string, min: number}} [opts.judged] the judgment-rendered signal
|
|
112
|
+
* @param {string} [opts.gapKeep] kept-failures pattern (F28): matching close-output
|
|
113
|
+
* lines survive the gap bound so a large suite's `not ok` names reach the worker
|
|
114
|
+
* @param {() => string[]} [opts.workerWrites] the crash-attribution instrument (F32):
|
|
115
|
+
* answers "which files has the WORKER written so far this run?" — the runner wires
|
|
116
|
+
* it to the gate audit's allow-decision writes. Injected like `redact` so the shell
|
|
117
|
+
* stays stdlib-only and dumb; consulted ONLY at a crashed verdict. With no seam, or
|
|
118
|
+
* with zero writes, a crash stays what it always was: an instrument stop.
|
|
41
119
|
* @returns {Promise<'green'|'escalated'>}
|
|
42
120
|
*/
|
|
43
|
-
export function ralph({ middle, close, capRuns, emit }: {
|
|
121
|
+
export function ralph({ middle, close, capRuns, emit, redact, closeTimeoutMs, cwd, expect, judged, gapKeep, workerWrites }: {
|
|
44
122
|
middle: (iteration: number, gap?: string) => void | Promise<void>;
|
|
45
123
|
close: string[];
|
|
46
124
|
capRuns: number;
|
|
47
125
|
emit: (type: string, data?: object) => object;
|
|
126
|
+
redact?: ((s: string) => string) | undefined;
|
|
127
|
+
closeTimeoutMs?: number | undefined;
|
|
128
|
+
cwd?: string | undefined;
|
|
129
|
+
expect?: number | undefined;
|
|
130
|
+
judged?: {
|
|
131
|
+
pattern: string;
|
|
132
|
+
min: number;
|
|
133
|
+
} | undefined;
|
|
134
|
+
gapKeep?: string | undefined;
|
|
135
|
+
workerWrites?: (() => string[]) | undefined;
|
|
48
136
|
}): Promise<"green" | "escalated">;
|
|
137
|
+
/**
|
|
138
|
+
* The forbidden zone, named (PRD v1.11). Each row is an outcome in which the
|
|
139
|
+
* close rendered NO JUDGMENT — so it is not a verdict, it never feeds a gap
|
|
140
|
+
* back, and it is never retried. They are kept SEPARATE on purpose: pooling
|
|
141
|
+
* them would erase the decision information the escalation exists to carry —
|
|
142
|
+
* "raise the timeout", "fix the argv", and "re-run, it was OOM-killed" are
|
|
143
|
+
* three different human answers.
|
|
144
|
+
* Exported because the RUNNER's close-first precheck runs the same arbiter
|
|
145
|
+
* before any tokens: two maps would be two instruments, and two instruments
|
|
146
|
+
* disagreeing about the same outcome is the fault this whole addendum exists
|
|
147
|
+
* to close.
|
|
148
|
+
* @type {Record<string, {category: string, decision: string, options: string[]}>}
|
|
149
|
+
*/
|
|
150
|
+
export const CLOSE_FAULTS: Record<string, {
|
|
151
|
+
category: string;
|
|
152
|
+
decision: string;
|
|
153
|
+
options: string[];
|
|
154
|
+
}>;
|
package/types/run.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run an approved job end to end: approval gate → primitive smoke → sequential
|
|
3
|
+
* per-step interpret loops under the one ledger → the hitl step opens the draft
|
|
4
|
+
* PR (deterministic git, never model tools) and becomes the decision-ready
|
|
5
|
+
* escalation. Every predicate step runs its close FIRST (close-first skip,
|
|
6
|
+
* resume model): already-green skips the step for zero tokens as a distinct
|
|
7
|
+
* spine record, so a stopped run reruns from where it died — the workdir plus
|
|
8
|
+
* the closes are the checkpoint. The sealed config draft (one shot + one
|
|
9
|
+
* redraft) is deferred to the first step that actually needs a worker; a clean
|
|
10
|
+
* rerun pays zero provider calls.
|
|
11
|
+
*
|
|
12
|
+
* N2 bounds (honest, documented): text-mode steps write a single `target`
|
|
13
|
+
* artifact; tool-mode steps (2b) work multi-file through the gated shell tools,
|
|
14
|
+
* granted per step by the SPEC (mode/tools — the drafted config cannot express
|
|
15
|
+
* either); `gold`/`rubric` closes refuse `close-unsupported` (execution lands
|
|
16
|
+
* with the verdict classes, N4); the pricing-red halt lands at the step
|
|
17
|
+
* boundary — the Gate still caps within a step, but an unpriced result cannot
|
|
18
|
+
* be summed, so the run stops rather than counting it $0 (F6).
|
|
19
|
+
*
|
|
20
|
+
* @param {object|string} rawSpec the job spec (job-v1), text or parsed
|
|
21
|
+
* @param {object} opts
|
|
22
|
+
* @param {unknown} opts.approvals `{ specHash, signer, ts }` records (from OUTSIDE the spec)
|
|
23
|
+
* @param {string} opts.workdir the run directory (the fence's root)
|
|
24
|
+
* @param {string} [opts.target] the step artifact path (text-mode steps; unused by tool-mode steps)
|
|
25
|
+
* @param {any} opts.provider shell-owned LLM binding (never the config's)
|
|
26
|
+
* @param {(type: string, data?: object) => object} opts.emit spine emitter
|
|
27
|
+
* @param {number} [opts.capRuns] shell-owned per-step iteration cap
|
|
28
|
+
* @param {number} [opts.shellCapUsd] the shell's hard USD ceiling
|
|
29
|
+
* @param {number} [opts.closeTimeoutMs] close wall-clock cap (shell territory)
|
|
30
|
+
* @param {ExecCmd} [opts.execCmd] process runner for the hitl PR mechanics
|
|
31
|
+
* (shell-owned seam, same doctrine as the provider binding)
|
|
32
|
+
* @returns {Promise<string>} outcome: 'green' | 'escalated' | 'unapproved-spec' |
|
|
33
|
+
* 'job-red' | 'smoke-red' | 'config-red' | 'pricing-red' | 'provider-red' |
|
|
34
|
+
* 'cap-halt' | 'close-unsupported' | `step-red:<id>`
|
|
35
|
+
*/
|
|
36
|
+
export function runJob(rawSpec: object | string, { approvals, workdir, target, provider, emit, capRuns, shellCapUsd, closeTimeoutMs, execCmd }: {
|
|
37
|
+
approvals: unknown;
|
|
38
|
+
workdir: string;
|
|
39
|
+
target?: string | undefined;
|
|
40
|
+
provider: any;
|
|
41
|
+
emit: (type: string, data?: object) => object;
|
|
42
|
+
capRuns?: number | undefined;
|
|
43
|
+
shellCapUsd?: number | undefined;
|
|
44
|
+
closeTimeoutMs?: number | undefined;
|
|
45
|
+
execCmd?: ExecCmd | undefined;
|
|
46
|
+
}): Promise<string>;
|
|
47
|
+
export type Red = {
|
|
48
|
+
code: string;
|
|
49
|
+
path: string;
|
|
50
|
+
detail?: string;
|
|
51
|
+
};
|
|
52
|
+
export type ExecCmd = (argv: string[], opts?: {
|
|
53
|
+
cwd?: string;
|
|
54
|
+
}) => {
|
|
55
|
+
status: number | null;
|
|
56
|
+
stdout: string;
|
|
57
|
+
stderr: string;
|
|
58
|
+
};
|
package/types/text.d.ts
CHANGED
|
@@ -1 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Fence-robust artifact extraction (F2 port requirements #1/#2):
|
|
3
|
+
* - a fenced block opening within the first {@link FENCE_PREAMBLE_LINES} lines
|
|
4
|
+
* is the artifact — prose-wrapped and preamble fences extract clean (the F21
|
|
5
|
+
* instrument caveat: prose written to the target corrupted the close signal);
|
|
6
|
+
* - a fence opening deeper is the artifact's own content — the trimmed whole
|
|
7
|
+
* text is the artifact (fence-heavy artifacts belong in tool mode, where the
|
|
8
|
+
* worker writes files directly and nothing is parsed);
|
|
9
|
+
* - no fence → the trimmed whole text, with N0's unclosed-leading-fence strip
|
|
10
|
+
* as the fallback (reference parity);
|
|
11
|
+
* - nothing extractable → `code: null` plus a named reason: artifact-red
|
|
12
|
+
* material for the caller's OWN axis, never a silent empty write.
|
|
13
|
+
* Never throws.
|
|
14
|
+
* @param {string|null|undefined} t
|
|
15
|
+
* @returns {{ code: string|null, red: string|null }}
|
|
16
|
+
*/
|
|
17
|
+
export function extractArtifact(t: string | null | undefined): {
|
|
18
|
+
code: string | null;
|
|
19
|
+
red: string | null;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The ONE spelling of the F6 honest-null cost read on a bare-agent result.
|
|
23
|
+
* `metrics.costUsd` is the honest null when NOTHING priced — never fall
|
|
24
|
+
* through to `cost` when metrics exist: `cost` sums priced rounds only, so an
|
|
25
|
+
* all-unpriced run reports cost 0 and `?? cost` would launder the explicit
|
|
26
|
+
* unknown into a silent $0 (the F6 class — four shipped launderings were this
|
|
27
|
+
* exact fallback chain hand-spelled). `unpricedRounds` makes a PARTIALLY
|
|
28
|
+
* unpriced run visible (costUsd finite but an under-count).
|
|
29
|
+
* @param {any} r a Loop.run() result (or null)
|
|
30
|
+
* @returns {{ costUsd: number|null, unpricedRounds: number }}
|
|
31
|
+
*/
|
|
32
|
+
export function priceOf(r: any): {
|
|
33
|
+
costUsd: number | null;
|
|
34
|
+
unpricedRounds: number;
|
|
35
|
+
};
|
package/types/validate.d.ts
CHANGED
|
@@ -9,13 +9,54 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export function globToPrefix(scope: string): string;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* A scope may never reach the arbiter's inputs (design law #1): it must
|
|
13
|
+
* resolve to a PROPER subdirectory of the run directory. Absolute paths and
|
|
14
|
+
* ".." segments escape it; "." / "./**" cover the whole run directory — where
|
|
15
|
+
* the close suite lives. Windows spellings ("..\", "C:\") count as escapes.
|
|
16
|
+
* Exported for the job validator: the operator's outer fence obeys the SAME
|
|
17
|
+
* law through the same code — two containment transforms would be the F9
|
|
18
|
+
* red-class one level up.
|
|
19
|
+
* @param {string} s
|
|
20
|
+
*/
|
|
21
|
+
export function scopeContained(s: string): boolean;
|
|
22
|
+
/** Shared with the job validator — one definition of "a JSON object" for both
|
|
23
|
+
* documents (the sibling-validator drift class).
|
|
24
|
+
* @param {unknown} v */
|
|
25
|
+
export function isObj(v: unknown): boolean;
|
|
26
|
+
/** @param {unknown} v @returns {v is string} */
|
|
27
|
+
export function isNonEmptyString(v: unknown): v is string;
|
|
28
|
+
/**
|
|
29
|
+
* Scan a RAW text stream (a spine file, a close's output, a transcript) for
|
|
30
|
+
* known secret shapes and return the literal matches. The ONE spelling of the
|
|
31
|
+
* text-side scan, for the same reason SECRET_PATTERNS is the ONE inventory: a
|
|
32
|
+
* hand-rolled copy that misses a shape is a leak on the very output it guards
|
|
33
|
+
* (seven copies of this expression lived in scripts/ before it landed here).
|
|
34
|
+
* `sweepSecretLiterals` is the config-tree twin — same shapes, tree walk.
|
|
35
|
+
* Never throws; returns [] for a missing stream.
|
|
36
|
+
* @param {unknown} raw
|
|
37
|
+
* @returns {string[]} every match, in stream order per pattern
|
|
38
|
+
*/
|
|
39
|
+
export function scanSecrets(raw: unknown): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Red every string in a config tree that carries a known secret-token shape.
|
|
42
|
+
* @param {any} root
|
|
43
|
+
* @param {(code: string, path: string, detail?: string) => void} red
|
|
44
|
+
*/
|
|
45
|
+
export function sweepSecretLiterals(root: any, red: (code: string, path: string, detail?: string) => void): void;
|
|
46
|
+
/**
|
|
47
|
+
* Validate a workflow config against schema v1. Returns the parsed config on
|
|
48
|
+
* ok (single parse — callers never re-parse; null on any red).
|
|
13
49
|
* @param {object|string} input parsed config, or raw JSON text (parse failures are a red)
|
|
14
|
-
* @param {{ shellCapUsd?: number }} [opts] the shell's
|
|
15
|
-
*
|
|
50
|
+
* @param {{ shellCapUsd?: number, jobWriteScope?: string[] }} [opts] the shell's
|
|
51
|
+
* ceilings — a config may tighten either, never exceed. `shellCapUsd`: at N2+
|
|
52
|
+
* the shell passes min(shell cap, job budgetUsd) — the ceiling chain
|
|
53
|
+
* workflow ≤ job ≤ shell. `jobWriteScope`: the job spec's outer fence
|
|
54
|
+
* (operator law, job-v1) — every workflow scope must fit inside it.
|
|
55
|
+
* @returns {{ ok: boolean, reds: Array<{code: string, path: string, detail?: string}>, config: object|null }}
|
|
16
56
|
*/
|
|
17
|
-
export function validateConfig(input: object | string, { shellCapUsd }?: {
|
|
57
|
+
export function validateConfig(input: object | string, { shellCapUsd, jobWriteScope }?: {
|
|
18
58
|
shellCapUsd?: number;
|
|
59
|
+
jobWriteScope?: string[];
|
|
19
60
|
}): {
|
|
20
61
|
ok: boolean;
|
|
21
62
|
reds: Array<{
|
|
@@ -23,6 +64,7 @@ export function validateConfig(input: object | string, { shellCapUsd }?: {
|
|
|
23
64
|
path: string;
|
|
24
65
|
detail?: string;
|
|
25
66
|
}>;
|
|
67
|
+
config: object | null;
|
|
26
68
|
};
|
|
27
69
|
/**
|
|
28
70
|
* Changed JSON paths between two configs — the one-knob mutation checker
|
|
@@ -33,6 +75,8 @@ export function validateConfig(input: object | string, { shellCapUsd }?: {
|
|
|
33
75
|
* @returns {string[]} sorted changed paths, dot-notation with array indices
|
|
34
76
|
*/
|
|
35
77
|
export function diffPaths(a: object, b: object): string[];
|
|
36
|
-
export const LOOP_SHAPES: string[];
|
|
37
|
-
export const SLOTS: string[];
|
|
38
|
-
export const VERBS: string[];
|
|
78
|
+
export const LOOP_SHAPES: readonly string[];
|
|
79
|
+
export const SLOTS: readonly string[];
|
|
80
|
+
export const VERBS: readonly string[];
|
|
81
|
+
export const REMEMBER_KINDS: string[];
|
|
82
|
+
export const SECRET_PATTERNS: RegExp[];
|