@rness/cli 0.17.2 → 0.18.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 CHANGED
@@ -98,28 +98,42 @@ the files a given agent needs, for the agents the team declares in
98
98
  get a Claude Code plugin, `.claude/skills/rness/`, with five commands:
99
99
  `/rness:status [tab]`, the tables of `rness status`, and the lifecycle
100
100
  skills below. rness owns those files whole — an edit by hand is reported
101
- by `sync --check` and written back by `sync`. Nothing in them depends on
101
+ by `sync --check` and written back by `sync`. The plugin's manifest,
102
+ `.claude-plugin/plugin.json`, also carries the agent-plugins.org
103
+ `$schema`, the author, homepage, repository, licence and keywords, so a
104
+ scanner that looks for an Agent Plugins manifest finds one; Claude Code
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
102
107
  the version; the last line of the status skill names the workspace's
103
108
  package manager, so changing `packageManager` in `.rness/package.json`
104
109
  leaves it stale until the next `sync`. Claude Code loads the plugin once
105
110
  the folder is trusted, in a session started there.
106
- - **The lifecycle skills**: `/rness:adr [subject | NNNN]` records a decision
107
- as an ADR, `/rness:spec [subject | NNNN]` writes a specification,
108
- `/rness:plan <spec>` turns an approved specification into a plan, and
109
- `/rness:done [plan]` closes a piece of work — each task checked on
110
- evidence, then the plan `Completed`, its specification `Implemented`, and
111
- the documents the work made inaccurate corrected. Each is a procedure
112
- loaded into the conversation, not a file generator: after a decision has
113
- been discussed, `/rness:adr` writes it from the conversation; otherwise
114
- it asks, one question at a time. The skill stays in the conversation for
115
- the next turns, and the file carries the work to the next session
116
- (`/rness:adr 0010` reopens it). The agent may start one itself — an ADR
117
- when a choice is expensive to reverse — but writes nothing without a yes,
118
- except `/rness:done` on a plan whose last task has just passed.
119
- The rules stay in `.rness/CONVENTIONS.md`; the skills only add the steps.
120
- A new document takes the collection's first status (`Proposed` for an
121
- ADR, `Draft` otherwise) and the next number of the local checkout; two
122
- 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. Each skill records its session: it adds
123
137
  `{ id: <session id>, agent: <model> }` to `sessions:` in the front matter
124
138
  of what it writes or closes. The agent is the model it runs as, as Claude
125
139
  Code names it (`Claude Opus 5.5`): no variable gives it to a skill. An
@@ -381,11 +395,13 @@ it through one adapter; `git` still does what git does (clone, pull, push,
381
395
  credentials), and the provider's API the rest (organizations, creating a
382
396
  repository, the board).
383
397
 
384
- - `rness create` asks `Where does your organization live?`: GitHub, and
385
- GitLab and Atlassian (Bitbucket + Jira) shown disabled, coming later.
386
- `--provider github` answers it off a terminal. A blank workspace asks
387
- nothing. Joining an organization asks first as well, then takes the
388
- provider its `rness.json` names.
398
+ - `rness create` asks `Where does your organization live?` first: GitHub,
399
+ GitLab and Atlassian (Bitbucket + Jira) shown disabled, coming later, and
400
+ `No organization yet: a blank local workspace` (the `--blank` of
401
+ "Blank workspace"). `--provider github` answers it off a terminal;
402
+ `--org`, `--repos` and `--blank` settle it unasked. Joining an
403
+ organization asks first as well, then takes the provider its `rness.json`
404
+ names.
389
405
  - A workspace without the key is read from its first repository URL: a
390
406
  GitLab host reads as `gitlab`, any other host — or no repository — as
391
407
  `github`. Nothing to change: `pulse create` writes it, and refuses a
@@ -457,8 +473,23 @@ anonymously.
457
473
  GitHub, anonymous or with `--yes`, it prints the two manual steps instead
458
474
  — create the empty repository on github.com, then `git remote add origin …
459
475
  && git push`. No other tool is ever needed.
460
- - An organization that restricts OAuth apps hides its private repositories
461
- until an owner approves "Rness"; `create` says so, with the link.
476
+ - Logged in, the wizard lists the organizations you belong to that have
477
+ approved "Rness" — GitHub shows an OAuth app no other — your account
478
+ last, then `an organization not listed here…` for a typed name: one that
479
+ has not approved rness yet, an outside collaborator's, a public one.
480
+ Right after the
481
+ organization, before the SSH test, the probe of `<org>/.rness` and the
482
+ listing, `create` checks your access: an organization that restricts
483
+ OAuth apps and has not approved "Rness" hides its private repositories,
484
+ so the wizard asks `Open github.com to approve rness for <org> now?`,
485
+ opens the approval page in your browser (printed only over SSH) and waits
486
+ — polling every 5 seconds, for 10 minutes at most — until an owner's
487
+ click makes you a member in its eyes; then it goes on with the full
488
+ listing. Declined, or timed out, it goes on with what is visible and
489
+ names the page for later; with `--yes` or off a terminal it prints the
490
+ warning and the page, and asks nothing. The order matters: a private
491
+ `.rness` probed through a token the organization has not approved would
492
+ read as absent, and `create` would start a second one.
462
493
  - Over HTTPS, rness's own clones and pulls carry the login — through the
463
494
  environment of that one git command, never in a URL or `.git/config`. For
464
495
  your own `git pull` and `git push`, `login` offers to make rness git's
@@ -572,6 +603,52 @@ per repository, the files to commit there.
572
603
  Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
573
604
  `RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
574
605
 
606
+ ## 0.18.0 — the wizard asks where first and waits for the approval; the skills on one grammar; Node 22.17
607
+
608
+ - The published CLI runs on **Node 22.17 or later** (ADR 0010); the guard
609
+ compares major and minor. A workspace pinned to 0.17.x keeps refusing
610
+ Node 22 until its pin moves: from inside it, `npx @rness/cli@latest
611
+ upgrade` works under Node 22, since `upgrade` is served by the copy
612
+ invoked, never the pinned one.
613
+ - `rness create` asks **where the organization lives first** — the blank
614
+ workspace is that question's last answer — then offers the login, which
615
+ now lists **the organizations you belong to that have approved rness**
616
+ (your account last, then `an organization not listed here…` for the
617
+ rest). Right after the organization and
618
+ before anything reads it, an organization that restricts OAuth apps and
619
+ has not approved "Rness" gets its **approval page opened in your
620
+ browser**; the wizard waits for the owner's click (10 minutes at most)
621
+ and then lists the private repositories too. See "GitHub login".
622
+ - `/rness:adr`, `/rness:spec` and `/rness:plan` read their first word as
623
+ the verb: `create`, `open` (a bare number), and for a plan `from <spec>`
624
+ — which **approves the specification** it plans — and `check NNNN`, the
625
+ proofs of a plan, in place of `/rness:done`. `/rness:done` is retired:
626
+ `rness sync` removes its `SKILL.md` where an earlier release wrote it
627
+ (`removed` in its output); commit the deletion in each repository, as
628
+ `upgrade`'s next steps list. Note: `/rness:plan 0028` now opens plan
629
+ 0028; a plan is made with `from <spec>`. See "Agent targets".
630
+ - `rness doc new <collection> [--title <text>]` writes the next numbered
631
+ document of `adr`, `specs` or `plans` and prints its path: the skills
632
+ allocate with it instead of counting. `rness validate` and the edit hook
633
+ refuse two documents with one number in a collection.
634
+ - The day of a release, `pnpm create rness` runs the previous version:
635
+ pnpm ≥ 11 holds back a package younger than 24 hours
636
+ (`minimumReleaseAge`). `rness upgrade` installs the latest all the same.
637
+
638
+ ## 0.17.3 — the packages name the product; the plugin manifest for scanners
639
+
640
+ - `homepage` of `@rness/cli`, `create-rness` and `@rness/create` is
641
+ `https://rness.dev`; `repository` and `bugs` stay on GitHub. That is
642
+ how a scanner tells an official package from a fork;
643
+ `pnpm check:versions` checks it with the versions.
644
+ - `.claude/skills/rness/.claude-plugin/plugin.json`, written by the Claude
645
+ target, carries the agent-plugins.org `$schema`, the author, homepage,
646
+ repository, licence and keywords. `rness sync` rewrites it once in each
647
+ repository; commit it there.
648
+ - `skills/rness/SKILL.md` at the root of the repository: when to use Rness
649
+ and how to install and run it, for `npx skills add rness-dev/rness`
650
+ and skills.sh.
651
+
575
652
  ## 0.17.2 — the lifecycle skills move statuses and commit their files
576
653
 
577
654
  - `/rness:adr`, `/rness:spec`, `/rness:plan` and `/rness:done` let the
@@ -1058,4 +1135,4 @@ workspace pins exactly that build and no cache serves an older one under its
1058
1135
  number. To try it in a workspace that exists, run `rness upgrade <version>`
1059
1136
  inside it; the deploy prints the line.
1060
1137
 
1061
- Node ≥ 24. MIT.
1138
+ 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-REDELHNC.js";
9
+ } from "../chunk-VGBS7HDY.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":[]}