@codyswann/lisa 4.70.3 → 4.71.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/all/copy-overwrite/scripts/lib/automation-provenance-contract.mjs +174 -0
- package/all/copy-overwrite/scripts/lib/automation-provenance-local.mjs +279 -0
- package/all/copy-overwrite/scripts/lib/gate-failure-diagnosis.mjs +17 -7
- package/all/copy-overwrite/scripts/lib/github-attestation-provider.mjs +241 -0
- package/all/copy-overwrite/scripts/lib/github-attestation-recovery.mjs +283 -0
- package/all/copy-overwrite/scripts/lib/github-attestation-verifier.mjs +244 -0
- package/all/copy-overwrite/scripts/lib/history-secret-evidence-shape.mjs +188 -0
- package/all/copy-overwrite/scripts/lib/history-secret-evidence.mjs +271 -0
- package/all/copy-overwrite/scripts/lib/history-secret-scanner.mjs +6 -296
- package/all/copy-overwrite/scripts/lib/npm-update-allocate.mjs +289 -0
- package/all/copy-overwrite/scripts/lib/npm-update-authorization.mjs +235 -0
- package/all/copy-overwrite/scripts/lib/npm-update-broker-client.mjs +92 -0
- package/all/copy-overwrite/scripts/lib/npm-update-checkpoint.mjs +241 -0
- package/all/copy-overwrite/scripts/lib/npm-update-contract.mjs +278 -0
- package/all/copy-overwrite/scripts/lib/npm-update-controller-broker.mjs +234 -0
- package/all/copy-overwrite/scripts/lib/npm-update-controller-factory.mjs +278 -0
- package/all/copy-overwrite/scripts/lib/npm-update-controller-recipe.mjs +135 -0
- package/all/copy-overwrite/scripts/lib/npm-update-execution-adapter.mjs +292 -0
- package/all/copy-overwrite/scripts/lib/npm-update-gate-hooks.mjs +214 -0
- package/all/copy-overwrite/scripts/lib/npm-update-gate-install.mjs +267 -0
- package/all/copy-overwrite/scripts/lib/npm-update-gate-proof.mjs +99 -0
- package/all/copy-overwrite/scripts/lib/npm-update-gate.mjs +300 -0
- package/all/copy-overwrite/scripts/lib/npm-update-gh-dispatch.mjs +182 -0
- package/all/copy-overwrite/scripts/lib/npm-update-gh-grants.mjs +156 -0
- package/all/copy-overwrite/scripts/lib/npm-update-gh-requests.mjs +221 -0
- package/all/copy-overwrite/scripts/lib/npm-update-github.mjs +214 -0
- package/all/copy-overwrite/scripts/lib/npm-update-helper-graph.mjs +238 -0
- package/all/copy-overwrite/scripts/lib/npm-update-helper-inventory.mjs +126 -0
- package/all/copy-overwrite/scripts/lib/npm-update-helper.mjs +292 -0
- package/all/copy-overwrite/scripts/lib/npm-update-hook-installation.mjs +116 -0
- package/all/copy-overwrite/scripts/lib/npm-update-hook-preload.mjs +153 -0
- package/all/copy-overwrite/scripts/lib/npm-update-hook-provider.mjs +207 -0
- package/all/copy-overwrite/scripts/lib/npm-update-hook-read-client.mjs +164 -0
- package/all/copy-overwrite/scripts/lib/npm-update-hosted-gate.mjs +272 -0
- package/all/copy-overwrite/scripts/lib/npm-update-hosted-hook.mjs +157 -0
- package/all/copy-overwrite/scripts/lib/npm-update-invariants.mjs +28 -0
- package/all/copy-overwrite/scripts/lib/npm-update-isolation.mjs +11 -0
- package/all/copy-overwrite/scripts/lib/npm-update-leaf-contract.mjs +171 -0
- package/all/copy-overwrite/scripts/lib/npm-update-leaf.mjs +194 -0
- package/all/copy-overwrite/scripts/lib/npm-update-native-process.mjs +155 -0
- package/all/copy-overwrite/scripts/lib/npm-update-npm.mjs +190 -0
- package/all/copy-overwrite/scripts/lib/npm-update-object.mjs +112 -0
- package/all/copy-overwrite/scripts/lib/npm-update-orchestrator.mjs +273 -0
- package/all/copy-overwrite/scripts/lib/npm-update-owner.mjs +292 -0
- package/all/copy-overwrite/scripts/lib/npm-update-prepare.mjs +263 -0
- package/all/copy-overwrite/scripts/lib/npm-update-process-core.mjs +179 -0
- package/all/copy-overwrite/scripts/lib/npm-update-process.mjs +16 -0
- package/all/copy-overwrite/scripts/lib/npm-update-publication.mjs +258 -0
- package/all/copy-overwrite/scripts/lib/npm-update-publish.mjs +258 -0
- package/all/copy-overwrite/scripts/lib/npm-update-quality.mjs +153 -0
- package/all/copy-overwrite/scripts/lib/npm-update-recovery.mjs +264 -0
- package/all/copy-overwrite/scripts/lib/npm-update-runtime-archive.mjs +204 -0
- package/all/copy-overwrite/scripts/lib/npm-update-runtime-graph.mjs +185 -0
- package/all/copy-overwrite/scripts/lib/npm-update-runtime-transport.mjs +221 -0
- package/all/copy-overwrite/scripts/lib/npm-update-runtime.mjs +284 -0
- package/all/copy-overwrite/scripts/lib/npm-update-tool-launcher.mjs +287 -0
- package/all/copy-overwrite/scripts/lib/npm-update-worker-environment.mjs +161 -0
- package/all/copy-overwrite/scripts/lib/npm-update-worker-inspection.mjs +142 -0
- package/all/copy-overwrite/scripts/lib/npm-update-worker-lifecycle.mjs +256 -0
- package/all/copy-overwrite/scripts/lib/npm-update-worker-policy.mjs +266 -0
- package/all/copy-overwrite/scripts/lib/process-tree-runner.mjs +230 -36
- package/all/copy-overwrite/scripts/lisa-automation-provenance.mjs +161 -0
- package/all/copy-overwrite/scripts/lisa-history-secrets.mjs +8 -1
- package/all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh +89 -5
- package/all/copy-overwrite/scripts/lisa-npm-updater.mjs +204 -0
- package/all/copy-overwrite/scripts/lisa-run-gates.mjs +48 -123
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +107 -41
- package/all/copy-overwrite/scripts/npm-updater-gate-runtime.json +1 -0
- package/all/copy-overwrite/scripts/npm-updater-gate-supervisor.c +121 -0
- package/all/copy-overwrite/scripts/npm-updater-gate.Dockerfile +49 -0
- package/all/copy-overwrite/scripts/npm-updater-helper-graph.json +1085 -0
- package/dist/codex/scripts/block-no-verify.sh +89 -5
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +620 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +165 -13
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/opencode/plugin-templates/block-no-verify.sh +89 -5
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/hooks/block-no-verify.agy.sh +89 -5
- package/plugins/lisa/hooks/block-no-verify.sh +89 -5
- package/plugins/lisa-agy/hooks/block-no-verify.agy.sh +89 -5
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/hooks/block-no-verify.sh +89 -5
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/block-no-verify.sh +89 -5
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/hooks/block-no-verify.agy.sh +89 -5
- package/plugins/src/base/hooks/block-no-verify.sh +89 -5
- package/scripts/check-shipped-surface-removals.mjs +96 -24
- package/scripts/generate-npm-updater-helper-graph.mjs +184 -0
- package/scripts/two-channel-couplings.json +31 -7
- package/typescript/copy-contents/.husky/commit-msg +18 -0
- package/typescript/copy-overwrite/.prettierignore +2 -0
|
@@ -152,6 +152,7 @@ fi
|
|
|
152
152
|
|
|
153
153
|
if ! BLOCK_NO_VERIFY_COMMAND="$command_str" python3 - <<'PY'
|
|
154
154
|
import os
|
|
155
|
+
import io
|
|
155
156
|
import re
|
|
156
157
|
import shlex
|
|
157
158
|
import sys
|
|
@@ -1284,6 +1285,57 @@ def git_skips_verification(text, depth=0):
|
|
|
1284
1285
|
return False
|
|
1285
1286
|
|
|
1286
1287
|
|
|
1288
|
+
def git_config_reads_key(tokens, index):
|
|
1289
|
+
"""Whether this key is a read operand of this exact Git config invocation.
|
|
1290
|
+
|
|
1291
|
+
Keep the command boundary: a query cannot authorize the next command or
|
|
1292
|
+
turn a later setting into a read. Unknown options remain conservative.
|
|
1293
|
+
"""
|
|
1294
|
+
start = index
|
|
1295
|
+
while start > 0 and tokens[start - 1] not in COMMAND_SEPARATORS:
|
|
1296
|
+
start -= 1
|
|
1297
|
+
end = index + 1
|
|
1298
|
+
while end < len(tokens) and tokens[end] not in COMMAND_SEPARATORS:
|
|
1299
|
+
end += 1
|
|
1300
|
+
program, args, opaque = command_word(tokens[start:end])
|
|
1301
|
+
if opaque or program != "git":
|
|
1302
|
+
return False
|
|
1303
|
+
found = subcommand_after_git(args, 0)
|
|
1304
|
+
if not found or found[0] != "config":
|
|
1305
|
+
return False
|
|
1306
|
+
argv = found[1]
|
|
1307
|
+
key_offset = index - (end - len(argv))
|
|
1308
|
+
read = bool(argv and argv[0] == "get")
|
|
1309
|
+
cursor = 1 if read else 0
|
|
1310
|
+
operands = []
|
|
1311
|
+
read_actions = {"--get", "--get-all", "--get-regexp", "--get-urlmatch"}
|
|
1312
|
+
modifiers = {
|
|
1313
|
+
"--local", "--global", "--system", "--worktree", "--includes",
|
|
1314
|
+
"--no-includes", "--show-origin", "--show-scope", "--null", "-z",
|
|
1315
|
+
"--name-only", "--all", "--regexp",
|
|
1316
|
+
}
|
|
1317
|
+
value_options = {"--file", "-f", "--blob", "--type", "--default", "--value"}
|
|
1318
|
+
while cursor < len(argv):
|
|
1319
|
+
token = argv[cursor]
|
|
1320
|
+
if token in read_actions:
|
|
1321
|
+
if read:
|
|
1322
|
+
return False
|
|
1323
|
+
read = True
|
|
1324
|
+
elif token in value_options:
|
|
1325
|
+
if cursor + 1 >= len(argv):
|
|
1326
|
+
return False
|
|
1327
|
+
cursor += 1
|
|
1328
|
+
elif token in modifiers:
|
|
1329
|
+
pass
|
|
1330
|
+
elif token.startswith("-"):
|
|
1331
|
+
if not any(token.startswith(option + "=") for option in value_options):
|
|
1332
|
+
return False
|
|
1333
|
+
else:
|
|
1334
|
+
operands.append(cursor)
|
|
1335
|
+
cursor += 1
|
|
1336
|
+
return bool(operands and operands[0] == key_offset and (read or len(operands) == 1))
|
|
1337
|
+
|
|
1338
|
+
|
|
1287
1339
|
def token_bypass(tokens):
|
|
1288
1340
|
"""Whether any token disables hooks by environment or by git config.
|
|
1289
1341
|
|
|
@@ -1295,7 +1347,7 @@ def token_bypass(tokens):
|
|
|
1295
1347
|
option, and an option belongs to an argv.
|
|
1296
1348
|
|
|
1297
1349
|
Args:
|
|
1298
|
-
tokens:
|
|
1350
|
+
tokens: Operator-aware tokens of one command or script.
|
|
1299
1351
|
|
|
1300
1352
|
Returns:
|
|
1301
1353
|
True when a token disables verification.
|
|
@@ -1321,7 +1373,9 @@ def token_bypass(tokens):
|
|
|
1321
1373
|
if lowered.startswith("core.hookspath="):
|
|
1322
1374
|
if not is_permitted_hooks_path(token.split("=", 1)[1]):
|
|
1323
1375
|
return True
|
|
1324
|
-
if lowered == "core.hookspath" and i + 1 < len(tokens)
|
|
1376
|
+
if (lowered == "core.hookspath" and i + 1 < len(tokens)
|
|
1377
|
+
and tokens[i + 1] not in COMMAND_SEPARATORS
|
|
1378
|
+
and not git_config_reads_key(tokens, i)):
|
|
1325
1379
|
if not is_permitted_hooks_path(tokens[i + 1]):
|
|
1326
1380
|
return True
|
|
1327
1381
|
# `git --config-env=core.hooksPath=SOMEVAR` sets the same config, reading
|
|
@@ -1388,8 +1442,22 @@ def token_bypass(tokens):
|
|
|
1388
1442
|
return False
|
|
1389
1443
|
|
|
1390
1444
|
|
|
1445
|
+
class OperatorStream(io.StringIO):
|
|
1446
|
+
"""Remember punctuation read while shlex is inside a quote or escape."""
|
|
1447
|
+
|
|
1448
|
+
lexer = None
|
|
1449
|
+
literal_operator = False
|
|
1450
|
+
|
|
1451
|
+
def read(self, size=-1):
|
|
1452
|
+
value = super().read(size)
|
|
1453
|
+
if (self.lexer is not None and self.lexer.state in {"'", '"', "\\"}
|
|
1454
|
+
and any(char in "();|&<>" for char in value)):
|
|
1455
|
+
self.literal_operator = True
|
|
1456
|
+
return value
|
|
1457
|
+
|
|
1458
|
+
|
|
1391
1459
|
def flat_tokens(text):
|
|
1392
|
-
"""
|
|
1460
|
+
"""Operator-aware tokens without printed data, or None on a lex failure.
|
|
1393
1461
|
|
|
1394
1462
|
Args:
|
|
1395
1463
|
text: A command line or a script's contents.
|
|
@@ -1398,9 +1466,25 @@ def flat_tokens(text):
|
|
|
1398
1466
|
The token list, or None.
|
|
1399
1467
|
"""
|
|
1400
1468
|
try:
|
|
1401
|
-
|
|
1469
|
+
stream = OperatorStream(line_boundaries_as_separators(text))
|
|
1470
|
+
lexer = shlex.shlex(stream, posix=True, punctuation_chars=True)
|
|
1471
|
+
lexer.whitespace_split = True
|
|
1472
|
+
lexer.commenters = ""
|
|
1473
|
+
stream.lexer = lexer
|
|
1474
|
+
tokens = []
|
|
1475
|
+
while True:
|
|
1476
|
+
stream.literal_operator = False
|
|
1477
|
+
token = lexer.get_token()
|
|
1478
|
+
if token is None:
|
|
1479
|
+
break
|
|
1480
|
+
# shlex otherwise makes quoted ";" indistinguishable from a real
|
|
1481
|
+
# command boundary. Keep literal destinations as data, so a setter
|
|
1482
|
+
# cannot masquerade as a one-operand configuration read.
|
|
1483
|
+
if token in COMMAND_SEPARATORS and stream.literal_operator:
|
|
1484
|
+
token = "\x00" + token
|
|
1485
|
+
tokens.append(token)
|
|
1402
1486
|
return [
|
|
1403
|
-
token
|
|
1487
|
+
token
|
|
1404
1488
|
for index, token in enumerate(tokens)
|
|
1405
1489
|
if not printed_argument(tokens, index)
|
|
1406
1490
|
]
|
|
@@ -152,6 +152,7 @@ fi
|
|
|
152
152
|
|
|
153
153
|
if ! BLOCK_NO_VERIFY_COMMAND="$command_str" python3 - <<'PY'
|
|
154
154
|
import os
|
|
155
|
+
import io
|
|
155
156
|
import re
|
|
156
157
|
import shlex
|
|
157
158
|
import sys
|
|
@@ -1284,6 +1285,57 @@ def git_skips_verification(text, depth=0):
|
|
|
1284
1285
|
return False
|
|
1285
1286
|
|
|
1286
1287
|
|
|
1288
|
+
def git_config_reads_key(tokens, index):
|
|
1289
|
+
"""Whether this key is a read operand of this exact Git config invocation.
|
|
1290
|
+
|
|
1291
|
+
Keep the command boundary: a query cannot authorize the next command or
|
|
1292
|
+
turn a later setting into a read. Unknown options remain conservative.
|
|
1293
|
+
"""
|
|
1294
|
+
start = index
|
|
1295
|
+
while start > 0 and tokens[start - 1] not in COMMAND_SEPARATORS:
|
|
1296
|
+
start -= 1
|
|
1297
|
+
end = index + 1
|
|
1298
|
+
while end < len(tokens) and tokens[end] not in COMMAND_SEPARATORS:
|
|
1299
|
+
end += 1
|
|
1300
|
+
program, args, opaque = command_word(tokens[start:end])
|
|
1301
|
+
if opaque or program != "git":
|
|
1302
|
+
return False
|
|
1303
|
+
found = subcommand_after_git(args, 0)
|
|
1304
|
+
if not found or found[0] != "config":
|
|
1305
|
+
return False
|
|
1306
|
+
argv = found[1]
|
|
1307
|
+
key_offset = index - (end - len(argv))
|
|
1308
|
+
read = bool(argv and argv[0] == "get")
|
|
1309
|
+
cursor = 1 if read else 0
|
|
1310
|
+
operands = []
|
|
1311
|
+
read_actions = {"--get", "--get-all", "--get-regexp", "--get-urlmatch"}
|
|
1312
|
+
modifiers = {
|
|
1313
|
+
"--local", "--global", "--system", "--worktree", "--includes",
|
|
1314
|
+
"--no-includes", "--show-origin", "--show-scope", "--null", "-z",
|
|
1315
|
+
"--name-only", "--all", "--regexp",
|
|
1316
|
+
}
|
|
1317
|
+
value_options = {"--file", "-f", "--blob", "--type", "--default", "--value"}
|
|
1318
|
+
while cursor < len(argv):
|
|
1319
|
+
token = argv[cursor]
|
|
1320
|
+
if token in read_actions:
|
|
1321
|
+
if read:
|
|
1322
|
+
return False
|
|
1323
|
+
read = True
|
|
1324
|
+
elif token in value_options:
|
|
1325
|
+
if cursor + 1 >= len(argv):
|
|
1326
|
+
return False
|
|
1327
|
+
cursor += 1
|
|
1328
|
+
elif token in modifiers:
|
|
1329
|
+
pass
|
|
1330
|
+
elif token.startswith("-"):
|
|
1331
|
+
if not any(token.startswith(option + "=") for option in value_options):
|
|
1332
|
+
return False
|
|
1333
|
+
else:
|
|
1334
|
+
operands.append(cursor)
|
|
1335
|
+
cursor += 1
|
|
1336
|
+
return bool(operands and operands[0] == key_offset and (read or len(operands) == 1))
|
|
1337
|
+
|
|
1338
|
+
|
|
1287
1339
|
def token_bypass(tokens):
|
|
1288
1340
|
"""Whether any token disables hooks by environment or by git config.
|
|
1289
1341
|
|
|
@@ -1295,7 +1347,7 @@ def token_bypass(tokens):
|
|
|
1295
1347
|
option, and an option belongs to an argv.
|
|
1296
1348
|
|
|
1297
1349
|
Args:
|
|
1298
|
-
tokens:
|
|
1350
|
+
tokens: Operator-aware tokens of one command or script.
|
|
1299
1351
|
|
|
1300
1352
|
Returns:
|
|
1301
1353
|
True when a token disables verification.
|
|
@@ -1321,7 +1373,9 @@ def token_bypass(tokens):
|
|
|
1321
1373
|
if lowered.startswith("core.hookspath="):
|
|
1322
1374
|
if not is_permitted_hooks_path(token.split("=", 1)[1]):
|
|
1323
1375
|
return True
|
|
1324
|
-
if lowered == "core.hookspath" and i + 1 < len(tokens)
|
|
1376
|
+
if (lowered == "core.hookspath" and i + 1 < len(tokens)
|
|
1377
|
+
and tokens[i + 1] not in COMMAND_SEPARATORS
|
|
1378
|
+
and not git_config_reads_key(tokens, i)):
|
|
1325
1379
|
if not is_permitted_hooks_path(tokens[i + 1]):
|
|
1326
1380
|
return True
|
|
1327
1381
|
# `git --config-env=core.hooksPath=SOMEVAR` sets the same config, reading
|
|
@@ -1388,8 +1442,22 @@ def token_bypass(tokens):
|
|
|
1388
1442
|
return False
|
|
1389
1443
|
|
|
1390
1444
|
|
|
1445
|
+
class OperatorStream(io.StringIO):
|
|
1446
|
+
"""Remember punctuation read while shlex is inside a quote or escape."""
|
|
1447
|
+
|
|
1448
|
+
lexer = None
|
|
1449
|
+
literal_operator = False
|
|
1450
|
+
|
|
1451
|
+
def read(self, size=-1):
|
|
1452
|
+
value = super().read(size)
|
|
1453
|
+
if (self.lexer is not None and self.lexer.state in {"'", '"', "\\"}
|
|
1454
|
+
and any(char in "();|&<>" for char in value)):
|
|
1455
|
+
self.literal_operator = True
|
|
1456
|
+
return value
|
|
1457
|
+
|
|
1458
|
+
|
|
1391
1459
|
def flat_tokens(text):
|
|
1392
|
-
"""
|
|
1460
|
+
"""Operator-aware tokens without printed data, or None on a lex failure.
|
|
1393
1461
|
|
|
1394
1462
|
Args:
|
|
1395
1463
|
text: A command line or a script's contents.
|
|
@@ -1398,9 +1466,25 @@ def flat_tokens(text):
|
|
|
1398
1466
|
The token list, or None.
|
|
1399
1467
|
"""
|
|
1400
1468
|
try:
|
|
1401
|
-
|
|
1469
|
+
stream = OperatorStream(line_boundaries_as_separators(text))
|
|
1470
|
+
lexer = shlex.shlex(stream, posix=True, punctuation_chars=True)
|
|
1471
|
+
lexer.whitespace_split = True
|
|
1472
|
+
lexer.commenters = ""
|
|
1473
|
+
stream.lexer = lexer
|
|
1474
|
+
tokens = []
|
|
1475
|
+
while True:
|
|
1476
|
+
stream.literal_operator = False
|
|
1477
|
+
token = lexer.get_token()
|
|
1478
|
+
if token is None:
|
|
1479
|
+
break
|
|
1480
|
+
# shlex otherwise makes quoted ";" indistinguishable from a real
|
|
1481
|
+
# command boundary. Keep literal destinations as data, so a setter
|
|
1482
|
+
# cannot masquerade as a one-operand configuration read.
|
|
1483
|
+
if token in COMMAND_SEPARATORS and stream.literal_operator:
|
|
1484
|
+
token = "\x00" + token
|
|
1485
|
+
tokens.append(token)
|
|
1402
1486
|
return [
|
|
1403
|
-
token
|
|
1487
|
+
token
|
|
1404
1488
|
for index, token in enumerate(tokens)
|
|
1405
1489
|
if not printed_argument(tokens, index)
|
|
1406
1490
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.71.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.71.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.71.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.71.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.71.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|