@sema-agent/core 7.19.0 → 7.20.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/CHANGELOG.md +183 -2
- package/dist/agents/subagent.js +12 -20
- package/dist/agents/teacher.js +2 -5
- package/dist/agents/verify.js +21 -10
- package/dist/brain/anthropic.js +3 -1
- package/dist/brain/open-responses.js +4 -2
- package/dist/brain/openai.js +3 -1
- package/dist/brain/stream-engine.d.ts +4 -0
- package/dist/brain/stream-engine.js +4 -0
- package/dist/core/auto-mode.d.ts +37 -18
- package/dist/core/auto-mode.js +1 -1
- package/dist/core/child-clamp-seats.d.ts +79 -0
- package/dist/core/child-clamp-seats.js +29 -0
- package/dist/core/engine-notice.d.ts +67 -49
- package/dist/core/fs-write-gate-policy.d.ts +17 -9
- package/dist/core/fs-write-gate-policy.js +51 -4
- package/dist/core/gate-bounded-await.d.ts +38 -0
- package/dist/core/gate-bounded-await.js +53 -0
- package/dist/core/gate-fold.js +16 -48
- package/dist/core/gate-lanes.js +11 -3
- package/dist/core/gate-outcome.d.ts +9 -6
- package/dist/core/governance-codes.d.ts +16 -1
- package/dist/core/governance-codes.js +12 -0
- package/dist/core/hooks.d.ts +8 -8
- package/dist/core/memory-engine/engine.d.ts +14 -9
- package/dist/core/memory-engine/engine.js +21 -8
- package/dist/core/memory-engine/layout.d.ts +31 -0
- package/dist/core/memory-engine/layout.js +68 -3
- package/dist/core/memory-engine/types.d.ts +24 -0
- package/dist/core/memory.d.ts +19 -0
- package/dist/core/memory.js +12 -0
- package/dist/core/remote-env.d.ts +32 -0
- package/dist/core/remote-env.js +4 -1
- package/dist/core/runner/advertised-writable-dirs.d.ts +59 -1
- package/dist/core/runner/advertised-writable-dirs.js +51 -3
- package/dist/core/runner/announce-once-ledger.d.ts +15 -0
- package/dist/core/runner/announce-once-ledger.js +8 -0
- package/dist/core/runner/classifier-ladder.d.ts +5 -0
- package/dist/core/runner/classifier-ladder.js +13 -2
- package/dist/core/runner/contracts.d.ts +44 -1
- package/dist/core/runner/denial-limit-arms.d.ts +14 -1
- package/dist/core/runner/denial-limit-arms.js +5 -4
- package/dist/core/runner/env-capability-census.d.ts +30 -0
- package/dist/core/runner/env-capability-census.js +38 -0
- package/dist/core/runner/forward-sink.d.ts +32 -0
- package/dist/core/runner/forward-sink.js +41 -0
- package/dist/core/runner/gate-exit.d.ts +4 -0
- package/dist/core/runner/gate-exit.js +4 -1
- package/dist/core/runner/git-status-frame.d.ts +0 -9
- package/dist/core/runner/listing-fold.d.ts +57 -0
- package/dist/core/runner/listing-fold.js +75 -0
- package/dist/core/runner/prepare-execution-env.d.ts +1 -1
- package/dist/core/runner/prepare-execution-env.js +2 -0
- package/dist/core/runner/prepare-gate-stations.d.ts +8 -0
- package/dist/core/runner/prepare-gate-stations.js +6 -2
- package/dist/core/runner/prepare-hands-readface.d.ts +4 -0
- package/dist/core/runner/prepare-hands-readface.js +3 -5
- package/dist/core/runner/prepare-listings.d.ts +3 -0
- package/dist/core/runner/prepare-listings.js +4 -2
- package/dist/core/runner/prepare-memory.js +7 -1
- package/dist/core/runner/prepare-policy-chain.js +5 -5
- package/dist/core/runner/prepare-prompt-inputs.d.ts +2 -2
- package/dist/core/runner/prepare-run-refs.d.ts +4 -2
- package/dist/core/runner/prepare-run-refs.js +5 -4
- package/dist/core/runner/prepare-task.js +7 -5
- package/dist/core/runner/run-clock-and-content.js +3 -7
- package/dist/core/runner/run-harness-handlers.js +10 -10
- package/dist/core/runner/run-leg.js +28 -19
- package/dist/core/runner/run-settle-and-teardown.js +2 -5
- package/dist/core/runner/run-turn-boundary.js +44 -33
- package/dist/core/runner/runtask.js +2 -1
- package/dist/core/runner/synthetic-tools.d.ts +13 -39
- package/dist/core/runner/synthetic-tools.js +15 -59
- package/dist/core/runner/task-root-canonical.d.ts +45 -0
- package/dist/core/runner/task-root-canonical.js +18 -0
- package/dist/core/runner/turn-attachments.d.ts +125 -49
- package/dist/core/runner/turn-attachments.js +124 -66
- package/dist/core/safe-notify.d.ts +5 -0
- package/dist/core/safe-notify.js +24 -2
- package/dist/core/sensitive-path-policy.d.ts +53 -27
- package/dist/core/sensitive-path-policy.js +16 -26
- package/dist/core/skill-listing-budget.d.ts +34 -40
- package/dist/core/skill-listing-budget.js +25 -26
- package/dist/core/skills-directory.js +17 -10
- package/dist/core/task-registry.js +2 -1
- package/dist/core/task-spec.d.ts +8 -7
- package/dist/core/tool-policy.d.ts +12 -1
- package/dist/core/tool-policy.js +39 -25
- package/dist/core/write-protect.d.ts +98 -18
- package/dist/core/write-protect.js +88 -34
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -4
- package/dist/orchestration/workflow-primitives.js +10 -20
- package/dist/stores/file/memory-store.d.ts +5 -2
- package/dist/stores/file/memory-store.js +8 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +13 -2
- package/dist/tools/fs/bash-readonly-classifier.js +317 -35
- package/dist/tools/fs/fs-bash.d.ts +1 -1
- package/dist/tools/fs/fs-bash.js +12 -25
- package/dist/tools/fs/fs-shared.d.ts +22 -0
- package/dist/tools/fs/fs-shared.js +30 -0
- package/dist/tools/fs/index.d.ts +1 -1
- package/dist/tools/fs/index.js +1 -1
- package/package.json +2 -1
- package/test/export-surface.snapshot.json +19 -3
- package/wire-changes/core@7.20.0.json +568 -0
|
@@ -8,7 +8,10 @@ export const BASH_READONLY_DEFAULT_ALLOW = [
|
|
|
8
8
|
"cal", "uptime", "id", "groups", "nproc", "locale", "free", "realpath", "readlink",
|
|
9
9
|
"true", "false", "seq", "expr", "type", "sleep", "diff", "cmp", "comm",
|
|
10
10
|
];
|
|
11
|
-
export const
|
|
11
|
+
export const BASH_CLASSIFY_EXTRA_ALLOW = ["find", "sed", "cd"];
|
|
12
|
+
export function bashClassifyDefaultAllow() {
|
|
13
|
+
return [...BASH_READONLY_DEFAULT_ALLOW, ...BASH_CLASSIFY_EXTRA_ALLOW];
|
|
14
|
+
}
|
|
12
15
|
const SHELL_OPERATORS = /[;&|<>$()`\n\r\\]/;
|
|
13
16
|
function hasBareShellOperator(s, quotedOperatorsAreText) {
|
|
14
17
|
if (!quotedOperatorsAreText)
|
|
@@ -446,18 +449,6 @@ function isGrepPatternFlagToken(tok) {
|
|
|
446
449
|
}
|
|
447
450
|
return /^-[A-Za-z0-9]*[ef]/.test(tok);
|
|
448
451
|
}
|
|
449
|
-
function isGrepPatternPayloadLongOption(tok) {
|
|
450
|
-
if (!tok.includes("="))
|
|
451
|
-
return false;
|
|
452
|
-
const name = longOptionNameOf(tok);
|
|
453
|
-
return name !== undefined && isLongOptionAbbrevOf(name, "regexp");
|
|
454
|
-
}
|
|
455
|
-
function isCutDelimiterPayloadLongOption(tok) {
|
|
456
|
-
if (!tok.includes("="))
|
|
457
|
-
return false;
|
|
458
|
-
const name = longOptionNameOf(tok);
|
|
459
|
-
return name !== undefined && (isLongOptionAbbrevOf(name, "delimiter") || isLongOptionAbbrevOf(name, "output-delimiter"));
|
|
460
|
-
}
|
|
461
452
|
function isGrepClusterFileStdin(tok) {
|
|
462
453
|
if (tok.startsWith("--") || !/^-[A-Za-z0-9]/.test(tok))
|
|
463
454
|
return false;
|
|
@@ -472,6 +463,283 @@ function isGrepClusterFileStdin(tok) {
|
|
|
472
463
|
}
|
|
473
464
|
return false;
|
|
474
465
|
}
|
|
466
|
+
function valueNamesAFile(kind) {
|
|
467
|
+
return kind === "path" || kind === "indirect" || kind === "form" || kind === "header" || kind === "url";
|
|
468
|
+
}
|
|
469
|
+
function widestValueKind(kinds) {
|
|
470
|
+
if (kinds.has("indirect"))
|
|
471
|
+
return "indirect";
|
|
472
|
+
if (kinds.has("path"))
|
|
473
|
+
return "path";
|
|
474
|
+
if (kinds.has("form"))
|
|
475
|
+
return "form";
|
|
476
|
+
if (kinds.has("header"))
|
|
477
|
+
return "header";
|
|
478
|
+
if (kinds.has("url"))
|
|
479
|
+
return "url";
|
|
480
|
+
return [...kinds][0];
|
|
481
|
+
}
|
|
482
|
+
const VERB_OPTION_SLOTS = {
|
|
483
|
+
head: {
|
|
484
|
+
shortValue: { c: "count", n: "count" },
|
|
485
|
+
shortPlain: "qvz",
|
|
486
|
+
longValue: { bytes: "count", lines: "count" },
|
|
487
|
+
longOptionalValue: {},
|
|
488
|
+
longPlain: ["help", "quiet", "silent", "verbose", "version", "zero-terminated"],
|
|
489
|
+
},
|
|
490
|
+
tail: {
|
|
491
|
+
shortValue: { b: "count", c: "count", n: "count", s: "count" },
|
|
492
|
+
shortPlain: "fFqvz",
|
|
493
|
+
longValue: { bytes: "count", lines: "count", "max-unchanged-stats": "count", pid: "count", "sleep-interval": "count" },
|
|
494
|
+
longOptionalValue: { follow: "label" },
|
|
495
|
+
longPlain: ["help", "quiet", "retry", "silent", "verbose", "version", "zero-terminated"],
|
|
496
|
+
},
|
|
497
|
+
cut: {
|
|
498
|
+
shortValue: { b: "count", c: "count", d: "delimiter", f: "count" },
|
|
499
|
+
shortPlain: "nsz",
|
|
500
|
+
longValue: { bytes: "count", characters: "count", delimiter: "delimiter", fields: "count", "output-delimiter": "delimiter" },
|
|
501
|
+
longOptionalValue: {},
|
|
502
|
+
longPlain: ["complement", "help", "only-delimited", "version", "zero-terminated"],
|
|
503
|
+
},
|
|
504
|
+
grep: {
|
|
505
|
+
shortValue: { A: "count", B: "count", C: "count", D: "label", d: "label", e: "pattern", f: "path", m: "count" },
|
|
506
|
+
shortPlain: "0123456789abcEFGhHiIlLnoPqrRsUvVwxyzZ",
|
|
507
|
+
longValue: {
|
|
508
|
+
"after-context": "count",
|
|
509
|
+
"before-context": "count",
|
|
510
|
+
"binary-files": "label",
|
|
511
|
+
devices: "label",
|
|
512
|
+
directories: "label",
|
|
513
|
+
exclude: "name-pattern",
|
|
514
|
+
"exclude-dir": "name-pattern",
|
|
515
|
+
"exclude-from": "path",
|
|
516
|
+
file: "path",
|
|
517
|
+
"group-separator": "label",
|
|
518
|
+
include: "name-pattern",
|
|
519
|
+
label: "label",
|
|
520
|
+
"max-count": "count",
|
|
521
|
+
regexp: "pattern",
|
|
522
|
+
},
|
|
523
|
+
longOptionalValue: { color: "label", colour: "label", context: "count" },
|
|
524
|
+
longPlain: [
|
|
525
|
+
"basic-regexp", "byte-offset", "count", "dereference-recursive", "extended-regexp",
|
|
526
|
+
"files-with-matches", "files-without-match", "fixed-strings", "help", "ignore-case", "initial-tab",
|
|
527
|
+
"invert-match", "line-buffered", "line-number", "line-regexp", "no-filename", "no-group-separator",
|
|
528
|
+
"no-messages", "null", "null-data", "only-matching", "perl-regexp", "quiet", "recursive", "silent",
|
|
529
|
+
"text", "version", "with-filename", "word-regexp",
|
|
530
|
+
],
|
|
531
|
+
},
|
|
532
|
+
diff: {
|
|
533
|
+
shortValue: { C: "count", D: "label", F: "pattern", I: "pattern", L: "label", S: "path", U: "count", W: "count", X: "path", x: "name-pattern" },
|
|
534
|
+
shortPlain: "abBcdeEHilnNpqrstTuvwyZ",
|
|
535
|
+
longValue: {
|
|
536
|
+
exclude: "name-pattern",
|
|
537
|
+
"exclude-from": "path",
|
|
538
|
+
"from-file": "path",
|
|
539
|
+
"horizon-lines": "count",
|
|
540
|
+
ifdef: "label",
|
|
541
|
+
"ignore-matching-lines": "pattern",
|
|
542
|
+
label: "label",
|
|
543
|
+
"show-function-line": "pattern",
|
|
544
|
+
"starting-file": "path",
|
|
545
|
+
tabsize: "count",
|
|
546
|
+
"to-file": "path",
|
|
547
|
+
width: "count",
|
|
548
|
+
},
|
|
549
|
+
longOptionalValue: { color: "label", context: "count", unified: "count" },
|
|
550
|
+
longPlain: [
|
|
551
|
+
"brief", "ed", "expand-tabs", "help", "ignore-all-space", "ignore-blank-lines", "ignore-case",
|
|
552
|
+
"ignore-space-change", "ignore-tab-expansion", "ignore-trailing-space", "initial-tab", "minimal",
|
|
553
|
+
"new-file", "normal", "paginate", "recursive", "report-identical-files", "rcs", "show-c-function",
|
|
554
|
+
"side-by-side", "speed-large-files", "suppress-blank-empty", "text", "version",
|
|
555
|
+
],
|
|
556
|
+
},
|
|
557
|
+
cmp: {
|
|
558
|
+
shortValue: { i: "count", n: "count" },
|
|
559
|
+
shortPlain: "blsv",
|
|
560
|
+
longValue: { bytes: "count", "ignore-initial": "count" },
|
|
561
|
+
longOptionalValue: {},
|
|
562
|
+
longPlain: ["help", "print-bytes", "quiet", "silent", "verbose", "version"],
|
|
563
|
+
},
|
|
564
|
+
sed: {
|
|
565
|
+
shortValue: { e: "script", f: "path" },
|
|
566
|
+
shortPlain: "nrEszu",
|
|
567
|
+
longValue: { expression: "script", file: "path", "line-length": "count" },
|
|
568
|
+
longOptionalValue: { "in-place": "label" },
|
|
569
|
+
longPlain: [
|
|
570
|
+
"debug", "follow-symlinks", "help", "null-data", "posix", "quiet", "regexp-extended", "sandbox",
|
|
571
|
+
"separate", "silent", "unbuffered", "version", "zero-terminated",
|
|
572
|
+
],
|
|
573
|
+
},
|
|
574
|
+
date: {
|
|
575
|
+
shortValue: { d: "count", f: "path", r: "path", s: "count" },
|
|
576
|
+
shortPlain: "uR",
|
|
577
|
+
longValue: { date: "count", file: "path", reference: "path", "rfc-3339": "count", set: "count" },
|
|
578
|
+
longOptionalValue: { "iso-8601": "label" },
|
|
579
|
+
longPlain: ["debug", "help", "rfc-822", "rfc-email", "universal", "utc", "version"],
|
|
580
|
+
},
|
|
581
|
+
tar: {
|
|
582
|
+
shortValue: { b: "count", C: "path", f: "path", T: "path", X: "path" },
|
|
583
|
+
shortPlain: "acdhjJkmOpPrStuvwWxzZ",
|
|
584
|
+
longValue: {
|
|
585
|
+
"blocking-factor": "count",
|
|
586
|
+
directory: "path",
|
|
587
|
+
exclude: "name-pattern",
|
|
588
|
+
"exclude-from": "path",
|
|
589
|
+
file: "path",
|
|
590
|
+
"files-from": "path",
|
|
591
|
+
"strip-components": "count",
|
|
592
|
+
},
|
|
593
|
+
longOptionalValue: {},
|
|
594
|
+
longPlain: [
|
|
595
|
+
"absolute-names", "append", "create", "dereference", "extract", "get", "help", "interactive",
|
|
596
|
+
"keep-old-files", "list", "preserve-permissions", "sparse", "to-stdout", "touch", "update",
|
|
597
|
+
"verbose", "verify", "version",
|
|
598
|
+
],
|
|
599
|
+
},
|
|
600
|
+
curl: {
|
|
601
|
+
shortValue: {
|
|
602
|
+
A: "label", b: "indirect", C: "count", c: "path", D: "path", d: "indirect", E: "path", e: "label",
|
|
603
|
+
F: "form", H: "header", K: "path", m: "count", o: "path", P: "label", Q: "label", r: "count",
|
|
604
|
+
T: "path", t: "label", U: "label", u: "label", w: "indirect", X: "label", x: "label", Y: "count",
|
|
605
|
+
y: "count", z: "path",
|
|
606
|
+
},
|
|
607
|
+
shortPlain: "#0123456aBfgGhiIjJklLMnNOpqRsSvVZ",
|
|
608
|
+
longValue: {
|
|
609
|
+
cacert: "path",
|
|
610
|
+
capath: "path",
|
|
611
|
+
cert: "path",
|
|
612
|
+
config: "path",
|
|
613
|
+
"connect-timeout": "count",
|
|
614
|
+
cookie: "indirect",
|
|
615
|
+
"cookie-jar": "path",
|
|
616
|
+
data: "indirect",
|
|
617
|
+
"data-ascii": "indirect",
|
|
618
|
+
"data-binary": "indirect",
|
|
619
|
+
"data-raw": "label",
|
|
620
|
+
"data-urlencode": "form",
|
|
621
|
+
"dump-header": "path",
|
|
622
|
+
form: "form",
|
|
623
|
+
"form-string": "label",
|
|
624
|
+
header: "header",
|
|
625
|
+
key: "path",
|
|
626
|
+
"max-time": "count",
|
|
627
|
+
"netrc-file": "path",
|
|
628
|
+
output: "path",
|
|
629
|
+
proxy: "label",
|
|
630
|
+
range: "count",
|
|
631
|
+
referer: "label",
|
|
632
|
+
request: "label",
|
|
633
|
+
resolve: "label",
|
|
634
|
+
trace: "path",
|
|
635
|
+
"time-cond": "path",
|
|
636
|
+
"trace-ascii": "path",
|
|
637
|
+
"upload-file": "path",
|
|
638
|
+
url: "url",
|
|
639
|
+
user: "label",
|
|
640
|
+
"user-agent": "label",
|
|
641
|
+
"write-out": "indirect",
|
|
642
|
+
},
|
|
643
|
+
longOptionalValue: {},
|
|
644
|
+
longPlain: [
|
|
645
|
+
"append", "compressed", "disable", "fail", "get", "globoff", "head", "help", "include", "insecure",
|
|
646
|
+
"junk-session-cookies", "list-only", "location", "manual", "netrc", "next", "no-buffer", "parallel",
|
|
647
|
+
"proxytunnel", "remote-header-name", "remote-name", "remote-time", "show-error", "silent",
|
|
648
|
+
"use-ascii", "verbose", "version",
|
|
649
|
+
],
|
|
650
|
+
},
|
|
651
|
+
};
|
|
652
|
+
function readVerbOptionSlot(name, tok) {
|
|
653
|
+
const row = VERB_OPTION_SLOTS[name];
|
|
654
|
+
if (row === undefined)
|
|
655
|
+
return undefined;
|
|
656
|
+
if (!tok.startsWith("-") || tok === "-" || tok === "--")
|
|
657
|
+
return { form: "unexplained" };
|
|
658
|
+
if (tok.startsWith("--")) {
|
|
659
|
+
const long = longOptionNameOf(tok);
|
|
660
|
+
if (long === undefined)
|
|
661
|
+
return { form: "unexplained" };
|
|
662
|
+
const eq = tok.indexOf("=");
|
|
663
|
+
const attached = eq >= 0 ? tok.slice(eq + 1) : undefined;
|
|
664
|
+
const withValue = (kind) => attached !== undefined ? { form: "attached", value: attached, kind } : { form: "separated", kind };
|
|
665
|
+
const exact = row.longValue[long];
|
|
666
|
+
if (exact !== undefined)
|
|
667
|
+
return withValue(exact);
|
|
668
|
+
const exactOptional = row.longOptionalValue[long];
|
|
669
|
+
if (exactOptional !== undefined)
|
|
670
|
+
return attached !== undefined ? { form: "attached", value: attached, kind: exactOptional } : { form: "no-value" };
|
|
671
|
+
if (row.longPlain.includes(long))
|
|
672
|
+
return attached === undefined ? { form: "no-value" } : { form: "unexplained" };
|
|
673
|
+
const valueNames = [
|
|
674
|
+
...Object.keys(row.longValue),
|
|
675
|
+
...(attached !== undefined ? Object.keys(row.longOptionalValue) : []),
|
|
676
|
+
].filter((full) => isLongOptionAbbrevOf(long, full));
|
|
677
|
+
const plainNames = [
|
|
678
|
+
...row.longPlain,
|
|
679
|
+
...(attached === undefined ? Object.keys(row.longOptionalValue) : []),
|
|
680
|
+
].filter((full) => isLongOptionAbbrevOf(long, full));
|
|
681
|
+
if (valueNames.length === 0)
|
|
682
|
+
return plainNames.length > 0 && attached === undefined ? { form: "no-value" } : { form: "unexplained" };
|
|
683
|
+
const kinds = new Set(valueNames.map((full) => (row.longValue[full] ?? row.longOptionalValue[full])));
|
|
684
|
+
if (attached !== undefined)
|
|
685
|
+
return { form: "attached", value: attached, kind: widestValueKind(kinds) };
|
|
686
|
+
if (plainNames.length > 0 || kinds.size !== 1)
|
|
687
|
+
return { form: "unexplained" };
|
|
688
|
+
return withValue([...kinds][0]);
|
|
689
|
+
}
|
|
690
|
+
for (let i = 1; i < tok.length; i++) {
|
|
691
|
+
const ch = tok[i];
|
|
692
|
+
const kind = row.shortValue[ch];
|
|
693
|
+
if (kind !== undefined) {
|
|
694
|
+
const rest = tok.slice(i + 1);
|
|
695
|
+
return rest !== "" ? { form: "attached", value: rest, kind } : { form: "separated", kind };
|
|
696
|
+
}
|
|
697
|
+
if (!row.shortPlain.includes(ch))
|
|
698
|
+
return { form: "unexplained" };
|
|
699
|
+
}
|
|
700
|
+
return { form: "no-value" };
|
|
701
|
+
}
|
|
702
|
+
function localFileUrlPath(value) {
|
|
703
|
+
const m = /^file:(?:\/\/[^/?#]*)?(\/[^?#]*)/i.exec(value.trim());
|
|
704
|
+
if (m === null)
|
|
705
|
+
return undefined;
|
|
706
|
+
const raw = m[1];
|
|
707
|
+
try {
|
|
708
|
+
return decodeURIComponent(raw);
|
|
709
|
+
}
|
|
710
|
+
catch {
|
|
711
|
+
return raw;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
function formSpecFileNames(value) {
|
|
715
|
+
const out = [];
|
|
716
|
+
const after = (s) => {
|
|
717
|
+
const at = s.search(/[@<]/);
|
|
718
|
+
if (at !== -1 && at < s.length - 1)
|
|
719
|
+
out.push(s.slice(at + 1));
|
|
720
|
+
};
|
|
721
|
+
after(value);
|
|
722
|
+
for (const part of value.split(/[;,]/))
|
|
723
|
+
after(part);
|
|
724
|
+
return [...new Set(out)];
|
|
725
|
+
}
|
|
726
|
+
function slotValueCandidates(value, kind) {
|
|
727
|
+
if (!valueNamesAFile(kind))
|
|
728
|
+
return [];
|
|
729
|
+
if (kind === "url") {
|
|
730
|
+
const local = localFileUrlPath(value);
|
|
731
|
+
return local !== undefined ? [local] : [];
|
|
732
|
+
}
|
|
733
|
+
if (kind === "form")
|
|
734
|
+
return formSpecFileNames(value).map(literalTildeSpelling);
|
|
735
|
+
const named = value.startsWith("@") && value.length > 1 ? literalTildeSpelling(value.slice(1)) : undefined;
|
|
736
|
+
if (kind === "header")
|
|
737
|
+
return named !== undefined ? [value, named] : [];
|
|
738
|
+
const out = [value];
|
|
739
|
+
if (kind === "indirect" && named !== undefined)
|
|
740
|
+
out.push(named);
|
|
741
|
+
return out;
|
|
742
|
+
}
|
|
475
743
|
const SEPARATED_VALUE_OPTIONS = {
|
|
476
744
|
head: { short: "cn", long: ["bytes", "lines"] },
|
|
477
745
|
tail: { short: "cns", long: ["bytes", "lines", "sleep-interval", "pid", "max-unchanged-stats"] },
|
|
@@ -1248,17 +1516,6 @@ function isGrepFileStdinLongOption(tok) {
|
|
|
1248
1516
|
return name !== undefined && isLongOptionAbbrevOf(name, "file");
|
|
1249
1517
|
}
|
|
1250
1518
|
const CLUSTER_OPTION_CHAR = /[A-Za-z0-9]/;
|
|
1251
|
-
function grepClusterValueOwner(tok) {
|
|
1252
|
-
if (!tok.startsWith("-") || tok.startsWith("--") || !CLUSTER_OPTION_CHAR.test(tok[1] ?? ""))
|
|
1253
|
-
return undefined;
|
|
1254
|
-
for (const ch of tok.slice(1)) {
|
|
1255
|
-
if (ch === "e" || ch === "f")
|
|
1256
|
-
return ch;
|
|
1257
|
-
if (!CLUSTER_OPTION_CHAR.test(ch))
|
|
1258
|
-
return undefined;
|
|
1259
|
-
}
|
|
1260
|
-
return undefined;
|
|
1261
|
-
}
|
|
1262
1519
|
function attachedOptionPayloads(tok) {
|
|
1263
1520
|
const literal = literalTildeSpelling;
|
|
1264
1521
|
const out = [];
|
|
@@ -1282,6 +1539,7 @@ function attachedOptionPayloads(tok) {
|
|
|
1282
1539
|
}
|
|
1283
1540
|
function collectSegmentBoundaryFindings(tokens, boundary) {
|
|
1284
1541
|
const name = tokens.folded[0];
|
|
1542
|
+
const slotVerb = tokens.slotVerb ?? name;
|
|
1285
1543
|
if (NO_PATH_OPERAND_COMMANDS.has(name))
|
|
1286
1544
|
return [];
|
|
1287
1545
|
const args = tokens.folded.slice(1);
|
|
@@ -1328,6 +1586,8 @@ function collectSegmentBoundaryFindings(tokens, boundary) {
|
|
|
1328
1586
|
const eoo = args.indexOf("--");
|
|
1329
1587
|
const patternSuppliedByFlag = name === "grep" && (eoo === -1 ? args : args.slice(0, eoo)).some(isGrepPatternFlagToken);
|
|
1330
1588
|
let sawOperand = false;
|
|
1589
|
+
const argvOperandsStartAt = tokens.slotVerb !== undefined ? 1 : 0;
|
|
1590
|
+
let sawArgvOperand = false;
|
|
1331
1591
|
let endOfOptions = false;
|
|
1332
1592
|
for (let k = 0; k < args.length; k++) {
|
|
1333
1593
|
const t = args[k];
|
|
@@ -1338,15 +1598,35 @@ function collectSegmentBoundaryFindings(tokens, boundary) {
|
|
|
1338
1598
|
endOfOptions = true;
|
|
1339
1599
|
continue;
|
|
1340
1600
|
}
|
|
1341
|
-
if (name === "cut" && (t === "-d" || t === "--delimiter" || t === "--output-delimiter")) {
|
|
1342
|
-
k++;
|
|
1343
|
-
continue;
|
|
1344
|
-
}
|
|
1345
|
-
if (name === "cut" && (/^-d./.test(t) || isCutDelimiterPayloadLongOption(t)))
|
|
1346
|
-
continue;
|
|
1347
|
-
if (name === "grep" && (grepClusterValueOwner(t) === "e" || isGrepPatternPayloadLongOption(t)))
|
|
1348
|
-
continue;
|
|
1349
1601
|
if (t.startsWith("-") && t !== "-") {
|
|
1602
|
+
const slot = readVerbOptionSlot(slotVerb, t);
|
|
1603
|
+
if (sawArgvOperand) {
|
|
1604
|
+
judgeOperand(t, argGlobs(k));
|
|
1605
|
+
if (slot !== undefined && slot.form === "separated") {
|
|
1606
|
+
const ahead = args[k + 1];
|
|
1607
|
+
if (ahead !== undefined && !expandingArgs.has(k + 1)) {
|
|
1608
|
+
for (const c of slotValueCandidates(ahead, slot.kind))
|
|
1609
|
+
judgeOperand(c, argGlobs(k + 1));
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
if (slot !== undefined && slot.form !== "unexplained" && !(slot.form === "separated" && sawArgvOperand)) {
|
|
1614
|
+
if (slot.form === "attached") {
|
|
1615
|
+
for (const c of slotValueCandidates(literalTildeSpelling(slot.value), slot.kind))
|
|
1616
|
+
judgeOperand(c, argGlobs(k));
|
|
1617
|
+
}
|
|
1618
|
+
else if (slot.form === "separated") {
|
|
1619
|
+
const value = args[++k];
|
|
1620
|
+
if (value !== undefined && !expandingArgs.has(k)) {
|
|
1621
|
+
const named = slotValueCandidates(value, slot.kind);
|
|
1622
|
+
for (const c of named)
|
|
1623
|
+
judgeOperand(c, argGlobs(k));
|
|
1624
|
+
if (named.length > 0)
|
|
1625
|
+
positionalOperands.push(value);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
continue;
|
|
1629
|
+
}
|
|
1350
1630
|
for (const payload of attachedOptionPayloads(t))
|
|
1351
1631
|
judgeOperand(payload, argGlobs(k));
|
|
1352
1632
|
continue;
|
|
@@ -1354,6 +1634,8 @@ function collectSegmentBoundaryFindings(tokens, boundary) {
|
|
|
1354
1634
|
}
|
|
1355
1635
|
const isGrepPatternSlot = name === "grep" && !patternSuppliedByFlag && !sawOperand;
|
|
1356
1636
|
sawOperand = true;
|
|
1637
|
+
if (k >= argvOperandsStartAt)
|
|
1638
|
+
sawArgvOperand = true;
|
|
1357
1639
|
if (t === "-") {
|
|
1358
1640
|
if (isGrepPatternSlot)
|
|
1359
1641
|
continue;
|
|
@@ -1584,7 +1866,7 @@ export function classifyCompoundReadonlyDetailed(command, allow, boundary, opts)
|
|
|
1584
1866
|
const unlisted = tokenizeSegment(segments[si]);
|
|
1585
1867
|
if (unlisted.folded.length === 0)
|
|
1586
1868
|
continue;
|
|
1587
|
-
foldedSegments.push({ folded: [LAUNCHER_SCAN_HEAD, ...unlisted.folded], raw: [LAUNCHER_SCAN_HEAD, ...unlisted.raw] });
|
|
1869
|
+
foldedSegments.push({ folded: [LAUNCHER_SCAN_HEAD, ...unlisted.folded], raw: [LAUNCHER_SCAN_HEAD, ...unlisted.raw], slotVerb: programBasename(unlisted.folded[0]) });
|
|
1588
1870
|
pushReach();
|
|
1589
1871
|
continue;
|
|
1590
1872
|
}
|
|
@@ -1734,7 +2016,7 @@ function evaluateReadBoundary(foldedSegments, boundary, mintGrantCandidate, reac
|
|
|
1734
2016
|
if (si > 0 && reach?.[si]?.andJoined !== true)
|
|
1735
2017
|
andRunStart = reach?.[si]?.orBroken === true ? si + 1 : si;
|
|
1736
2018
|
const reachable = candidates.filter((c) => c.skippedCd < andRunStart);
|
|
1737
|
-
const row = findingsRowFor(JSON.stringify([toks.folded, toks.raw]));
|
|
2019
|
+
const row = findingsRowFor(JSON.stringify([toks.folded, toks.raw, toks.slotVerb]));
|
|
1738
2020
|
for (const { base: currentBase } of reachable) {
|
|
1739
2021
|
for (const finding of findingsFor(row, toks, currentBase)) {
|
|
1740
2022
|
if (finding.kind === "unresolvable") {
|
|
@@ -1929,7 +2211,7 @@ export function classifyOutOfRootReadGate(command, allow, boundary) {
|
|
|
1929
2211
|
if (UNMODELLED_BASE_MOVERS.has(name))
|
|
1930
2212
|
baseMoved = true;
|
|
1931
2213
|
if (!allow.has(name) && name !== "cd") {
|
|
1932
|
-
pushReader({ folded: [LAUNCHER_SCAN_HEAD, ...toks.folded.slice(i)], raw: [LAUNCHER_SCAN_HEAD, ...toks.raw.slice(i)] });
|
|
2214
|
+
pushReader({ folded: [LAUNCHER_SCAN_HEAD, ...toks.folded.slice(i)], raw: [LAUNCHER_SCAN_HEAD, ...toks.raw.slice(i)], slotVerb: name });
|
|
1933
2215
|
continue;
|
|
1934
2216
|
}
|
|
1935
2217
|
pushReader(i === 0 && name === written ? toks : { folded: [name, ...toks.folded.slice(i + 1)], raw: [toks.raw[i] ?? name, ...toks.raw.slice(i + 1)] });
|
|
@@ -100,7 +100,7 @@ export declare function bashReversibilityProbe(allow?: readonly string[], bounda
|
|
|
100
100
|
* add a mandate to an ask, never originate one). The poll-loop face's structured verdict
|
|
101
101
|
* ({@link classifyBoundedReadonlyPollLoopDetailed}) is read the same three ways as the compound face's.
|
|
102
102
|
*
|
|
103
|
-
* The reader set is the engine's classify set ({@link
|
|
103
|
+
* The reader set is the engine's classify set ({@link bashClassifyDefaultAllow}) — here it is NOT an
|
|
104
104
|
* auto-allow list but the set of programs whose operands the faces read; a wider set means more reads are
|
|
105
105
|
* judged, never that more runs are vouched.
|
|
106
106
|
*
|
package/dist/tools/fs/fs-bash.js
CHANGED
|
@@ -9,11 +9,11 @@ import { hasBackgroundShell } from "../../core/background-shell.js";
|
|
|
9
9
|
import { delimitUntrusted } from "../../core/untrusted-text.js";
|
|
10
10
|
import { MCP_IMAGE_MAX_BASE64 } from "../../core/mcp.js";
|
|
11
11
|
import { imageMagicMatches, normalizeAbsPathLexically, withinAnyRoot } from "./safety.js";
|
|
12
|
-
import { boundaryIsTheSandbox, hasDestroy, isIsolated } from "../../core/remote-env.js";
|
|
12
|
+
import { boundaryIsTheSandbox, canonicalPathIsAuthoritative, hasDestroy, isIsolated } from "../../core/remote-env.js";
|
|
13
13
|
import { ghRateLimitHint } from "./gh-rate-limit.js";
|
|
14
|
-
import { resolveBashTimeoutCaps, bashTimeoutCapsSec, bashTimeoutArgRefusal, bashTimeoutParamDescription, envErrorDetail, bashMaxOutputChars, clipShellOutput, writeShellOverflowFile, createShellOverflowSpoolFence, shellRecoveryHint, CWD_SENTINEL, BASH_READONLY_CONFINEMENT_NOTE, } from "./fs-shared.js";
|
|
14
|
+
import { resolveBashTimeoutCaps, bashTimeoutCapsSec, bashTimeoutArgRefusal, bashTimeoutParamDescription, envErrorDetail, bashMaxOutputChars, clipShellOutput, writeShellOverflowFile, createShellOverflowSpoolFence, shellRecoveryHint, CWD_SENTINEL, stripCwdSentinel, BASH_READONLY_CONFINEMENT_NOTE, } from "./fs-shared.js";
|
|
15
15
|
import { PROBE_CAUSE_PATH_MAX, inlineUntrusted } from "../../core/untrusted-text.js";
|
|
16
|
-
import {
|
|
16
|
+
import { bashClassifyDefaultAllow, BASH_READONLY_DEFAULT_ALLOW, coarseReadonlyCheck, classifyBoundedReadonlyPollLoopDetailed, classifyCompoundReadonlyDetailed, classifyOutOfRootReadGate, refusedCommandMayRead, classifySimpleCommandReadBoundary, NOT_AUTO_ALLOWED, } from "./bash-readonly-classifier.js";
|
|
17
17
|
import { toolFace } from "../../core/tool-catalog-entries.js";
|
|
18
18
|
const RECURSIVE_CAUSE_MAX_PATHS = 3;
|
|
19
19
|
const RECURSIVE_READ_CAUSE_CODE = "shell.recursive_read_unbounded";
|
|
@@ -25,7 +25,7 @@ function operandFamily(paths) {
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
export function bashReversibilityProbe(allow, boundary) {
|
|
28
|
-
const allowSet = new Set(allow ??
|
|
28
|
+
const allowSet = new Set(allow ?? bashClassifyDefaultAllow());
|
|
29
29
|
return (args) => {
|
|
30
30
|
const command = shellCommandOf(args);
|
|
31
31
|
if (command === undefined)
|
|
@@ -109,7 +109,7 @@ function recursiveReadCause(detailed) {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
export function bashReadBoundaryProbe(boundary) {
|
|
112
|
-
const allowSet = new Set(
|
|
112
|
+
const allowSet = new Set(bashClassifyDefaultAllow());
|
|
113
113
|
return (args) => {
|
|
114
114
|
const command = shellCommandOf(args);
|
|
115
115
|
if (command === undefined)
|
|
@@ -402,23 +402,6 @@ function createEpilogueFilter(marker) {
|
|
|
402
402
|
return out + buf;
|
|
403
403
|
};
|
|
404
404
|
}
|
|
405
|
-
function readCwdEpilogue(stderr, marker) {
|
|
406
|
-
let out = "";
|
|
407
|
-
let rest = stderr;
|
|
408
|
-
let cwd;
|
|
409
|
-
for (;;) {
|
|
410
|
-
const open = rest.indexOf(marker);
|
|
411
|
-
if (open === -1)
|
|
412
|
-
break;
|
|
413
|
-
const close = rest.indexOf(marker, open + marker.length);
|
|
414
|
-
if (close === -1)
|
|
415
|
-
break;
|
|
416
|
-
out += rest.slice(0, open);
|
|
417
|
-
cwd = rest.slice(open + marker.length, close);
|
|
418
|
-
rest = rest.slice(close + marker.length);
|
|
419
|
-
}
|
|
420
|
-
return { stderr: out + rest, cwd };
|
|
421
|
-
}
|
|
422
405
|
function describeSafely(sink, body) {
|
|
423
406
|
if (sink === undefined)
|
|
424
407
|
return;
|
|
@@ -582,7 +565,7 @@ async function runShell(env, cwd, toolName, command, timeoutSec, caps, signal, c
|
|
|
582
565
|
let { stderr } = res.value;
|
|
583
566
|
const { stdout, exitCode } = res.value;
|
|
584
567
|
if (cwdRef) {
|
|
585
|
-
const epilogue =
|
|
568
|
+
const epilogue = stripCwdSentinel(stderr, cwdMarker);
|
|
586
569
|
stderr = epilogue.stderr;
|
|
587
570
|
if (epilogue.cwd !== undefined) {
|
|
588
571
|
const captured = epilogue.cwd.trim();
|
|
@@ -736,7 +719,7 @@ export function createBashTool(env, rootCanonical, coAuthor = false, cwdRef = {
|
|
|
736
719
|
const bgRetained = hasBackgroundShell(env) && env.backgroundCapabilities.retainBackgroundProcesses === true;
|
|
737
720
|
const bgSessionScoped = taskOpts.sessionId !== undefined && taskOpts.taskRegistry !== undefined;
|
|
738
721
|
const bgEnvIsolatedOwned = hasDestroy(env) && isIsolated(env);
|
|
739
|
-
const recheckReaders = new Set(
|
|
722
|
+
const recheckReaders = new Set(bashClassifyDefaultAllow());
|
|
740
723
|
let canonicalForRoots;
|
|
741
724
|
const canonicalBoundaryFor = (roots) => {
|
|
742
725
|
const key = roots.join("\u0000");
|
|
@@ -1070,6 +1053,7 @@ function pathSegmentsFrom(p, from) {
|
|
|
1070
1053
|
}
|
|
1071
1054
|
function createCanonicalReadBoundary(env, readRoots) {
|
|
1072
1055
|
const lexicalOnly = boundaryIsTheSandbox(env);
|
|
1056
|
+
const resolverIsAuthoritative = canonicalPathIsAuthoritative(env);
|
|
1073
1057
|
let rootsOnce;
|
|
1074
1058
|
const canonicalRoots = async (signal) => {
|
|
1075
1059
|
rootsOnce ??= (async () => {
|
|
@@ -1229,8 +1213,11 @@ function createCanonicalReadBoundary(env, readRoots) {
|
|
|
1229
1213
|
let unresolvable;
|
|
1230
1214
|
const judge = async (p) => {
|
|
1231
1215
|
const real = await resolve(p, signal);
|
|
1232
|
-
if (real === undefined)
|
|
1216
|
+
if (real === undefined) {
|
|
1217
|
+
if (resolverIsAuthoritative)
|
|
1218
|
+
unresolvable ??= `"${p}" cannot be resolved to verify where it reads`;
|
|
1233
1219
|
return;
|
|
1220
|
+
}
|
|
1234
1221
|
if (!real.exact && real.missing !== true) {
|
|
1235
1222
|
unresolvable ??= `"${p}" cannot be resolved to verify where it reads`;
|
|
1236
1223
|
return;
|
|
@@ -361,6 +361,28 @@ export declare function shellRecoveryHint(path: string, readOnly: boolean | unde
|
|
|
361
361
|
* (NOT NotebookEdit — CC ships it without the trailer). */
|
|
362
362
|
export declare const FILE_STATE_TRAILER = " (file state is current in your context \u2014 no need to Read it back)";
|
|
363
363
|
export declare const CWD_SENTINEL = "__cc_cwd_9f2c1b__";
|
|
364
|
+
/**
|
|
365
|
+
* Take the engine's own cwd epilogue out of a finished stderr, and report the working directory the
|
|
366
|
+
* command left behind (the payload of the LAST span).
|
|
367
|
+
*
|
|
368
|
+
* EVERY span, and the LAST one — not the first, and not just one. A command that turns on shell tracing
|
|
369
|
+
* produces more than one (the shell echoes the epilogue's own source, marker and all, before running
|
|
370
|
+
* it), and under a one-pair rule the FIRST pair was that echo, whose payload is the unexpanded
|
|
371
|
+
* `' "$(pwd)" '`; a `cd` that plainly worked was then dropped while the real record stayed in the stderr
|
|
372
|
+
* a person reads. An opener with no close is NOT ours to eat — the command's own text is left exactly
|
|
373
|
+
* as it arrived.
|
|
374
|
+
*
|
|
375
|
+
* TWO CALLERS, ONE RULE, which is why the marker is optional. The foreground result path KNOWS the
|
|
376
|
+
* marker it minted and passes it (exact, unambiguous). A backgrounded command's spool is assembled by a
|
|
377
|
+
* different lane entirely — the shell row outlives the run that launched it and never had the marker —
|
|
378
|
+
* so it passes none and the marker is recovered per span from the sentinel plus its hex suffix. Before
|
|
379
|
+
* this was shared, only the foreground path stripped, and the completion notification handed a person
|
|
380
|
+
* the raw internal marker with the directory inside it.
|
|
381
|
+
*/
|
|
382
|
+
export declare function stripCwdSentinel(stderr: string, marker?: string): {
|
|
383
|
+
stderr: string;
|
|
384
|
+
cwd: string | undefined;
|
|
385
|
+
};
|
|
364
386
|
/** Convert a model-supplied millisecond timeout to our internal seconds, clamped. Exported for the
|
|
365
387
|
* cc-parity unit (model sees ms, internal stays seconds — no ×1000 error).
|
|
366
388
|
* ⚠️ This returns the EFFECTIVE budget, not the request — capping at a call site destroys the
|
|
@@ -247,6 +247,36 @@ export function shellRecoveryHint(path, readOnly) {
|
|
|
247
247
|
}
|
|
248
248
|
export const FILE_STATE_TRAILER = " (file state is current in your context — no need to Read it back)";
|
|
249
249
|
export const CWD_SENTINEL = "__cc_cwd_9f2c1b__";
|
|
250
|
+
const CWD_SENTINEL_SUFFIX_CHARS = 16;
|
|
251
|
+
function cwdMarkerAt(text, open) {
|
|
252
|
+
const after = open + CWD_SENTINEL.length;
|
|
253
|
+
const suffix = /^[0-9a-f]{16}/.exec(text.slice(after, after + CWD_SENTINEL_SUFFIX_CHARS));
|
|
254
|
+
return suffix === null ? undefined : CWD_SENTINEL + suffix[0];
|
|
255
|
+
}
|
|
256
|
+
export function stripCwdSentinel(stderr, marker) {
|
|
257
|
+
let out = "";
|
|
258
|
+
let rest = stderr;
|
|
259
|
+
let cwd;
|
|
260
|
+
let from = 0;
|
|
261
|
+
for (;;) {
|
|
262
|
+
const open = rest.indexOf(marker ?? CWD_SENTINEL, from);
|
|
263
|
+
if (open === -1)
|
|
264
|
+
break;
|
|
265
|
+
const span = marker ?? cwdMarkerAt(rest, open);
|
|
266
|
+
if (span === undefined) {
|
|
267
|
+
from = open + CWD_SENTINEL.length;
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const close = rest.indexOf(span, open + span.length);
|
|
271
|
+
if (close === -1)
|
|
272
|
+
break;
|
|
273
|
+
out += rest.slice(0, open);
|
|
274
|
+
cwd = rest.slice(open + span.length, close);
|
|
275
|
+
rest = rest.slice(close + span.length);
|
|
276
|
+
from = 0;
|
|
277
|
+
}
|
|
278
|
+
return { stderr: out + rest, cwd };
|
|
279
|
+
}
|
|
250
280
|
export function msTimeoutToSec(timeoutMs, caps = resolveBashTimeoutCaps()) {
|
|
251
281
|
const { defaultSec, maxSec } = bashTimeoutCapsSec(caps);
|
|
252
282
|
if (timeoutMs === undefined || !Number.isFinite(timeoutMs))
|
package/dist/tools/fs/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export * from "./bash-readonly-classifier.js";
|
|
|
12
12
|
export * from "./fs-bash.js";
|
|
13
13
|
export * from "./read-deny.js";
|
|
14
14
|
import { type BashReadonlyRootBoundary } from "./bash-readonly-classifier.js";
|
|
15
|
-
export {
|
|
15
|
+
export { BASH_CLASSIFY_EXTRA_ALLOW, bashClassifyDefaultAllow } from "./bash-readonly-classifier.js";
|
|
16
16
|
import { type ReadDenyEntry } from "./read-deny.js";
|
|
17
17
|
import { type ContainmentFace } from "./containment-face.js";
|
|
18
18
|
export * from "./containment-face.js";
|
package/dist/tools/fs/index.js
CHANGED
|
@@ -12,7 +12,7 @@ export * from "./bash-readonly-classifier.js";
|
|
|
12
12
|
export * from "./fs-bash.js";
|
|
13
13
|
export * from "./read-deny.js";
|
|
14
14
|
import { BASH_READONLY_DEFAULT_ALLOW, } from "./bash-readonly-classifier.js";
|
|
15
|
-
export {
|
|
15
|
+
export { BASH_CLASSIFY_EXTRA_ALLOW, bashClassifyDefaultAllow } from "./bash-readonly-classifier.js";
|
|
16
16
|
import { compileReadDeny } from "./read-deny.js";
|
|
17
17
|
import { deploymentFaceClampNotice, resolveContainmentFace } from "./containment-face.js";
|
|
18
18
|
export * from "./containment-face.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/core",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.20.0",
|
|
4
4
|
"description": "Stateless, task-oriented AI agent core",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
"gate:tool-names": "node scripts/verify-tool-name-tables.mjs",
|
|
85
85
|
"gate:tool-docs": "node scripts/gen-tool-spec-fields.mjs --check",
|
|
86
86
|
"gate:backlog-ledger": "node scripts/verify-backlog-ledger.mjs",
|
|
87
|
+
"gate:child-clamp-seats": "node scripts/verify-child-clamp-seats.mjs",
|
|
87
88
|
"gate:docs-tool-names": "node scripts/verify-docs-tool-names.mjs",
|
|
88
89
|
"gate:comment-ratio": "vitest run test/comment-ratio-ratchet.test.ts",
|
|
89
90
|
"gate:negative-controls": "vitest run test/gate-negative-controls.test.ts",
|