approval-md 0.4.5 → 0.4.6

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.
Files changed (44) hide show
  1. package/SPEC.md +13 -2
  2. package/dist/src/channels/telegram.d.ts +105 -31
  3. package/dist/src/channels/telegram.js +157 -81
  4. package/dist/src/channels/telegram.js.map +1 -1
  5. package/dist/src/cli/channel-telegram.d.ts +100 -35
  6. package/dist/src/cli/channel-telegram.js +216 -119
  7. package/dist/src/cli/channel-telegram.js.map +1 -1
  8. package/dist/src/cli/doctor.js +33 -13
  9. package/dist/src/cli/doctor.js.map +1 -1
  10. package/dist/src/cli/help.js +3 -3
  11. package/dist/src/cli/hook-exec-code.d.ts +150 -0
  12. package/dist/src/cli/hook-exec-code.js +357 -0
  13. package/dist/src/cli/hook-exec-code.js.map +1 -0
  14. package/dist/src/cli/hook.d.ts +125 -1
  15. package/dist/src/cli/hook.js +2177 -107
  16. package/dist/src/cli/hook.js.map +1 -1
  17. package/dist/src/cli/wordmark.d.ts +2 -2
  18. package/dist/src/cli/wordmark.js +2 -2
  19. package/dist/src/core/command-class.d.ts +349 -1
  20. package/dist/src/core/command-class.js +2347 -87
  21. package/dist/src/core/command-class.js.map +1 -1
  22. package/dist/src/core/exec-code.d.ts +77 -0
  23. package/dist/src/core/exec-code.js +60 -0
  24. package/dist/src/core/exec-code.js.map +1 -0
  25. package/dist/src/core/git-push-argv.d.ts +111 -0
  26. package/dist/src/core/git-push-argv.js +375 -0
  27. package/dist/src/core/git-push-argv.js.map +1 -0
  28. package/dist/src/core/harness-version.d.ts +71 -30
  29. package/dist/src/core/harness-version.js +101 -34
  30. package/dist/src/core/harness-version.js.map +1 -1
  31. package/dist/src/core/policy-load.d.ts +8 -0
  32. package/dist/src/core/policy-load.js.map +1 -1
  33. package/dist/src/daemon/git-evidence.d.ts +2 -2
  34. package/dist/src/daemon/git-evidence.js +1 -1
  35. package/docs/README-extended.md +3 -2
  36. package/docs/cli-reference.md +20 -7
  37. package/package.json +2 -2
  38. package/schema/event.schema.json +1 -1
  39. package/schema/fixtures/policy/invalid/exec-code-custody-boolean.json +11 -0
  40. package/schema/fixtures/policy/invalid/exec-code-execute-code-value.json +11 -0
  41. package/schema/fixtures/policy/invalid/exec-code-unknown-key.json +12 -0
  42. package/schema/fixtures/policy/valid/exec-code-both.json +17 -0
  43. package/schema/fixtures/policy/valid/exec-code-custody.json +11 -0
  44. package/schema/policy.schema.json +23 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The `exec.code` gate: what the attested policy says about opaque agent code
3
+ * (APRV-510, 0.4.5 candidate).
4
+ *
5
+ * `python3 -c`, `node -e` and kin, an interpreter running a file that is not a
6
+ * skill script, and a Hermes `execute_code` call are all programs whose effect
7
+ * no classifier reads. Before this module every one of them was refused before
8
+ * policy (`hook-opaque`, `hook-unclassified`, `hook-hermes-execute-code-unbound`),
9
+ * and that stays the answer for every policy that does not speak: the gate is
10
+ * CLOSED unless the operator's policy opens it, key by key.
11
+ *
12
+ * Two keys, each opening one thing, and an absent key is the closed answer:
13
+ *
14
+ * - `exec.code.custody: attested` opens the class for the shell forms. It is the
15
+ * operator's statement that credential custody is in place: opaque code run by
16
+ * an agent that can read the tenant's credentials is a way round every gate
17
+ * that guards them, so the class may not exist without that statement.
18
+ * - `exec.code.execute_code: hooked`, beside the first, opens Hermes's
19
+ * `execute_code`. It is the operator's statement that a tool call made from
20
+ * inside the `execute_code` kernel re-fires the hook, which only a live probe
21
+ * can establish (`docs/hermes-hook.md`); without it one `execute_code` call
22
+ * would be an unbounded bypass of the adapter.
23
+ *
24
+ * Pure: a function of the parsed policy and nothing else. It decides whether a
25
+ * call may be CLASSIFIED `exec.code`; what the class then resolves to is the
26
+ * policy's ordinary class resolution (an `exec.code` row, an `exec.*` row, or
27
+ * `defaults.autonomy`), unchanged.
28
+ */
29
+ import type { Policy } from "./policy-load.js";
30
+ /** The `exec` policy block (schema/policy.schema.json, APRV-510). */
31
+ export interface ExecBlock {
32
+ code?: {
33
+ custody?: "attested" | "unattested";
34
+ execute_code?: "hooked" | "unhooked";
35
+ };
36
+ }
37
+ /** The class an opened program is judged under. Mirrors `command-class.ts`. */
38
+ export declare const EXEC_CODE_POLICY_CLASS = "exec.code";
39
+ /** The policy line that opens the class, as a refusal names it. */
40
+ export declare const EXEC_CODE_CUSTODY_KEY = "exec.code.custody: attested";
41
+ /** The policy line that opens Hermes `execute_code`, as a refusal names it. */
42
+ export declare const EXEC_CODE_EXECUTE_KEY = "exec.code.execute_code: hooked";
43
+ /**
44
+ * Why the gate is closed, which decides the refusal's code and words.
45
+ *
46
+ * - `silent`: the policy says nothing about `exec.code` (no `exec` block and no
47
+ * `exec.code` class row), or there is no policy. The refusal is today's,
48
+ * byte for byte.
49
+ * - `unattested`: the policy names `exec.code` (an `exec` block, or a class row
50
+ * for it) without `custody: attested`. The refusal is
51
+ * `hook-exec-code-custody-unattested`, naming the key.
52
+ * - `window`: an open window is standing. A window suspends the policy's
53
+ * answer, and opening this class is a policy statement, so it is not reached
54
+ * through one; the refusal is today's.
55
+ * - `harness`: the adapter binds native bytes this class's payload cannot
56
+ * carry (Codex), so the class is not opened there; the refusal is today's.
57
+ */
58
+ export type ExecCodeClosed = "silent" | "unattested" | "window" | "harness";
59
+ export interface ExecCodeGate {
60
+ /** May a shell segment be classified `exec.code`? */
61
+ shell: boolean;
62
+ /** May a Hermes `execute_code` call be classified `exec.code`? */
63
+ executeCode: boolean;
64
+ /** Why `shell` is false; `null` when it is true. */
65
+ closed: ExecCodeClosed | null;
66
+ }
67
+ /** The gate with everything closed for `reason`. */
68
+ export declare function closedExecCodeGate(reason: ExecCodeClosed): ExecCodeGate;
69
+ /**
70
+ * Does the policy name `exec.code` anywhere? An `exec` block, or a `classes`
71
+ * key that is exactly `exec.code`. A family row (`exec.*`) is not a mention:
72
+ * it was written for `exec.local`, and a policy that predates the class keeps
73
+ * its refusals byte for byte.
74
+ */
75
+ export declare function execCodeMentioned(policy: Policy): boolean;
76
+ /** What `policy` opens. `null` (no policy loaded) opens nothing. */
77
+ export declare function execCodeGate(policy: Policy | null): ExecCodeGate;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The `exec.code` gate: what the attested policy says about opaque agent code
3
+ * (APRV-510, 0.4.5 candidate).
4
+ *
5
+ * `python3 -c`, `node -e` and kin, an interpreter running a file that is not a
6
+ * skill script, and a Hermes `execute_code` call are all programs whose effect
7
+ * no classifier reads. Before this module every one of them was refused before
8
+ * policy (`hook-opaque`, `hook-unclassified`, `hook-hermes-execute-code-unbound`),
9
+ * and that stays the answer for every policy that does not speak: the gate is
10
+ * CLOSED unless the operator's policy opens it, key by key.
11
+ *
12
+ * Two keys, each opening one thing, and an absent key is the closed answer:
13
+ *
14
+ * - `exec.code.custody: attested` opens the class for the shell forms. It is the
15
+ * operator's statement that credential custody is in place: opaque code run by
16
+ * an agent that can read the tenant's credentials is a way round every gate
17
+ * that guards them, so the class may not exist without that statement.
18
+ * - `exec.code.execute_code: hooked`, beside the first, opens Hermes's
19
+ * `execute_code`. It is the operator's statement that a tool call made from
20
+ * inside the `execute_code` kernel re-fires the hook, which only a live probe
21
+ * can establish (`docs/hermes-hook.md`); without it one `execute_code` call
22
+ * would be an unbounded bypass of the adapter.
23
+ *
24
+ * Pure: a function of the parsed policy and nothing else. It decides whether a
25
+ * call may be CLASSIFIED `exec.code`; what the class then resolves to is the
26
+ * policy's ordinary class resolution (an `exec.code` row, an `exec.*` row, or
27
+ * `defaults.autonomy`), unchanged.
28
+ */
29
+ /** The class an opened program is judged under. Mirrors `command-class.ts`. */
30
+ export const EXEC_CODE_POLICY_CLASS = "exec.code";
31
+ /** The policy line that opens the class, as a refusal names it. */
32
+ export const EXEC_CODE_CUSTODY_KEY = "exec.code.custody: attested";
33
+ /** The policy line that opens Hermes `execute_code`, as a refusal names it. */
34
+ export const EXEC_CODE_EXECUTE_KEY = "exec.code.execute_code: hooked";
35
+ /** The gate with everything closed for `reason`. */
36
+ export function closedExecCodeGate(reason) {
37
+ return { shell: false, executeCode: false, closed: reason };
38
+ }
39
+ /**
40
+ * Does the policy name `exec.code` anywhere? An `exec` block, or a `classes`
41
+ * key that is exactly `exec.code`. A family row (`exec.*`) is not a mention:
42
+ * it was written for `exec.local`, and a policy that predates the class keeps
43
+ * its refusals byte for byte.
44
+ */
45
+ export function execCodeMentioned(policy) {
46
+ if (policy.exec !== undefined)
47
+ return true;
48
+ return Object.prototype.hasOwnProperty.call(policy.classes ?? {}, EXEC_CODE_POLICY_CLASS);
49
+ }
50
+ /** What `policy` opens. `null` (no policy loaded) opens nothing. */
51
+ export function execCodeGate(policy) {
52
+ if (policy === null)
53
+ return closedExecCodeGate("silent");
54
+ const code = policy.exec?.code;
55
+ if (code?.custody !== "attested") {
56
+ return closedExecCodeGate(execCodeMentioned(policy) ? "unattested" : "silent");
57
+ }
58
+ return { shell: true, executeCode: code.execute_code === "hooked", closed: null };
59
+ }
60
+ //# sourceMappingURL=exec-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec-code.js","sourceRoot":"","sources":["../../../src/core/exec-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAYH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAC;AAElD,mEAAmE;AACnE,MAAM,CAAC,MAAM,qBAAqB,GAAG,6BAA6B,CAAC;AAEnE,+EAA+E;AAC/E,MAAM,CAAC,MAAM,qBAAqB,GAAG,gCAAgC,CAAC;AA4BtE,oDAAoD;AACpD,MAAM,UAAU,kBAAkB,CAAC,MAAsB;IACvD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC3C,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,sBAAsB,CAAC,CAAC;AAC5F,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,MAAqB;IAChD,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC;IAC/B,IAAI,IAAI,EAAE,OAAO,KAAK,UAAU,EAAE,CAAC;QACjC,OAAO,kBAAkB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACpF,CAAC"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * `git push` read the way git 2.50's option parser reads it (APRV-517).
3
+ *
4
+ * The classifier's `git-push` row used to look for flags by exact spelling:
5
+ * `--delete` and `-d`, `--force` and `-f`. git's parser accepts more than
6
+ * that, and every extra spelling it accepts did the same thing as the one it
7
+ * stands for while classifying as a plain push:
8
+ *
9
+ * - a short bundle: `-ud`, `-du`, `-fd`, `-dn` carry `-d` (and `-f`);
10
+ * - a long-option abbreviation by unique prefix: `--de`, `--del`, `--dele`
11
+ * and `--delet` are `--delete`, `--m` is `--mirror`, `--pru` is `--prune`;
12
+ * - a deleting option the exact list never named: `--prune` removes every
13
+ * remote ref a wildcard refspec no longer matches;
14
+ * - the words after a value-taking option (`-o x`, `--repo x`) shift the
15
+ * positionals, and a global option in front of `push` (`git --no-pager
16
+ * push origin`) shifted them too.
17
+ *
18
+ * So this file is the closed rule: it walks the argv exactly as git's
19
+ * `parse-options.c` does over the option table of `builtin/push.c` in git
20
+ * 2.50, and reports what the push does rather than which words it contains.
21
+ * Anything it cannot walk is a refusal, never a guess:
22
+ *
23
+ * - `unreadable`: a word the shell may split or expand into words this walk
24
+ * never saw (`$`, a backtick, a glob, a brace expansion), a word that came
25
+ * out of a command substitution, or an assignment or global option in
26
+ * front of `push` that steers which configuration git reads (`GIT_*=`,
27
+ * `HOME=`, `XDG_CONFIG_HOME=`, `--git-dir=`, `--work-tree=`,
28
+ * `--config-env=`: `remote.origin.push=:refs/heads/main` deletes the trunk
29
+ * with no refspec on the command line, and `remote.<name>.mirror` turns a
30
+ * plain push into a mirror). Any of these can hold `-d`, `:main` or `+main`;
31
+ * - `unparseable`: an option git does not know, an ambiguous abbreviation, a
32
+ * value where none is taken, a missing value, or a global option in front
33
+ * of `push` this file does not know. git refuses all of these itself, so
34
+ * refusing them costs nothing, and a newer git that grew an option this
35
+ * table lacks is refused rather than read as a plain push;
36
+ * - `runs-program`: `--receive-pack` / `--exec` name the program git starts
37
+ * for the far side, which for a local or `file://` remote runs on this
38
+ * machine, and `git --exec-path=` picks where git finds its helpers. What it runs is a command line this classifier is not reading,
39
+ * the reason `find -exec` is opaque (APRV-283).
40
+ *
41
+ * Negations (`--no-delete`) never clear a flag an earlier word set: a push
42
+ * that both deletes and un-deletes is read as deleting, which only ever picks
43
+ * the stricter class for a spelling nobody writes.
44
+ *
45
+ * The walk is checked against the real binary: tests/git-push-delete-spellings
46
+ * runs every deleting spelling against a bare local remote and asserts the ref
47
+ * is gone, and the generated differential there runs the corpus through git
48
+ * and asserts every deletion and every forced update it observed was
49
+ * classified at least that strictly.
50
+ */
51
+ /** What an option does to the push, for the options whose effect matters. */
52
+ type PushEffect = "force" | "mirror" | "remove" | "prune" | "tags" | "all" | "submodules" | "program" | "help";
53
+ interface PushOption {
54
+ /** The long name as `builtin/push.c` spells it (`no-verify` keeps its `no-`). */
55
+ long: string;
56
+ short?: string;
57
+ /** `required`: the next word when not `=`-joined. `optional`: `=`-joined only. */
58
+ value: "none" | "required" | "optional";
59
+ /** `PARSE_OPT_NONEG`: no `--no-` form. */
60
+ noneg?: boolean;
61
+ /** `OPT_ALIAS`: an abbreviation matching this and its target is not ambiguous. */
62
+ aliasOf?: string;
63
+ effect?: PushEffect;
64
+ }
65
+ /**
66
+ * `git push -h` on git 2.50, in `builtin/push.c` order. Order matters only for
67
+ * which candidate an ambiguity error names, never for which option matches.
68
+ */
69
+ export declare const GIT_PUSH_OPTIONS: readonly PushOption[];
70
+ /** Can the shell turn this word into a different word, or into several? */
71
+ export declare function isUnreadablePushWord(word: string): boolean;
72
+ /** What a `git push` argv does, as far as its class is concerned. */
73
+ export interface GitPushReading {
74
+ /** `--force`, `-f`, `--force-with-lease`, `--force-if-includes`, `--mirror`. */
75
+ force: boolean;
76
+ /** `--delete` / `-d`: every refspec is a ref being removed. */
77
+ remove: boolean;
78
+ /** `--prune`: removes the remote refs a refspec pattern no longer matches. */
79
+ prune: boolean;
80
+ /** `--tags` / `--follow-tags`. */
81
+ tags: boolean;
82
+ /** `--all`, `--branches`, `--mirror`, or a submodule push: the trunk among them. */
83
+ all: boolean;
84
+ /** Non-option words: the repository, then the refspecs. */
85
+ positionals: string[];
86
+ }
87
+ export type GitPushParse = {
88
+ ok: true;
89
+ reading: GitPushReading;
90
+ } | {
91
+ ok: false;
92
+ kind: "unreadable" | "unparseable" | "runs-program";
93
+ detail: string;
94
+ };
95
+ /**
96
+ * Split the words after `git` at the `push` subcommand: the global options in
97
+ * front of it, and the push's own argv after it.
98
+ */
99
+ export declare function splitGitPush(gitArgs: readonly string[]): {
100
+ globals: string[];
101
+ words: string[];
102
+ } | null;
103
+ /**
104
+ * Walk a `git push` argv (the words after `push`) the way git does.
105
+ *
106
+ * `assignments` are the `NAME=value` words in front of `git`, `substituted`
107
+ * says whether any word came out of a command substitution, and `globals` are
108
+ * the git options in front of `push` ({@link splitGitPush}).
109
+ */
110
+ export declare function parseGitPushArgv(words: readonly string[], assignments?: readonly string[], substituted?: boolean, globals?: readonly string[]): GitPushParse;
111
+ export {};
@@ -0,0 +1,375 @@
1
+ /**
2
+ * `git push` read the way git 2.50's option parser reads it (APRV-517).
3
+ *
4
+ * The classifier's `git-push` row used to look for flags by exact spelling:
5
+ * `--delete` and `-d`, `--force` and `-f`. git's parser accepts more than
6
+ * that, and every extra spelling it accepts did the same thing as the one it
7
+ * stands for while classifying as a plain push:
8
+ *
9
+ * - a short bundle: `-ud`, `-du`, `-fd`, `-dn` carry `-d` (and `-f`);
10
+ * - a long-option abbreviation by unique prefix: `--de`, `--del`, `--dele`
11
+ * and `--delet` are `--delete`, `--m` is `--mirror`, `--pru` is `--prune`;
12
+ * - a deleting option the exact list never named: `--prune` removes every
13
+ * remote ref a wildcard refspec no longer matches;
14
+ * - the words after a value-taking option (`-o x`, `--repo x`) shift the
15
+ * positionals, and a global option in front of `push` (`git --no-pager
16
+ * push origin`) shifted them too.
17
+ *
18
+ * So this file is the closed rule: it walks the argv exactly as git's
19
+ * `parse-options.c` does over the option table of `builtin/push.c` in git
20
+ * 2.50, and reports what the push does rather than which words it contains.
21
+ * Anything it cannot walk is a refusal, never a guess:
22
+ *
23
+ * - `unreadable`: a word the shell may split or expand into words this walk
24
+ * never saw (`$`, a backtick, a glob, a brace expansion), a word that came
25
+ * out of a command substitution, or an assignment or global option in
26
+ * front of `push` that steers which configuration git reads (`GIT_*=`,
27
+ * `HOME=`, `XDG_CONFIG_HOME=`, `--git-dir=`, `--work-tree=`,
28
+ * `--config-env=`: `remote.origin.push=:refs/heads/main` deletes the trunk
29
+ * with no refspec on the command line, and `remote.<name>.mirror` turns a
30
+ * plain push into a mirror). Any of these can hold `-d`, `:main` or `+main`;
31
+ * - `unparseable`: an option git does not know, an ambiguous abbreviation, a
32
+ * value where none is taken, a missing value, or a global option in front
33
+ * of `push` this file does not know. git refuses all of these itself, so
34
+ * refusing them costs nothing, and a newer git that grew an option this
35
+ * table lacks is refused rather than read as a plain push;
36
+ * - `runs-program`: `--receive-pack` / `--exec` name the program git starts
37
+ * for the far side, which for a local or `file://` remote runs on this
38
+ * machine, and `git --exec-path=` picks where git finds its helpers. What it runs is a command line this classifier is not reading,
39
+ * the reason `find -exec` is opaque (APRV-283).
40
+ *
41
+ * Negations (`--no-delete`) never clear a flag an earlier word set: a push
42
+ * that both deletes and un-deletes is read as deleting, which only ever picks
43
+ * the stricter class for a spelling nobody writes.
44
+ *
45
+ * The walk is checked against the real binary: tests/git-push-delete-spellings
46
+ * runs every deleting spelling against a bare local remote and asserts the ref
47
+ * is gone, and the generated differential there runs the corpus through git
48
+ * and asserts every deletion and every forced update it observed was
49
+ * classified at least that strictly.
50
+ */
51
+ /**
52
+ * `git push -h` on git 2.50, in `builtin/push.c` order. Order matters only for
53
+ * which candidate an ambiguity error names, never for which option matches.
54
+ */
55
+ export const GIT_PUSH_OPTIONS = [
56
+ { long: "verbose", short: "v", value: "none" },
57
+ { long: "quiet", short: "q", value: "none" },
58
+ { long: "repo", value: "required" },
59
+ { long: "all", value: "none", effect: "all" },
60
+ { long: "branches", value: "none", aliasOf: "all", effect: "all" },
61
+ { long: "mirror", value: "none", effect: "mirror" },
62
+ { long: "delete", short: "d", value: "none", effect: "remove" },
63
+ { long: "tags", value: "none", effect: "tags" },
64
+ { long: "dry-run", short: "n", value: "none" },
65
+ { long: "porcelain", value: "none" },
66
+ { long: "force", short: "f", value: "none", effect: "force" },
67
+ { long: "force-with-lease", value: "optional", effect: "force" },
68
+ { long: "force-if-includes", value: "none", effect: "force" },
69
+ { long: "recurse-submodules", value: "required", effect: "submodules" },
70
+ { long: "thin", value: "none" },
71
+ { long: "receive-pack", value: "required", effect: "program" },
72
+ { long: "exec", value: "required", effect: "program" },
73
+ { long: "set-upstream", short: "u", value: "none" },
74
+ { long: "progress", value: "none" },
75
+ { long: "prune", value: "none", effect: "prune" },
76
+ { long: "no-verify", value: "none" },
77
+ { long: "follow-tags", value: "none", effect: "tags" },
78
+ { long: "signed", value: "optional" },
79
+ { long: "atomic", value: "none" },
80
+ { long: "push-option", short: "o", value: "required" },
81
+ { long: "ipv4", short: "4", value: "none", noneg: true },
82
+ { long: "ipv6", short: "6", value: "none", noneg: true },
83
+ ];
84
+ /**
85
+ * The help options parse-options itself answers, by exact spelling only
86
+ * (`-h` is the short one): each prints usage and exits without pushing, so it
87
+ * adds nothing to the reading.
88
+ */
89
+ const INTERNAL_LONG = ["help", "help-all"];
90
+ /**
91
+ * Global options in front of the subcommand (`git.c` `handle_options`, git
92
+ * 2.50), matched by exact spelling, as git matches them. These take no value
93
+ * and change nothing about what a push sends.
94
+ */
95
+ const GIT_GLOBAL_BARE = [
96
+ "-p",
97
+ "--paginate",
98
+ "-P",
99
+ "--no-pager",
100
+ "--no-replace-objects",
101
+ "--no-lazy-fetch",
102
+ "--no-optional-locks",
103
+ "--no-advice",
104
+ "--bare",
105
+ "--literal-pathspecs",
106
+ "--glob-pathspecs",
107
+ "--noglob-pathspecs",
108
+ "--icase-pathspecs",
109
+ ];
110
+ /** `=`-joined globals that change nothing about what a push sends either. */
111
+ const GIT_GLOBAL_JOINED = ["--namespace=", "--attr-source="];
112
+ /**
113
+ * `=`-joined globals that decide which configuration the push runs under:
114
+ * another repository's `.git/config` (`--git-dir`, `--work-tree`) or a value
115
+ * injected from the environment (`--config-env`). Configuration can carry a
116
+ * deleting refspec or `mirror = true`, so these read like a steering
117
+ * assignment.
118
+ */
119
+ const GIT_GLOBAL_STEERING = ["--git-dir=", "--work-tree=", "--config-env="];
120
+ /** `--exec-path=` picks the directory git runs its helper programs from. */
121
+ const GIT_GLOBAL_PROGRAM = "--exec-path";
122
+ // Anything else in front of `push` is refused, the separate-value forms
123
+ // (`-C dir`, `-c k=v`, `--git-dir dir`) included: there the word the
124
+ // classifier took for the subcommand may have been that option's value.
125
+ /** Assignments in front of `git` that steer which configuration it reads. */
126
+ const STEERING_ENV = /^(?:GIT_[A-Za-z0-9_]*|HOME|XDG_CONFIG_HOME)=/u;
127
+ /** `$`, a backtick, or a glob character: the shell may expand the word into others. */
128
+ const EXPANDING_CHAR = /[$`*?[\]]/u;
129
+ /** A brace expansion: `{a,b}` or `{1..3}`. A reflog `@{1}` is neither. */
130
+ const BRACE_EXPANSION = /\{[^{}]*(?:,|\.\.)[^{}]*\}/u;
131
+ /** Can the shell turn this word into a different word, or into several? */
132
+ export function isUnreadablePushWord(word) {
133
+ return EXPANDING_CHAR.test(word) || BRACE_EXPANSION.test(word);
134
+ }
135
+ /** Are these two options one option under two names (`OPT_ALIAS`)? */
136
+ function isAlias(a, b) {
137
+ return a.aliasOf === b.long || b.aliasOf === a.long || (a.aliasOf !== undefined && a.aliasOf === b.aliasOf);
138
+ }
139
+ /**
140
+ * `parse_long_opt` in git 2.50's `parse-options.c`, over `name` (the text
141
+ * after `--` and before any `=`).
142
+ *
143
+ * An exact spelling wins outright. Otherwise every option the text is a
144
+ * prefix of is a candidate, positively or through `no-`; two candidates that
145
+ * are not aliases of each other are ambiguous, which git refuses.
146
+ */
147
+ function matchLong(name) {
148
+ let abbrev = null;
149
+ let ambiguous = false;
150
+ const candidate = (option, unset) => {
151
+ if (abbrev !== null && !isAlias(abbrev.option, option))
152
+ ambiguous = true;
153
+ abbrev = { option, unset };
154
+ };
155
+ for (const option of GIT_PUSH_OPTIONS) {
156
+ let long = option.long;
157
+ let optUnset = false;
158
+ if (long.startsWith("no-")) {
159
+ long = long.slice(3);
160
+ optUnset = true;
161
+ }
162
+ if (name.startsWith(long)) {
163
+ if (name === long)
164
+ return { option, unset: optUnset };
165
+ continue;
166
+ }
167
+ if (long.startsWith(name)) {
168
+ candidate(option, optUnset);
169
+ continue;
170
+ }
171
+ if (option.noneg === true)
172
+ continue;
173
+ if ("no-".startsWith(name)) {
174
+ candidate(option, !optUnset);
175
+ continue;
176
+ }
177
+ if (!name.startsWith("no-"))
178
+ continue;
179
+ const rest = name.slice(3);
180
+ if (rest.startsWith(long)) {
181
+ if (rest === long)
182
+ return { option, unset: !optUnset };
183
+ continue;
184
+ }
185
+ if (long.startsWith(rest))
186
+ candidate(option, !optUnset);
187
+ }
188
+ if (ambiguous)
189
+ return "ambiguous";
190
+ return abbrev;
191
+ }
192
+ /** The option a short letter names, or `null`. */
193
+ function matchShort(letter) {
194
+ return GIT_PUSH_OPTIONS.find((option) => option.short === letter) ?? null;
195
+ }
196
+ /**
197
+ * Split the words after `git` at the `push` subcommand: the global options in
198
+ * front of it, and the push's own argv after it.
199
+ */
200
+ export function splitGitPush(gitArgs) {
201
+ const at = gitArgs.findIndex((word) => !(word.startsWith("-") && word !== "-"));
202
+ if (at === -1 || gitArgs[at] !== "push")
203
+ return null;
204
+ return { globals: gitArgs.slice(0, at), words: gitArgs.slice(at + 1) };
205
+ }
206
+ /** The global options in front of `push`, judged; `null` when they change nothing. */
207
+ function judgeGlobals(globals) {
208
+ for (const word of globals) {
209
+ if (isUnreadablePushWord(word)) {
210
+ return { ok: false, kind: "unreadable", detail: `the shell may expand ${word} into other words` };
211
+ }
212
+ if (GIT_GLOBAL_BARE.includes(word))
213
+ continue;
214
+ if (GIT_GLOBAL_JOINED.some((prefix) => word.startsWith(prefix)))
215
+ continue;
216
+ if (GIT_GLOBAL_STEERING.some((prefix) => word.startsWith(prefix))) {
217
+ return {
218
+ ok: false,
219
+ kind: "unreadable",
220
+ detail: `git ${word.slice(0, word.indexOf("=") + 1)}… decides which configuration the push reads`,
221
+ };
222
+ }
223
+ if (word === GIT_GLOBAL_PROGRAM || word.startsWith(`${GIT_GLOBAL_PROGRAM}=`)) {
224
+ return { ok: false, kind: "runs-program", detail: "git --exec-path picks the directory git runs its helpers from" };
225
+ }
226
+ return {
227
+ ok: false,
228
+ kind: "unparseable",
229
+ detail: `git ${word} in front of push: this classifier does not read that global option`,
230
+ };
231
+ }
232
+ return null;
233
+ }
234
+ /**
235
+ * Walk a `git push` argv (the words after `push`) the way git does.
236
+ *
237
+ * `assignments` are the `NAME=value` words in front of `git`, `substituted`
238
+ * says whether any word came out of a command substitution, and `globals` are
239
+ * the git options in front of `push` ({@link splitGitPush}).
240
+ */
241
+ export function parseGitPushArgv(words, assignments = [], substituted = false, globals = []) {
242
+ const globalRefusal = judgeGlobals(globals);
243
+ if (globalRefusal !== null)
244
+ return globalRefusal;
245
+ if (substituted) {
246
+ return { ok: false, kind: "unreadable", detail: "a word of this push is a command substitution's output" };
247
+ }
248
+ const steering = assignments.find((word) => STEERING_ENV.test(word));
249
+ if (steering !== undefined) {
250
+ return {
251
+ ok: false,
252
+ kind: "unreadable",
253
+ detail: `${steering.slice(0, steering.indexOf("="))}=… in front of git steers which configuration the push reads`,
254
+ };
255
+ }
256
+ const unreadable = words.find(isUnreadablePushWord);
257
+ if (unreadable !== undefined) {
258
+ return { ok: false, kind: "unreadable", detail: `the shell may expand ${unreadable} into other words` };
259
+ }
260
+ const reading = {
261
+ force: false,
262
+ remove: false,
263
+ prune: false,
264
+ tags: false,
265
+ all: false,
266
+ positionals: [],
267
+ };
268
+ const unparseable = (detail) => ({ ok: false, kind: "unparseable", detail });
269
+ const apply = (option, unset, value) => {
270
+ if (unset)
271
+ return null;
272
+ switch (option.effect) {
273
+ case "force":
274
+ reading.force = true;
275
+ break;
276
+ case "mirror":
277
+ reading.force = true;
278
+ reading.all = true;
279
+ break;
280
+ case "remove":
281
+ reading.remove = true;
282
+ break;
283
+ case "prune":
284
+ reading.prune = true;
285
+ break;
286
+ case "tags":
287
+ reading.tags = true;
288
+ break;
289
+ case "all":
290
+ reading.all = true;
291
+ break;
292
+ case "submodules":
293
+ // `check` only verifies and `no` turns it off; `on-demand` and `only`
294
+ // push the submodules' own branches, which may be their trunks.
295
+ if (value !== "check" && value !== "no")
296
+ reading.all = true;
297
+ break;
298
+ case "program":
299
+ return {
300
+ ok: false,
301
+ kind: "runs-program",
302
+ detail: `git push --${option.long} names the program git runs for the far side`,
303
+ };
304
+ default:
305
+ break;
306
+ }
307
+ return null;
308
+ };
309
+ for (let index = 0; index < words.length; index += 1) {
310
+ const word = words[index];
311
+ if (word === "--" || word === "--end-of-options") {
312
+ reading.positionals.push(...words.slice(index + 1));
313
+ break;
314
+ }
315
+ if (word.startsWith("--")) {
316
+ const body = word.slice(2);
317
+ const equals = body.indexOf("=");
318
+ const name = equals === -1 ? body : body.slice(0, equals);
319
+ if (INTERNAL_LONG.includes(body))
320
+ continue;
321
+ const matched = matchLong(name);
322
+ if (matched === "ambiguous")
323
+ return unparseable(`git push --${name} is ambiguous`);
324
+ if (matched === null)
325
+ return unparseable(`git push has no option --${name}`);
326
+ const { option, unset } = matched;
327
+ let value;
328
+ if (equals !== -1) {
329
+ if (unset || option.value === "none")
330
+ return unparseable(`git push --${name} takes no value`);
331
+ value = body.slice(equals + 1);
332
+ }
333
+ else if (!unset && option.value === "required") {
334
+ if (index + 1 >= words.length)
335
+ return unparseable(`git push --${name} requires a value`);
336
+ index += 1;
337
+ value = words[index];
338
+ }
339
+ const refusal = apply(option, unset, value);
340
+ if (refusal !== null)
341
+ return refusal;
342
+ continue;
343
+ }
344
+ if (word.startsWith("-") && word !== "-") {
345
+ const letters = word.slice(1);
346
+ for (let at = 0; at < letters.length; at += 1) {
347
+ const letter = letters[at];
348
+ if (letter === "h")
349
+ break;
350
+ const option = matchShort(letter);
351
+ if (option === null)
352
+ return unparseable(`git push has no switch -${letter}`);
353
+ if (option.value === "required") {
354
+ // The rest of the bundle is the value, or else the next word.
355
+ if (at + 1 >= letters.length) {
356
+ if (index + 1 >= words.length)
357
+ return unparseable(`git push -${letter} requires a value`);
358
+ index += 1;
359
+ }
360
+ const refusal = apply(option, false, undefined);
361
+ if (refusal !== null)
362
+ return refusal;
363
+ break;
364
+ }
365
+ const refusal = apply(option, false, undefined);
366
+ if (refusal !== null)
367
+ return refusal;
368
+ }
369
+ continue;
370
+ }
371
+ reading.positionals.push(word);
372
+ }
373
+ return { ok: true, reading };
374
+ }
375
+ //# sourceMappingURL=git-push-argv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-push-argv.js","sourceRoot":"","sources":["../../../src/core/git-push-argv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AA2BH;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA0B;IACrD,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE;IAC9C,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE;IAC5C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE;IACnC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;IAC7C,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;IAClE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE;IACnD,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE;IAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAC/C,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE;IAC9C,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE;IACpC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IAC7D,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE;IAChE,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IAC7D,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE;IACvE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAC/B,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE;IAC9D,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE;IACtD,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE;IACnD,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE;IACnC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IACjD,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE;IACpC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACtD,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE;IACrC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE;IACjC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE;IACtD,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;IACxD,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;CACzD,CAAC;AAEF;;;;GAIG;AACH,MAAM,aAAa,GAAsB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAE9D;;;;GAIG;AACH,MAAM,eAAe,GAAsB;IACzC,IAAI;IACJ,YAAY;IACZ,IAAI;IACJ,YAAY;IACZ,sBAAsB;IACtB,iBAAiB;IACjB,qBAAqB;IACrB,aAAa;IACb,QAAQ;IACR,qBAAqB;IACrB,kBAAkB;IAClB,oBAAoB;IACpB,mBAAmB;CACpB,CAAC;AACF,6EAA6E;AAC7E,MAAM,iBAAiB,GAAsB,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;AAChF;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAsB,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;AAC/F,4EAA4E;AAC5E,MAAM,kBAAkB,GAAG,aAAa,CAAC;AACzC,wEAAwE;AACxE,qEAAqE;AACrE,wEAAwE;AAExE,6EAA6E;AAC7E,MAAM,YAAY,GAAG,+CAA+C,CAAC;AAErE,uFAAuF;AACvF,MAAM,cAAc,GAAG,YAAY,CAAC;AACpC,0EAA0E;AAC1E,MAAM,eAAe,GAAG,6BAA6B,CAAC;AAEtD,2EAA2E;AAC3E,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjE,CAAC;AA4BD,sEAAsE;AACtE,SAAS,OAAO,CAAC,CAAa,EAAE,CAAa;IAC3C,OAAO,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;AAC9G,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,MAAM,GAAmB,IAAI,CAAC;IAClC,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,MAAM,SAAS,GAAG,CAAC,MAAkB,EAAE,KAAc,EAAQ,EAAE;QAC7D,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;YAAE,SAAS,GAAG,IAAI,CAAC;QACzE,MAAM,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC,CAAC;IACF,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACtC,IAAI,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACvB,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACrB,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;YACtD,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC5B,SAAS;QACX,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI;YAAE,SAAS;QACpC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,SAAS,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,SAAS;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,CAAC;YACvD,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,SAAS;QAAE,OAAO,WAAW,CAAC;IAClC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,kDAAkD;AAClD,SAAS,UAAU,CAAC,MAAc;IAChC,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAA0B;IACrD,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IAChF,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACrD,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;AACzE,CAAC;AAED,sFAAsF;AACtF,SAAS,YAAY,CAAC,OAA0B;IAC9C,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,wBAAwB,IAAI,mBAAmB,EAAE,CAAC;QACpG,CAAC;QACD,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7C,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAAE,SAAS;QAC1E,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YAClE,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,YAAY;gBAClB,MAAM,EAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,8CAA8C;aAClG,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,KAAK,kBAAkB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,kBAAkB,GAAG,CAAC,EAAE,CAAC;YAC7E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,+DAA+D,EAAE,CAAC;QACtH,CAAC;QACD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,OAAO,IAAI,qEAAqE;SACzF,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAwB,EACxB,WAAW,GAAsB,EAAE,EACnC,WAAW,GAAG,KAAK,EACnB,OAAO,GAAsB,EAAE;IAE/B,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,aAAa,CAAC;IACjD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,wDAAwD,EAAE,CAAC;IAC7G,CAAC;IACD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,8DAA8D;SAClH,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,wBAAwB,UAAU,mBAAmB,EAAE,CAAC;IAC1G,CAAC;IAED,MAAM,OAAO,GAAmB;QAC9B,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,KAAK;QACb,KAAK,EAAE,KAAK;QACZ,IAAI,EAAE,KAAK;QACX,GAAG,EAAE,KAAK;QACV,WAAW,EAAE,EAAE;KAChB,CAAC;IACF,MAAM,WAAW,GAAG,CAAC,MAAc,EAAgB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;IACnG,MAAM,KAAK,GAAG,CAAC,MAAkB,EAAE,KAAc,EAAE,KAAyB,EAAuB,EAAE;QACnG,IAAI,KAAK;YAAE,OAAO,IAAI,CAAC;QACvB,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,KAAK,OAAO;gBACV,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;gBACrB,MAAM;YACR,KAAK,QAAQ;gBACX,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;gBACrB,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;gBACnB,MAAM;YACR,KAAK,QAAQ;gBACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;gBACtB,MAAM;YACR,KAAK,OAAO;gBACV,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;gBACrB,MAAM;YACR,KAAK,MAAM;gBACT,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;gBACpB,MAAM;YACR,KAAK,KAAK;gBACR,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;gBACnB,MAAM;YACR,KAAK,YAAY;gBACf,sEAAsE;gBACtE,gEAAgE;gBAChE,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,IAAI;oBAAE,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;gBAC5D,MAAM;YACR,KAAK,SAAS;gBACZ,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,cAAc,MAAM,CAAC,IAAI,8CAA8C;iBAChF,CAAC;YACJ;gBACE,MAAM;QACV,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAW,CAAC;QACpC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACjD,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;YACpD,MAAM;QACR,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YAC1D,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC3C,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,OAAO,KAAK,WAAW;gBAAE,OAAO,WAAW,CAAC,cAAc,IAAI,eAAe,CAAC,CAAC;YACnF,IAAI,OAAO,KAAK,IAAI;gBAAE,OAAO,WAAW,CAAC,4BAA4B,IAAI,EAAE,CAAC,CAAC;YAC7E,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;YAClC,IAAI,KAAyB,CAAC;YAC9B,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClB,IAAI,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM;oBAAE,OAAO,WAAW,CAAC,cAAc,IAAI,iBAAiB,CAAC,CAAC;gBAC9F,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACjC,CAAC;iBAAM,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;gBACjD,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM;oBAAE,OAAO,WAAW,CAAC,cAAc,IAAI,mBAAmB,CAAC,CAAC;gBACzF,KAAK,IAAI,CAAC,CAAC;gBACX,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;YACD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YAC5C,IAAI,OAAO,KAAK,IAAI;gBAAE,OAAO,OAAO,CAAC;YACrC,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;gBAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,CAAW,CAAC;gBACrC,IAAI,MAAM,KAAK,GAAG;oBAAE,MAAM;gBAC1B,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;gBAClC,IAAI,MAAM,KAAK,IAAI;oBAAE,OAAO,WAAW,CAAC,2BAA2B,MAAM,EAAE,CAAC,CAAC;gBAC7E,IAAI,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;oBAChC,8DAA8D;oBAC9D,IAAI,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;wBAC7B,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM;4BAAE,OAAO,WAAW,CAAC,aAAa,MAAM,mBAAmB,CAAC,CAAC;wBAC1F,KAAK,IAAI,CAAC,CAAC;oBACb,CAAC;oBACD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;oBAChD,IAAI,OAAO,KAAK,IAAI;wBAAE,OAAO,OAAO,CAAC;oBACrC,MAAM;gBACR,CAAC;gBACD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;gBAChD,IAAI,OAAO,KAAK,IAAI;oBAAE,OAAO,OAAO,CAAC;YACvC,CAAC;YACD,SAAS;QACX,CAAC;QACD,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC"}