@rness/cli 0.17.3 → 0.18.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.
package/README.md CHANGED
@@ -102,28 +102,39 @@ the files a given agent needs, for the agents the team declares in
102
102
  `.claude-plugin/plugin.json`, also carries the agent-plugins.org
103
103
  `$schema`, the author, homepage, repository, licence and keywords, so a
104
104
  scanner that looks for an Agent Plugins manifest finds one; Claude Code
105
- reads the same file. Nothing in them depends on
105
+ reads the same file. The repository root also carries a `plugin.json` in
106
+ that form, describing the repository, where a scanner looks first. Nothing in them depends on
106
107
  the version; the last line of the status skill names the workspace's
107
108
  package manager, so changing `packageManager` in `.rness/package.json`
108
109
  leaves it stale until the next `sync`. Claude Code loads the plugin once
109
110
  the folder is trusted, in a session started there.
110
- - **The lifecycle skills**: `/rness:adr [subject | NNNN]` records a decision
111
- as an ADR, `/rness:spec [subject | NNNN]` writes a specification,
112
- `/rness:plan <spec>` turns an approved specification into a plan, and
113
- `/rness:done [plan]` closes a piece of work — each task checked on
114
- evidence, then the plan `Completed`, its specification `Implemented`, and
115
- the documents the work made inaccurate corrected. Each is a procedure
116
- loaded into the conversation, not a file generator: after a decision has
117
- been discussed, `/rness:adr` writes it from the conversation; otherwise
118
- it asks, one question at a time. The skill stays in the conversation for
119
- the next turns, and the file carries the work to the next session
120
- (`/rness:adr 0010` reopens it). The agent may start one itself — an ADR
121
- when a choice is expensive to reverse — but writes nothing without a yes,
122
- except `/rness:done` on a plan whose last task has just passed.
123
- The rules stay in `.rness/CONVENTIONS.md`; the skills only add the steps.
124
- A new document takes the collection's first status (`Proposed` for an
125
- ADR, `Draft` otherwise) and the next number of the local checkout; two
126
- branches can pick the same one. Each skill records its session: it adds
111
+ - **The lifecycle skills**, one per collection, on one grammar: the first
112
+ word is the verb, a bare number reopens, anything else is the subject of
113
+ a `create`. `/rness:adr [create <subject> | open NNNN]` records a decision
114
+ as an ADR or reopens one; `/rness:spec [create <subject> | open NNNN]`
115
+ writes a specification or reopens one; `/rness:plan` takes four verbs:
116
+ `from <spec NNNN>` writes a plan from a specification and approves it
117
+ (typing the command is the approval), `create [subject]` writes a plan
118
+ from the conversation for work too small for a specification, `open NNNN`
119
+ reopens a plan, and `check NNNN` runs the proofs of a plan — each task's
120
+ command, run now — and closes it when they all pass: the plan `Completed`,
121
+ its specification `Implemented`, the documents the work made inaccurate
122
+ corrected; one task without evidence and nothing moves. Each is a
123
+ procedure loaded into the conversation, not a file generator: after a
124
+ decision has been discussed, `/rness:adr` writes it from the
125
+ conversation; otherwise it asks, one question at a time. The skill stays
126
+ in the conversation for the next turns, and the file carries the work to
127
+ the next session (`/rness:adr 0010` reopens it). The agent may start one
128
+ itself — an ADR when a choice is expensive to reverse — but writes nothing
129
+ without a yes, except `/rness:plan check` on a plan whose last task has
130
+ just passed. The rules stay in `.rness/CONVENTIONS.md`; the skills only
131
+ add the steps. A new document takes the collection's first status
132
+ (`Proposed` for an ADR, `Draft` otherwise) and the next number, allocated
133
+ by `rness doc new <collection>` — the second pre-approved line of each
134
+ skill, so that every runtime and a bare terminal get the same number;
135
+ `rness validate` refuses two documents with one number, the case a merge
136
+ of two branches can still produce, and a document named without one
137
+ (`NNNN-<slug>.md`, never a date). Each skill records its session: it adds
127
138
  `{ id: <session id>, agent: <model> }` to `sessions:` in the front matter
128
139
  of what it writes or closes. The agent is the model it runs as, as Claude
129
140
  Code names it (`Claude Opus 5.5`): no variable gives it to a skill. An
@@ -385,11 +396,13 @@ it through one adapter; `git` still does what git does (clone, pull, push,
385
396
  credentials), and the provider's API the rest (organizations, creating a
386
397
  repository, the board).
387
398
 
388
- - `rness create` asks `Where does your organization live?`: GitHub, and
389
- GitLab and Atlassian (Bitbucket + Jira) shown disabled, coming later.
390
- `--provider github` answers it off a terminal. A blank workspace asks
391
- nothing. Joining an organization asks first as well, then takes the
392
- provider its `rness.json` names.
399
+ - `rness create` asks `Where does your organization live?` first: GitHub,
400
+ GitLab and Atlassian (Bitbucket + Jira) shown disabled, coming later, and
401
+ `No organization yet: a blank local workspace` (the `--blank` of
402
+ "Blank workspace"). `--provider github` answers it off a terminal;
403
+ `--org`, `--repos` and `--blank` settle it unasked. Joining an
404
+ organization asks first as well, then takes the provider its `rness.json`
405
+ names.
393
406
  - A workspace without the key is read from its first repository URL: a
394
407
  GitLab host reads as `gitlab`, any other host — or no repository — as
395
408
  `github`. Nothing to change: `pulse create` writes it, and refuses a
@@ -461,8 +474,23 @@ anonymously.
461
474
  GitHub, anonymous or with `--yes`, it prints the two manual steps instead
462
475
  — create the empty repository on github.com, then `git remote add origin …
463
476
  && git push`. No other tool is ever needed.
464
- - An organization that restricts OAuth apps hides its private repositories
465
- until an owner approves "Rness"; `create` says so, with the link.
477
+ - Logged in, the wizard lists the organizations you belong to that have
478
+ approved "Rness" — GitHub shows an OAuth app no other — your account
479
+ last, then `an organization not listed here…` for a typed name: one that
480
+ has not approved rness yet, an outside collaborator's, a public one.
481
+ Right after the
482
+ organization, before the SSH test, the probe of `<org>/.rness` and the
483
+ listing, `create` checks your access: an organization that restricts
484
+ OAuth apps and has not approved "Rness" hides its private repositories,
485
+ so the wizard asks `Open github.com to approve rness for <org> now?`,
486
+ opens the approval page in your browser (printed only over SSH) and waits
487
+ — polling every 5 seconds, for 10 minutes at most — until an owner's
488
+ click makes you a member in its eyes; then it goes on with the full
489
+ listing. Declined, or timed out, it goes on with what is visible and
490
+ names the page for later; with `--yes` or off a terminal it prints the
491
+ warning and the page, and asks nothing. The order matters: a private
492
+ `.rness` probed through a token the organization has not approved would
493
+ read as absent, and `create` would start a second one.
466
494
  - Over HTTPS, rness's own clones and pulls carry the login — through the
467
495
  environment of that one git command, never in a URL or `.git/config`. For
468
496
  your own `git pull` and `git push`, `login` offers to make rness git's
@@ -576,6 +604,60 @@ per repository, the files to commit there.
576
604
  Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
577
605
  `RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
578
606
 
607
+ ## 0.18.1 — a document without a number is caught; small fixes
608
+
609
+ - `rness validate` and the edit hook name a document of `adr/`, `specs/` or
610
+ `plans/` whose file name has no number, with the next one:
611
+ `plans/2026-10-02-x.md: not numbered; name it 0002-<slug>.md, the next
612
+ number of plans`. A plan another agent's skill wrote with a dated name
613
+ is the usual case; rename it, or let the agent do it when the hook
614
+ tells it. A workspace with such a file fails `validate` (and its CI)
615
+ after the upgrade until it is renamed. The scaffold's `CONVENTIONS.md`
616
+ states the rule, and `upgrade` merges it in.
617
+ - A dated file name is no longer read as a number: `rness doc new` after
618
+ `2026-10-02-x.md` gave `2027`, and two dated plans of one year were
619
+ reported as one number twice.
620
+ - `rness doc new` racing another one at the same number says `<file>
621
+ exists; nothing written` (exit 1) instead of a raw `EEXIST`.
622
+ - `1 repository`, not `1 repositories`, in `create` and `sync`.
623
+ - When the SSH test passes only by asking for the key's passphrase,
624
+ `create`, `add` and `sync` say once how to load it into an agent
625
+ (`ssh-add`), since every clone would ask again.
626
+ - Ctrl+C while `create` waits for an organization's approval is a cancel
627
+ in the plain look too: `cancelled`, nothing written, exit 0 (it was 130).
628
+
629
+ ## 0.18.0 — the wizard asks where first and waits for the approval; the skills on one grammar; Node 22.17
630
+
631
+ - The published CLI runs on **Node 22.17 or later** (ADR 0010); the guard
632
+ compares major and minor. A workspace pinned to 0.17.x keeps refusing
633
+ Node 22 until its pin moves: from inside it, `npx @rness/cli@latest
634
+ upgrade` works under Node 22, since `upgrade` is served by the copy
635
+ invoked, never the pinned one.
636
+ - `rness create` asks **where the organization lives first** — the blank
637
+ workspace is that question's last answer — then offers the login, which
638
+ now lists **the organizations you belong to that have approved rness**
639
+ (your account last, then `an organization not listed here…` for the
640
+ rest). Right after the organization and
641
+ before anything reads it, an organization that restricts OAuth apps and
642
+ has not approved "Rness" gets its **approval page opened in your
643
+ browser**; the wizard waits for the owner's click (10 minutes at most)
644
+ and then lists the private repositories too. See "GitHub login".
645
+ - `/rness:adr`, `/rness:spec` and `/rness:plan` read their first word as
646
+ the verb: `create`, `open` (a bare number), and for a plan `from <spec>`
647
+ — which **approves the specification** it plans — and `check NNNN`, the
648
+ proofs of a plan, in place of `/rness:done`. `/rness:done` is retired:
649
+ `rness sync` removes its `SKILL.md` where an earlier release wrote it
650
+ (`removed` in its output); commit the deletion in each repository, as
651
+ `upgrade`'s next steps list. Note: `/rness:plan 0028` now opens plan
652
+ 0028; a plan is made with `from <spec>`. See "Agent targets".
653
+ - `rness doc new <collection> [--title <text>]` writes the next numbered
654
+ document of `adr`, `specs` or `plans` and prints its path: the skills
655
+ allocate with it instead of counting. `rness validate` and the edit hook
656
+ refuse two documents with one number in a collection.
657
+ - The day of a release, `pnpm create rness` runs the previous version:
658
+ pnpm ≥ 11 holds back a package younger than 24 hours
659
+ (`minimumReleaseAge`). `rness upgrade` installs the latest all the same.
660
+
579
661
  ## 0.17.3 — the packages name the product; the plugin manifest for scanners
580
662
 
581
663
  - `homepage` of `@rness/cli`, `create-rness` and `@rness/create` is
@@ -1076,4 +1158,4 @@ workspace pins exactly that build and no cache serves an older one under its
1076
1158
  number. To try it in a workspace that exists, run `rness upgrade <version>`
1077
1159
  inside it; the deploy prints the line.
1078
1160
 
1079
- Node ≥ 24. MIT.
1161
+ Node ≥ 22.17. MIT.
package/dist/bin/rness.js CHANGED
@@ -6,19 +6,24 @@ import {
6
6
  findDelegate,
7
7
  reportError,
8
8
  run
9
- } from "../chunk-MMPMXYZU.js";
9
+ } from "../chunk-JHU2G7K7.js";
10
10
 
11
11
  // src/bin/rness.ts
12
12
  import { pathToFileURL } from "url";
13
13
 
14
14
  // src/core/node-version.ts
15
- var MIN_NODE_MAJOR = 24;
16
- function nodeMajor(version) {
17
- const major = Number.parseInt(version.split(".")[0] ?? "", 10);
18
- return Number.isNaN(major) ? 0 : major;
15
+ var MIN_NODE = { major: 22, minor: 17 };
16
+ var MIN_NODE_LABEL = `${MIN_NODE.major}.${MIN_NODE.minor}`;
17
+ function component(version, index) {
18
+ const n = Number.parseInt(version.split(".")[index] ?? "", 10);
19
+ return Number.isNaN(n) ? -1 : n;
19
20
  }
20
21
  function isSupportedNode(version) {
21
- return nodeMajor(version) >= MIN_NODE_MAJOR;
22
+ const major = component(version, 0);
23
+ const minor = component(version, 1);
24
+ if (major < 0 || minor < 0) return false;
25
+ if (major !== MIN_NODE.major) return major > MIN_NODE.major;
26
+ return minor >= MIN_NODE.minor;
22
27
  }
23
28
 
24
29
  // src/bin/rness.ts
@@ -29,7 +34,7 @@ process.stdout.on("error", (e) => {
29
34
  async function main() {
30
35
  if (!isSupportedNode(process.versions.node)) {
31
36
  process.stderr.write(
32
- `rness needs Node ${MIN_NODE_MAJOR} or newer (running ${process.version})
37
+ `rness needs Node ${MIN_NODE_LABEL} or newer (running ${process.version})
33
38
  `
34
39
  );
35
40
  return 1;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/rness.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { pathToFileURL } from 'node:url'\n\nimport { run } from '../cli.ts'\nimport { OWN_COMMANDS, catchUp } from '../core/catch-up.ts'\nimport { findDelegate } from '../core/delegate.ts'\nimport { MIN_NODE_MAJOR, isSupportedNode } from '../core/node-version.ts'\nimport { reportError } from '../report.ts'\nimport { VERSION } from '../version.ts'\n\n// `rness context | head`: once the reader has its lines it closes the pipe and\n// every further write emits EPIPE on stdout. Nothing is left to deliver, so end\n// quietly with success. This is the one process.exit() in the code base — it\n// runs only when there is no output left to drain (see main() below).\nprocess.stdout.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'EPIPE') process.exit(0)\n throw e\n})\n\n// Set process.exitCode rather than calling process.exit(): process.exit()\n// terminates before Node drains an async stdout pipe, truncating piped output\n// at the ~64 KiB pipe buffer (breaks `rness context --json | jq`, `$(...)`).\nasync function main(): Promise<number> {\n if (!isSupportedNode(process.versions.node)) {\n process.stderr.write(\n `rness needs Node ${MIN_NODE_MAJOR} or newer (running ${process.version})\\n`\n )\n return 1\n }\n const argv = process.argv.slice(2)\n const skipDelegation =\n OWN_COMMANDS.includes(argv[0] ?? '') ||\n process.env['RNESS_NO_DELEGATE'] === '1'\n // A pin that moved is installed first, and the fresh copy runs the command\n // as its own process (spec 0008 §4).\n const handedOff = await catchUp(argv)\n if (handedOff !== null) return handedOff\n const delegate = skipDelegation\n ? null\n : await findDelegate(process.cwd(), VERSION)\n if (delegate !== null) {\n const broken = (reason: string): Error =>\n new Error(\n `@rness/cli ${delegate.version} pinned in ${delegate.root}/.rness is not installed correctly (${reason}); reinstall in .rness/`\n )\n if (process.env['RNESS_DEBUG'] === '1') {\n process.stderr.write(\n `rness: delegating to @rness/cli ${delegate.version} (${delegate.entry})\\n`\n )\n }\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(delegate.entry).href)) as Record<\n string,\n unknown\n >\n } catch (e) {\n throw broken(e instanceof Error ? e.message : String(e))\n }\n if (typeof mod['run'] !== 'function')\n throw broken('dist/index.js does not export run')\n const delegateRun = mod['run'] as (argv: string[]) => Promise<unknown>\n const code = await delegateRun(argv)\n return typeof code === 'number' ? code : 1\n }\n return run(argv)\n}\n\nmain()\n .then((code) => {\n process.exitCode = code\n })\n .catch((e: unknown) => {\n process.exitCode = reportError(e)\n })\n","export const MIN_NODE_MAJOR = 24\n\nexport function nodeMajor(version: string): number {\n const major = Number.parseInt(version.split('.')[0] ?? '', 10)\n return Number.isNaN(major) ? 0 : major\n}\n\nexport function isSupportedNode(version: string): boolean {\n return nodeMajor(version) >= MIN_NODE_MAJOR\n}\n"],"mappings":";;;;;;;;;;;AACA,SAAS,qBAAqB;;;ACDvB,IAAM,iBAAiB;AAEvB,SAAS,UAAU,SAAyB;AACjD,QAAM,QAAQ,OAAO,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE;AAC7D,SAAO,OAAO,MAAM,KAAK,IAAI,IAAI;AACnC;AAEO,SAAS,gBAAgB,SAA0B;AACxD,SAAO,UAAU,OAAO,KAAK;AAC/B;;;ADKA,QAAQ,OAAO,GAAG,SAAS,CAAC,MAA6B;AACvD,MAAI,EAAE,SAAS,QAAS,SAAQ,KAAK,CAAC;AACtC,QAAM;AACR,CAAC;AAKD,eAAe,OAAwB;AACrC,MAAI,CAAC,gBAAgB,QAAQ,SAAS,IAAI,GAAG;AAC3C,YAAQ,OAAO;AAAA,MACb,oBAAoB,cAAc,sBAAsB,QAAQ,OAAO;AAAA;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AACA,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,QAAM,iBACJ,aAAa,SAAS,KAAK,CAAC,KAAK,EAAE,KACnC,QAAQ,IAAI,mBAAmB,MAAM;AAGvC,QAAM,YAAY,MAAM,QAAQ,IAAI;AACpC,MAAI,cAAc,KAAM,QAAO;AAC/B,QAAM,WAAW,iBACb,OACA,MAAM,aAAa,QAAQ,IAAI,GAAG,OAAO;AAC7C,MAAI,aAAa,MAAM;AACrB,UAAM,SAAS,CAAC,WACd,IAAI;AAAA,MACF,cAAc,SAAS,OAAO,cAAc,SAAS,IAAI,uCAAuC,MAAM;AAAA,IACxG;AACF,QAAI,QAAQ,IAAI,aAAa,MAAM,KAAK;AACtC,cAAQ,OAAO;AAAA,QACb,mCAAmC,SAAS,OAAO,KAAK,SAAS,KAAK;AAAA;AAAA,MACxE;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,YAAO,MAAM,OAAO,cAAc,SAAS,KAAK,EAAE;AAAA,IAIpD,SAAS,GAAG;AACV,YAAM,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IACzD;AACA,QAAI,OAAO,IAAI,KAAK,MAAM;AACxB,YAAM,OAAO,mCAAmC;AAClD,UAAM,cAAc,IAAI,KAAK;AAC7B,UAAM,OAAO,MAAM,YAAY,IAAI;AACnC,WAAO,OAAO,SAAS,WAAW,OAAO;AAAA,EAC3C;AACA,SAAO,IAAI,IAAI;AACjB;AAEA,KAAK,EACF,KAAK,CAAC,SAAS;AACd,UAAQ,WAAW;AACrB,CAAC,EACA,MAAM,CAAC,MAAe;AACrB,UAAQ,WAAW,YAAY,CAAC;AAClC,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/bin/rness.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { pathToFileURL } from 'node:url'\n\nimport { run } from '../cli.ts'\nimport { OWN_COMMANDS, catchUp } from '../core/catch-up.ts'\nimport { findDelegate } from '../core/delegate.ts'\nimport { MIN_NODE_LABEL, isSupportedNode } from '../core/node-version.ts'\nimport { reportError } from '../report.ts'\nimport { VERSION } from '../version.ts'\n\n// `rness context | head`: once the reader has its lines it closes the pipe and\n// every further write emits EPIPE on stdout. Nothing is left to deliver, so end\n// quietly with success. This is the one process.exit() in the code base — it\n// runs only when there is no output left to drain (see main() below).\nprocess.stdout.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'EPIPE') process.exit(0)\n throw e\n})\n\n// Set process.exitCode rather than calling process.exit(): process.exit()\n// terminates before Node drains an async stdout pipe, truncating piped output\n// at the ~64 KiB pipe buffer (breaks `rness context --json | jq`, `$(...)`).\nasync function main(): Promise<number> {\n if (!isSupportedNode(process.versions.node)) {\n process.stderr.write(\n `rness needs Node ${MIN_NODE_LABEL} or newer (running ${process.version})\\n`\n )\n return 1\n }\n const argv = process.argv.slice(2)\n const skipDelegation =\n OWN_COMMANDS.includes(argv[0] ?? '') ||\n process.env['RNESS_NO_DELEGATE'] === '1'\n // A pin that moved is installed first, and the fresh copy runs the command\n // as its own process (spec 0008 §4).\n const handedOff = await catchUp(argv)\n if (handedOff !== null) return handedOff\n const delegate = skipDelegation\n ? null\n : await findDelegate(process.cwd(), VERSION)\n if (delegate !== null) {\n const broken = (reason: string): Error =>\n new Error(\n `@rness/cli ${delegate.version} pinned in ${delegate.root}/.rness is not installed correctly (${reason}); reinstall in .rness/`\n )\n if (process.env['RNESS_DEBUG'] === '1') {\n process.stderr.write(\n `rness: delegating to @rness/cli ${delegate.version} (${delegate.entry})\\n`\n )\n }\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(delegate.entry).href)) as Record<\n string,\n unknown\n >\n } catch (e) {\n throw broken(e instanceof Error ? e.message : String(e))\n }\n if (typeof mod['run'] !== 'function')\n throw broken('dist/index.js does not export run')\n const delegateRun = mod['run'] as (argv: string[]) => Promise<unknown>\n const code = await delegateRun(argv)\n return typeof code === 'number' ? code : 1\n }\n return run(argv)\n}\n\nmain()\n .then((code) => {\n process.exitCode = code\n })\n .catch((e: unknown) => {\n process.exitCode = reportError(e)\n })\n","/** The runtime floor of the published CLI (ADR 0010): Node 22.17, the line where `fs.glob` is stable. */\nexport const MIN_NODE = { major: 22, minor: 17 } as const\nexport const MIN_NODE_LABEL = `${MIN_NODE.major}.${MIN_NODE.minor}`\n\nfunction component(version: string, index: number): number {\n const n = Number.parseInt(version.split('.')[index] ?? '', 10)\n return Number.isNaN(n) ? -1 : n\n}\n\nexport function nodeMajor(version: string): number {\n return Math.max(component(version, 0), 0)\n}\n\n/** True from `MIN_NODE` on: a newer major, or the same major from its minor. */\nexport function isSupportedNode(version: string): boolean {\n const major = component(version, 0)\n const minor = component(version, 1)\n if (major < 0 || minor < 0) return false\n if (major !== MIN_NODE.major) return major > MIN_NODE.major\n return minor >= MIN_NODE.minor\n}\n"],"mappings":";;;;;;;;;;;AACA,SAAS,qBAAqB;;;ACAvB,IAAM,WAAW,EAAE,OAAO,IAAI,OAAO,GAAG;AACxC,IAAM,iBAAiB,GAAG,SAAS,KAAK,IAAI,SAAS,KAAK;AAEjE,SAAS,UAAU,SAAiB,OAAuB;AACzD,QAAM,IAAI,OAAO,SAAS,QAAQ,MAAM,GAAG,EAAE,KAAK,KAAK,IAAI,EAAE;AAC7D,SAAO,OAAO,MAAM,CAAC,IAAI,KAAK;AAChC;AAOO,SAAS,gBAAgB,SAA0B;AACxD,QAAM,QAAQ,UAAU,SAAS,CAAC;AAClC,QAAM,QAAQ,UAAU,SAAS,CAAC;AAClC,MAAI,QAAQ,KAAK,QAAQ,EAAG,QAAO;AACnC,MAAI,UAAU,SAAS,MAAO,QAAO,QAAQ,SAAS;AACtD,SAAO,SAAS,SAAS;AAC3B;;;ADNA,QAAQ,OAAO,GAAG,SAAS,CAAC,MAA6B;AACvD,MAAI,EAAE,SAAS,QAAS,SAAQ,KAAK,CAAC;AACtC,QAAM;AACR,CAAC;AAKD,eAAe,OAAwB;AACrC,MAAI,CAAC,gBAAgB,QAAQ,SAAS,IAAI,GAAG;AAC3C,YAAQ,OAAO;AAAA,MACb,oBAAoB,cAAc,sBAAsB,QAAQ,OAAO;AAAA;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AACA,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,QAAM,iBACJ,aAAa,SAAS,KAAK,CAAC,KAAK,EAAE,KACnC,QAAQ,IAAI,mBAAmB,MAAM;AAGvC,QAAM,YAAY,MAAM,QAAQ,IAAI;AACpC,MAAI,cAAc,KAAM,QAAO;AAC/B,QAAM,WAAW,iBACb,OACA,MAAM,aAAa,QAAQ,IAAI,GAAG,OAAO;AAC7C,MAAI,aAAa,MAAM;AACrB,UAAM,SAAS,CAAC,WACd,IAAI;AAAA,MACF,cAAc,SAAS,OAAO,cAAc,SAAS,IAAI,uCAAuC,MAAM;AAAA,IACxG;AACF,QAAI,QAAQ,IAAI,aAAa,MAAM,KAAK;AACtC,cAAQ,OAAO;AAAA,QACb,mCAAmC,SAAS,OAAO,KAAK,SAAS,KAAK;AAAA;AAAA,MACxE;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,YAAO,MAAM,OAAO,cAAc,SAAS,KAAK,EAAE;AAAA,IAIpD,SAAS,GAAG;AACV,YAAM,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IACzD;AACA,QAAI,OAAO,IAAI,KAAK,MAAM;AACxB,YAAM,OAAO,mCAAmC;AAClD,UAAM,cAAc,IAAI,KAAK;AAC7B,UAAM,OAAO,MAAM,YAAY,IAAI;AACnC,WAAO,OAAO,SAAS,WAAW,OAAO;AAAA,EAC3C;AACA,SAAO,IAAI,IAAI;AACjB;AAEA,KAAK,EACF,KAAK,CAAC,SAAS;AACd,UAAQ,WAAW;AACrB,CAAC,EACA,MAAM,CAAC,MAAe;AACrB,UAAQ,WAAW,YAAY,CAAC;AAClC,CAAC;","names":[]}