@jawache/flow 0.1.1 → 0.2.1

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.
@@ -33,9 +33,20 @@ export declare const textBan: (options: {
33
33
  * (which is right for a file, where a hit must be able to name its line) every one of those
34
34
  * patterns matches nothing, silently: the rule loads, counts, and cannot catch the thing it
35
35
  * names.
36
+ *
37
+ * WITHOUT ITS HEREDOC BODIES (`elideHeredocs`), by default. A heredoc is text fed to a program,
38
+ * and a python script or a note that names a banned command is not a use of it: matched whole,
39
+ * `python3 - <<'PY'` scripts were refused for naming a recipe in a string. Only the bodies go —
40
+ * the newlines the patterns above span are kept — and a body a shell reads stays, because it is
41
+ * commands.
42
+ *
43
+ * `matchHeredocs: true` matches the whole command instead. A rule about what a command is FED —
44
+ * the text of a commit message given on stdin, `git commit -F - <<'EOF'` — has to see the body,
45
+ * and would be blind to that message without it.
36
46
  */
37
47
  export declare const banCommands: (options: {
38
48
  ban: readonly string[];
49
+ matchHeredocs?: boolean;
39
50
  }) => Check;
40
51
  /**
41
52
  * A `banCommands` pattern for: a command that writes permanent prose, with a BACKTICK inside a
@@ -86,6 +97,24 @@ export declare const SUBSTITUTION_MESSAGE: string;
86
97
  export declare const protectedPath: (options: {
87
98
  existingOnly?: boolean;
88
99
  }) => Check;
100
+ /**
101
+ * Only the listed categories may change a file: a write or a delete by any other actor is refused.
102
+ *
103
+ * It reads `ctx.actor` — the categories the acting session wears, recognised from what the host
104
+ * wrote about it, never from a claim it made — and nothing about the file. A session wearing none
105
+ * of `writers` is refused whatever it wrote, and one wearing none at all is refused too: "no
106
+ * category" is not "every category".
107
+ *
108
+ * `.for(…)` on an entry says which actors a RULE applies to; this says which actors may WRITE. Both
109
+ * read the same categories, and they answer different questions — a rule for a checker says what a
110
+ * checker may not do, this says that everybody but a builder may not write.
111
+ *
112
+ * An empty `writers` is refused at load: it would refuse every change by everyone, which is a
113
+ * frozen worktree, not a rule about who writes it.
114
+ */
115
+ export declare const oneWriter: (options: {
116
+ writers: readonly string[];
117
+ }) => Check;
89
118
  /**
90
119
  * A file must have a required companion on disk — every `src/domain/**` needs its `.test.ts`.
91
120
  *
@@ -241,6 +270,44 @@ export declare const changeTogether: (options: {
241
270
  * aimed at a directory called HEAD.
242
271
  */
243
272
  export declare const GIT_VALUE_OPTS: ReadonlySet<string>;
273
+ /** A heredoc's opener: its delimiter, whether `<<-` strips leading tabs, and where the opener ends. */
274
+ export interface HeredocOpen {
275
+ readonly delim: string;
276
+ readonly tabs: boolean;
277
+ readonly end: number;
278
+ }
279
+ /**
280
+ * The first heredoc opener anywhere in a line, quoted context or not — the one definition of "this
281
+ * line carries a heredoc". A here-string (`<<<`) is stepped over whole, so its tail is not read as
282
+ * one.
283
+ */
284
+ export declare function firstHeredoc(s: string): HeredocOpen | null;
285
+ /**
286
+ * Where a `$(` closes, honouring quotes, nesting and any heredoc inside it — a body is text, so an
287
+ * apostrophe or a `)` in it closes nothing. -1 when it never closes.
288
+ */
289
+ export declare function closeParen(s: string, from: number): number;
290
+ /** Where a double-quoted run closes — a `"` inside a `$(…)` in it does not close it. -1 when it never does. */
291
+ export declare function dquoteEnd(s: string, from: number): number;
292
+ /**
293
+ * THE COMMAND LINE WITHOUT ITS HEREDOC BODIES — what a command ban matches unless the rule sets
294
+ * `matchHeredocs`.
295
+ *
296
+ * A heredoc is text fed to a program on its standard input: a python script, a file being written,
297
+ * a note. The words of a banned command inside it are not a use of that command, and matching
298
+ * them refused `python3 - <<'PY'` scripts for naming a recipe in a string. Every body is removed
299
+ * (its terminator line stays, so the opener still ends), whether the delimiter is quoted or not,
300
+ * and wherever the heredoc sits —
301
+ * inside a `$(…)` or a quoted argument too. EVERYTHING ELSE IS LEFT AS WRITTEN — newlines
302
+ * included, because the patterns that police a commit message span them.
303
+ *
304
+ * One exception keeps a body: a heredoc fed to a SHELL (`bash`, `sh`, `zsh`, `eval`, or a pipeline
305
+ * into one), whose body is commands, and a banned one in it will run.
306
+ *
307
+ * Best-effort, and it errs toward matching: from a word whose quote never closes, the line is
308
+ * returned as written, so a ban still sees everything it saw before.
309
+ */
310
+ export declare function elideHeredocs(command: string): string;
244
311
  /**
245
312
  * A shell-ish tokeniser: quotes respected (so a commit message mentioning `git commit` is not a
246
313
  * second command), operators emitted as their own tokens.
@@ -266,19 +333,6 @@ export interface GitInvocation {
266
333
  * operator — so a `git` inside a quoted message or as an argument to something else is not one.
267
334
  */
268
335
  export declare function gitInvocations(command: string): GitInvocation[] | null;
269
- /**
270
- * The body of the first heredoc in the raw command, or null.
271
- *
272
- * `git commit -F -` reads its message on stdin, and a QUOTED heredoc is the safe way to write one
273
- * containing backticks — a form this codebase's own rules push commits toward. The argument scan
274
- * cannot see it: there is no `-m` token, so a message written that way goes unjudged, and every
275
- * rule that reads a commit message is inert on it.
276
- *
277
- * Deliberately last-resort and deliberately dumb — it runs only when no inline message was found,
278
- * and reads the FIRST heredoc, because a commit command carrying two is not a shape anyone writes
279
- * and guessing between them would be worse than the gap.
280
- */
281
- export declare function heredocBody(command: string): string | null;
282
336
  /**
283
337
  * The message a `git commit` in this command line carries, or null when there is no judgeable
284
338
  * commit in it at all. Null is the "not our business" answer and every caller passes on it.
@@ -296,7 +350,10 @@ export declare function heredocBody(command: string): string | null;
296
350
  *
297
351
  * git commit -m MSG · -mMSG · --message MSG · --message=MSG judged
298
352
  * git commit -m SUBJECT -m BODY (repeated, any mix of forms) judged, joined as git joins them
299
- * git commit -F - <<'EOF' … EOF (any heredoc on the line) judged, via the heredoc body
353
+ * git commit -F - <<'EOF' … EOF (the commit reads stdin) judged, via the heredoc body
354
+ * python3 - <<'PY' … PY; git commit -F msg.txt NOT judged — the heredoc is
355
+ * another command's script, and
356
+ * the message is on disk
300
357
  * git commit -F path/to/file NOT judged — the message is on
301
358
  * disk, and reading it is a read
302
359
  * of the world this layer does not
@@ -584,10 +641,24 @@ export interface RequireEdge {
584
641
  * language, and a fence written in regexes is a fence nobody re-reads — the compiled literals of
585
642
  * one such config were dead for four days while the guard's own status reported it healthy.
586
643
  */
644
+ /**
645
+ * One layer: the globs that are in it, and — optionally — the globs that are NOT.
646
+ *
647
+ * `not` exists because the shape a real architecture wants is "this folder, except these few": the
648
+ * marketing surface of a site is `src/pages/**` minus the handful of subtrees that are endpoints.
649
+ * Written as an enumeration of what IS marketing, the fence silently stops covering the next folder
650
+ * somebody adds — which is the failure this dialect is supposed to prevent, not cause. It compiles
651
+ * to dependency-cruiser's own `pathNot`, which is the same pair the `only` rule already uses.
652
+ */
653
+ export interface Layer {
654
+ readonly path: readonly string[];
655
+ readonly not?: readonly string[];
656
+ }
587
657
  export interface Dialect {
588
658
  /** What to cruise. A GLOB, because a bare directory makes depcruise cruise zero modules. */
589
659
  readonly scan: string;
590
- readonly layers: Readonly<Record<string, readonly string[]>>;
660
+ /** Each layer, as globs — a bare list, or `{ path, not }` when it has holes in it. */
661
+ readonly layers: Readonly<Record<string, readonly string[] | Layer>>;
591
662
  /** Fail-closed allowlist: a layer may reach ONLY these layers. */
592
663
  readonly only?: Readonly<Record<string, readonly string[]>>;
593
664
  /** Forbidden edges, each carrying the `why` its violation prints. */
@@ -635,7 +706,12 @@ export declare function entryToMatcher(entry: string): {
635
706
  path?: string;
636
707
  };
637
708
  /** Layer names → a depcruise matcher fragment. `path` is an OR-list; builtins become a type. */
638
- export declare function layersMatcher(names: readonly string[], layers: Readonly<Record<string, readonly string[]>>): Matcher;
709
+ /** The globs a layer holds, whichever of the two ways it was written. */
710
+ export declare function layerGlobs(layer: readonly string[] | Layer | undefined): {
711
+ path: readonly string[];
712
+ not: readonly string[];
713
+ };
714
+ export declare function layersMatcher(names: readonly string[], layers: Readonly<Record<string, readonly string[] | Layer>>): Matcher;
639
715
  /** The whole dialect → a native `{ forbidden, required, options }` config. */
640
716
  export declare function compileDialect(rule: Dialect): NativeConfig;
641
717
  /**
@@ -660,6 +736,25 @@ export declare function compileDialect(rule: Dialect): NativeConfig;
660
736
  export declare function depcruiseCommand(dialect: Dialect): string;
661
737
  /** The tool's JSON report → one hit per violation, each naming the fence and its `why`. */
662
738
  export declare function depcruiseHits(result: ExecResult): string[];
739
+ /**
740
+ * Every layer entry that is a regex where a glob belongs — the fault `depcruise` refuses to load with.
741
+ *
742
+ * MEASURED, NOT IMAGINED: the first repo to convert its guard to flow brought its fence across
743
+ * verbatim, layers and all, from an engine whose layers WERE regexes. They compiled to
744
+ * `^\^src/pages/\([^/]!app/…` — a pattern no module path can match — and the fence loaded, reported
745
+ * armed, walked the graph and found nothing, for as long as it took somebody to plant a probe and
746
+ * watch the commit sail through. A rule that cannot do its job must refuse to load.
747
+ */
748
+ export declare function nonGlobLayers(layers: Readonly<Record<string, readonly string[] | Layer>>): string[];
749
+ /**
750
+ * A layer with holes, named in an `only` allowlist — refused, because the holes would be silent.
751
+ *
752
+ * `only` is compiled by INVERTING the allowed layers: everything not in them blocks. The inversion
753
+ * reads the `path` globs and nothing else, so a layer's `not` would simply not be there — the
754
+ * allowlist would quietly be wider than the layer it names. Rather than half-apply it, this says so
755
+ * at load: use plain globs for a layer that an `only` names, or express the exclusion as a `forbid`.
756
+ */
757
+ export declare function holesInAnOnlyList(opts: Dialect): string[];
663
758
  /**
664
759
  * The generic import-fence runner.
665
760
  *
@@ -266,8 +266,16 @@ export declare const FLOW_DIR = ".flow";
266
266
  export declare const FLOW_GITIGNORE = "# flow's own state \u2014 telemetry and session marks, never committed.\n*\n";
267
267
  /** The log schema this build writes, stamped into every session file's first row. */
268
268
  export declare const LOG_VERSION = 1;
269
- /** Every kind a log row may be. Closed — a reader that meets another word has met corruption. */
270
- export declare const ROW_KINDS: readonly ["meta", "tool", "breadcrumb", "guardrail", "compaction", "run"];
269
+ /**
270
+ * Every kind a log row may be. Closed — a reader that meets another word has met corruption.
271
+ *
272
+ * `read` and `write` are what went ROUND the tool rows: a file a shell command read by name, and a
273
+ * file a call changed that the call did not name — a heredoc, a `sed -i`, a script. A `tool` row
274
+ * says a call happened; these say what it did to the tree, so the coverage and lead numbers count
275
+ * work done through the shell as well as through Edit. `mismatch` is the host's own list of the
276
+ * files a command changed disagreeing with flow's diff: a fact to read, never an input to a rule.
277
+ */
278
+ export declare const ROW_KINDS: readonly ["meta", "tool", "breadcrumb", "guardrail", "compaction", "run", "read", "write", "mismatch"];
271
279
  export type RowKind = (typeof ROW_KINDS)[number];
272
280
  export declare function flowDir(root: string): string;
273
281
  /** A session id becomes a filename, so it is held to a filename's charset. */
@@ -1,4 +1,21 @@
1
1
  export declare function escapeRe(s: string): string;
2
+ /**
3
+ * Is that a REGULAR EXPRESSION where this dialect wants a glob?
4
+ *
5
+ * It lives beside `escapeRe` because it is that function read backwards: these are the shapes
6
+ * `escapeRe` turns into literals, which is how a pattern written as a regex comes to match nothing
7
+ * at all while reading as a fence. Four of them — a leading `^`, a `(?` group, a `|`, a trailing `$`
8
+ * — and nothing broader is claimed: this is not a regex detector, it is the list of characters whose
9
+ * meaning is silently lost here.
10
+ *
11
+ * ANY `|` COUNTS, with no carve-out for a backslash before it. The dialect has no escape character:
12
+ * `\|` is a literal backslash followed by a pipe, and a path with either in it is not a path anyone
13
+ * has. A carve-out would only ever wave through the thing it was meant to catch.
14
+ *
15
+ * It was found the hard way — a repo's fence, brought across from an engine whose layers WERE
16
+ * regexes, loaded green and refused nothing for a week.
17
+ */
18
+ export declare function notAGlob(entry: string): boolean;
2
19
  /** One piece of a glob. The whole dialect: `**` · `*` · `?` · `{a,b}` · literal text. */
3
20
  export type GlobToken = {
4
21
  readonly kind: "literal";
@@ -1,8 +1,8 @@
1
1
  export { guardrail, breadcrumb, type Sentence, type EntrySpec, type GuardrailSpec, type BreadcrumbSpec, type GuardrailSentence, type BreadcrumbSentence, type EntryGroup, type DisabledMark, } from "./language/domain.ts";
2
2
  export { definePack, pack, override, defineConfig, type Pack, type PackDefinition, type EntryRef, type RefTarget, type FlowConfig, type Binding, type PackBinding, type OverrideBinding, type ConfigSentence, } from "./language/domain.ts";
3
- export { defineCheck, type Check, type Ctx, type World, type Verdict, type ExecResult, type TurnAction, type Case, type CaseWorld, type Cases, } from "./language/domain.ts";
3
+ export { defineCheck, withFaults, faultsOf, type Check, type Ctx, type World, type Verdict, type ExecResult, type TurnAction, type Case, type CaseWorld, type Cases, } from "./language/domain.ts";
4
4
  export { defineCategory, type Category, type Classifier, type SessionFacts } from "./language/domain.ts";
5
- export { astGrep, banCommands, canonicalFiles, changeTogether, commitReason, depcruise, execPasses, jsonInvariant, protectedPath, ranSinceEdit, siblingExists, symbolsInSibling, textBan, type CanonOptions, type ChangeGroup, type Dialect, type DiffAdds, type ForbidEdge, type JsonAssert, type RequireEdge, } from "./checks/domain.ts";
5
+ export { astGrep, banCommands, canonicalFiles, changeTogether, commitReason, depcruise, execPasses, jsonInvariant, oneWriter, protectedPath, ranSinceEdit, siblingExists, symbolsInSibling, textBan, type CanonOptions, type ChangeGroup, type Dialect, type Layer, type DiffAdds, type ForbidEdge, type JsonAssert, type RequireEdge, } from "./checks/domain.ts";
6
6
  export { substitutionInProse, SUBSTITUTION_MESSAGE } from "./checks/domain.ts";
7
7
  export { commitMessage, gitDirPrefix, gitInvocations, givesReason, quoteArg, tokenizeCommand, type GitInvocation, } from "./checks/domain.ts";
8
8
  export { spawnedAs, type SpawnRecipe } from "./engine/domain.ts";
@@ -141,6 +141,12 @@ export interface Ctx {
141
141
  readonly staged?: readonly string[] | undefined;
142
142
  /** turn-end: what the actor did this turn, in order. */
143
143
  readonly turn?: readonly TurnAction[] | undefined;
144
+ /**
145
+ * Every moment: the category names that match the session making this change — the categories
146
+ * some bound entry names, whose recognizer said yes to the host-written evidence about it. Empty
147
+ * when it matches none, which is not "every category".
148
+ */
149
+ readonly actor: readonly string[];
144
150
  exec(cmd: string): Promise<ExecResult>;
145
151
  readonly fs: {
146
152
  read(path: string): Promise<string>;
@@ -191,6 +197,24 @@ export type World = Pick<Ctx, "exec" | "fs" | "git">;
191
197
  * would be called with `ctx` as its receiver and break any world that closes over itself.
192
198
  */
193
199
  export declare function makeCtx(moment: Moment, facts: Partial<Ctx>, world: World): Ctx;
200
+ /**
201
+ * Mark a configured check as built with options it cannot work with, and say why.
202
+ *
203
+ * WHY IT IS A VALUE AND NOT A THROW: a check factory runs while the config module is evaluating, so
204
+ * a throw there is a module that will not import, and the reader gets one fault with a stack trace
205
+ * instead of every fault with its entry named. Marked instead, the load collects it beside the
206
+ * grammar's own refusals and the engine blocks every gated moment with the same text — which is the
207
+ * shape every other load failure already has.
208
+ *
209
+ * WHY IT EXISTS AT ALL: an option can be well-TYPED and still be nonsense — the class that bit here
210
+ * was a depcruise layer written as a regex where the dialect takes globs, which compiled to a
211
+ * pattern matching nothing. The fence loaded, `flow status` called it armed, and it walked no graph
212
+ * for as long as nobody planted a probe. A rule that cannot do its job must refuse to load, never
213
+ * report green.
214
+ */
215
+ export declare function withFaults<C extends Check>(check: C, faults: readonly string[]): C;
216
+ /** What a configured check said is wrong with its own options. Empty for every healthy check. */
217
+ export declare function faultsOf(check: Check | undefined): readonly string[];
194
218
  /**
195
219
  * Declare a CONFIGURED check: a function that takes options and returns a check.
196
220
  *
@@ -245,16 +269,20 @@ export type Case =
245
269
  string | {
246
270
  readonly command: string;
247
271
  readonly world?: CaseWorld;
272
+ readonly actor?: readonly string[];
248
273
  } | {
249
274
  readonly path: string;
250
275
  readonly content: string;
251
276
  readonly world?: CaseWorld;
277
+ readonly actor?: readonly string[];
252
278
  } | {
253
279
  readonly staged: readonly string[];
254
280
  readonly world?: CaseWorld;
281
+ readonly actor?: readonly string[];
255
282
  } | {
256
283
  readonly actions: readonly TurnAction[];
257
284
  readonly world?: CaseWorld;
285
+ readonly actor?: readonly string[];
258
286
  };
259
287
  /** The cases an entry carries: what must pass it, and what must be blocked by it. */
260
288
  export interface Cases {
@@ -520,6 +548,19 @@ export interface Settings {
520
548
  * it two ways.
521
549
  */
522
550
  readonly grammars?: readonly Grammar[];
551
+ /**
552
+ * Globs for the IGNORED paths the snapshot records as well. The snapshot is git's view of the
553
+ * tree — tracked files, and untracked ones git does not ignore — so a shell write to an ignored
554
+ * file is never seen unless a glob here brings it back. `.env` is the usual one.
555
+ */
556
+ readonly snapshotInclude?: readonly string[];
557
+ /**
558
+ * What is put back when a rule refuses a write that has already landed: `"refused"` (the default)
559
+ * writes back only the files a rule refused, `"all"` every file that call changed. While another
560
+ * agent's call overlaps it, only the refused files are put back whatever this says — that call's
561
+ * writes can be in the same diff.
562
+ */
563
+ readonly revert?: "refused" | "all";
523
564
  }
524
565
  /**
525
566
  * One hand-built tree-sitter grammar, as `registerDynamicLanguage` wants it.
@@ -631,7 +672,7 @@ export interface Overlaid {
631
672
  */
632
673
  export declare function overlay(base: EntrySpec, spoken: Readonly<Record<string, unknown>>, prior?: Readonly<Record<string, "pack" | "override">>): Overlaid;
633
674
  /** The closed vocabulary of refusals. Every load failure is exactly one of these. */
634
- export declare const REFUSAL_CODES: readonly ["not-a-pack", "missing-parameter", "unknown-entry", "unknown-key", "unknown-moment", "missing-mandatory", "undeclared-category", "no-cases", "duplicate-id", "dead-scope"];
675
+ export declare const REFUSAL_CODES: readonly ["not-a-pack", "missing-parameter", "unknown-entry", "unknown-key", "unknown-moment", "missing-mandatory", "undeclared-category", "no-cases", "duplicate-id", "dead-scope", "bad-check-options"];
635
676
  export type RefusalCode = (typeof REFUSAL_CODES)[number];
636
677
  /** One reason the config will not load. */
637
678
  export interface Refusal {
@@ -5,9 +5,9 @@
5
5
  * least possible cognitive load, and the agent wants almost nothing in context. So `docs/` has
6
6
  * exactly two doors and everything inside follows its door's rules.
7
7
  *
8
- * @setup A `docs/` folder holding exactly `user/` and `agent/`, each with its own index —
9
- * `docs/user/index.html` for people and `docs/agent/README.md` as a list of pointers. The two
10
- * guardrails below refuse anything else at the top of the folder, so a repo with a different shape
8
+ * @setup A `docs/` folder holding exactly `user/` and `agent/`, each with its own index — an index
9
+ * file under `docs/user/` for people and `docs/agent/README.md` as a list of pointers. The
10
+ * guardrail below refuses anything else at the top of the folder, so a repo with a different shape
11
11
  * either moves its pages or does not bind this pack.
12
12
  */
13
13
  export interface Doors {
@@ -45,5 +45,4 @@ export declare const docs: import("../index.ts").Pack<{
45
45
  * drawer, and neither audience's rules can be applied to what is in it.
46
46
  */
47
47
  docsShape: import("../index.ts").GuardrailSentence<"at" | "check" | "message" | "test" | "on" | "description", "write" | "commit">;
48
- noMarkdownInUserDocs: import("../index.ts").GuardrailSentence<"at" | "check" | "message" | "test" | "on" | "description", "write" | "commit">;
49
48
  }, Doors | undefined>;
@@ -17,6 +17,20 @@ export declare const builder: import("../index.ts").Category;
17
17
  * a frontmatter list somebody can widen.
18
18
  */
19
19
  export declare const checker: import("../index.ts").Category;
20
+ /** The rungs that may be named as writers — a checker is the rung that never writes. */
21
+ export type Writer = "builder" | "parent";
22
+ /** What a repo may say about how it runs the lifecycle. Every field is optional. */
23
+ export interface Rungs {
24
+ /**
25
+ * The rungs allowed to change files in a worktree, turning on ONE WRITER: a write or a delete by
26
+ * any other actor is refused — an Edit before it lands, anything else put back after.
27
+ *
28
+ * OPTIONAL, and with no list there is no entry at all. One writer is for a worktree several
29
+ * agents share with one builder in it; in a repo where a helper agent of any other kind is
30
+ * expected to write, it would refuse that helper's every change, so it is off until a repo asks.
31
+ */
32
+ readonly writers?: readonly Writer[];
33
+ }
20
34
  /**
21
35
  * The WORK LIFECYCLE's rungs: who is acting, and what each rung may do.
22
36
  *
@@ -38,12 +52,14 @@ export declare const checker: import("../index.ts").Category;
38
52
  * so in a repo that does not run the lifecycle they are five rules that can never fire.
39
53
  * @adopt Bind it only in a repo whose tasks are actually run through the lifecycle. The three rung
40
54
  * rules are scoped to categories this pack defines, so they judge nobody until a session is
41
- * classified as a builder or a checker — a human at a keyboard is neither.
55
+ * classified as a builder or a checker — a human at a keyboard is neither. Name `writers` to let
56
+ * only those rungs change files in the worktree.
42
57
  */
43
58
  export declare const work: import("../index.ts").Pack<{
59
+ builderWrites?: import("../index.ts").GuardrailSentence<"at" | "check" | "message" | "test" | "description", "write" | "delete">;
44
60
  planIsTheParents: import("../index.ts").GuardrailSentence<"at" | "check" | "message" | "test" | "for" | "description", "command">;
45
61
  checkersDoNotWrite: import("../index.ts").GuardrailSentence<"at" | "check" | "message" | "test" | "for" | "description", "write">;
46
62
  ticksAreTheChilds: import("../index.ts").GuardrailSentence<"at" | "check" | "message" | "test" | "for" | "description", "command">;
47
63
  noAgentInboxItems: import("../index.ts").GuardrailSentence<"at" | "check" | "message" | "test" | "description", "command">;
48
64
  noShellSubstitutionInProse: import("../index.ts").GuardrailSentence<"at" | "check" | "message" | "test" | "description", "command">;
49
- }, undefined>;
65
+ }, Rungs | undefined>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jawache/flow",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "Guardrails and breadcrumbs as code — packs you import, a config that typechecks, one adapter per harness.",
5
5
  "license": "MIT",
6
6
  "repository": {