@fro.bot/systematic 3.14.5 → 3.15.1
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/dist/claude-code-validator.d.ts +8 -0
- package/dist/cli.js +287 -230
- package/dist/index-7cyxcwf5.js +8486 -0
- package/dist/index.js +127 -124
- package/dist/lib/review-artifact-path.d.ts +20 -0
- package/dist/pi.js +23 -7
- package/package.json +6 -6
- package/skills/ce-review/references/review-summary-schema.json +1 -1
- package/skills/ce-review/references/synthesis-artifact-contract.md +21 -9
- package/dist/index-0stf3ag0.js +0 -17100
package/dist/index.js
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
+
parseFrontmatter,
|
|
4
|
+
string,
|
|
5
|
+
array,
|
|
6
|
+
object,
|
|
7
|
+
record,
|
|
8
|
+
_enum,
|
|
3
9
|
AgentOverlaySchema,
|
|
4
10
|
CategoryOverlaySchema,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
extractCommandFrontmatter,
|
|
11
|
+
loadConfig,
|
|
12
|
+
loadConfigWithSources,
|
|
13
|
+
isRecord,
|
|
14
|
+
isDiscoverableMarkdown,
|
|
10
15
|
findAgentsInDir,
|
|
16
|
+
extractAgentFrontmatter,
|
|
11
17
|
findCommandsInDir,
|
|
18
|
+
extractCommandFrontmatter,
|
|
12
19
|
findSkillsInDir,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
loadConfig,
|
|
16
|
-
loadConfigWithSources,
|
|
17
|
-
parseFrontmatter
|
|
18
|
-
} from "./index-0stf3ag0.js";
|
|
20
|
+
discoverSkills
|
|
21
|
+
} from "./index-7cyxcwf5.js";
|
|
19
22
|
|
|
20
23
|
// src/index.ts
|
|
21
24
|
import { createHash as createHash4 } from "crypto";
|
|
@@ -731,14 +734,14 @@ function registerSkillsPaths(config, skillsDir) {
|
|
|
731
734
|
};
|
|
732
735
|
}
|
|
733
736
|
function removeSystematicSkillPaths(paths) {
|
|
734
|
-
return paths.filter((
|
|
737
|
+
return paths.filter((path) => !isSystematicSkillPath(path));
|
|
735
738
|
}
|
|
736
|
-
function isSystematicSkillPath(
|
|
737
|
-
const normalizedPath = normalizePath(
|
|
739
|
+
function isSystematicSkillPath(path) {
|
|
740
|
+
const normalizedPath = normalizePath(path);
|
|
738
741
|
return normalizedPath.endsWith("/.config/opencode/systematic/skills") || normalizedPath.endsWith("/.cache/opencode/systematic/skills") || normalizedPath.endsWith("/.local/share/opencode/systematic/skills") || normalizedPath.endsWith("/.opencode/systematic/skills") || /(?:^|\/)\.cache\/opencode\/packages\/@fro\.bot\/systematic@[^/]+\/node_modules\/@fro\.bot\/systematic\/skills(?:$|\/)/u.test(normalizedPath);
|
|
739
742
|
}
|
|
740
|
-
function normalizePath(
|
|
741
|
-
return
|
|
743
|
+
function normalizePath(path) {
|
|
744
|
+
return path.replaceAll("\\", "/").replace(/\/+$/u, "");
|
|
742
745
|
}
|
|
743
746
|
|
|
744
747
|
// src/lib/opencode-operation-observer.ts
|
|
@@ -1655,10 +1658,10 @@ function createQuestionAttestation(options = {}) {
|
|
|
1655
1658
|
const disabledSessions = new Set;
|
|
1656
1659
|
let challengeCounter = 0;
|
|
1657
1660
|
function expireChallenges(now) {
|
|
1658
|
-
for (const [challengeId,
|
|
1659
|
-
if ((
|
|
1660
|
-
|
|
1661
|
-
const key = bindingKey(
|
|
1661
|
+
for (const [challengeId, challenge] of challenges) {
|
|
1662
|
+
if ((challenge.state === "pending" || challenge.state === "bound") && now - challenge.createdAt > maxChallengeAgeMs) {
|
|
1663
|
+
challenge.state = "expired";
|
|
1664
|
+
const key = bindingKey(challenge, challenge.resourceDigest);
|
|
1662
1665
|
if (activeByBinding.get(key) === challengeId)
|
|
1663
1666
|
activeByBinding.delete(key);
|
|
1664
1667
|
}
|
|
@@ -1675,17 +1678,17 @@ function createQuestionAttestation(options = {}) {
|
|
|
1675
1678
|
function findBindChallenge(input) {
|
|
1676
1679
|
return "challengeId" in input ? findChallengeById(input.challengeId) : findChallengeByScope(input);
|
|
1677
1680
|
}
|
|
1678
|
-
function bindStateRejection(
|
|
1679
|
-
if (
|
|
1681
|
+
function bindStateRejection(challenge, input) {
|
|
1682
|
+
if (challenge.state === "expired")
|
|
1680
1683
|
return "challenge-expired";
|
|
1681
|
-
if (
|
|
1684
|
+
if (challenge.state === "denied" || challenge.state === "consumed") {
|
|
1682
1685
|
return "challenge-consumed";
|
|
1683
1686
|
}
|
|
1684
|
-
if ("sessionId" in input && input.sessionId !== undefined && input.sessionId !==
|
|
1687
|
+
if ("sessionId" in input && input.sessionId !== undefined && input.sessionId !== challenge.sessionId) {
|
|
1685
1688
|
return "call-session-mismatch";
|
|
1686
1689
|
}
|
|
1687
|
-
if (
|
|
1688
|
-
return
|
|
1690
|
+
if (challenge.state === "bound") {
|
|
1691
|
+
return challenge.requestId === input.requestId ? "already-bound" : "substitution";
|
|
1689
1692
|
}
|
|
1690
1693
|
return seenRequestIds.has(input.requestId) ? "replay" : null;
|
|
1691
1694
|
}
|
|
@@ -1693,23 +1696,23 @@ function createQuestionAttestation(options = {}) {
|
|
|
1693
1696
|
const challengeId = challengeByRequest.get(requestId);
|
|
1694
1697
|
return challengeId === undefined ? null : challenges.get(challengeId) ?? null;
|
|
1695
1698
|
}
|
|
1696
|
-
function replyStateRejection(
|
|
1697
|
-
if (
|
|
1699
|
+
function replyStateRejection(challenge, input) {
|
|
1700
|
+
if (challenge.sessionId !== input.sessionId)
|
|
1698
1701
|
return "substitution";
|
|
1699
|
-
if (
|
|
1702
|
+
if (challenge.state === "expired")
|
|
1700
1703
|
return "challenge-expired";
|
|
1701
|
-
if (
|
|
1704
|
+
if (challenge.state !== "bound" || challenge.requestId !== input.requestId) {
|
|
1702
1705
|
return "replay";
|
|
1703
1706
|
}
|
|
1704
1707
|
return null;
|
|
1705
1708
|
}
|
|
1706
|
-
function rejectStateRejection(
|
|
1707
|
-
if (
|
|
1709
|
+
function rejectStateRejection(challenge, input) {
|
|
1710
|
+
if (challenge.sessionId !== input.sessionId)
|
|
1708
1711
|
return "substitution";
|
|
1709
|
-
if (
|
|
1712
|
+
if (challenge.state === "denied" || challenge.state === "consumed") {
|
|
1710
1713
|
return "already-consumed";
|
|
1711
1714
|
}
|
|
1712
|
-
if (
|
|
1715
|
+
if (challenge.state === "expired")
|
|
1713
1716
|
return "challenge-expired";
|
|
1714
1717
|
return null;
|
|
1715
1718
|
}
|
|
@@ -1721,37 +1724,37 @@ function createQuestionAttestation(options = {}) {
|
|
|
1721
1724
|
const parsed = parseBinding(input);
|
|
1722
1725
|
return parsed === null ? null : findChallengeByScope(parsed);
|
|
1723
1726
|
}
|
|
1724
|
-
function projectionBase(
|
|
1727
|
+
function projectionBase(challenge, status) {
|
|
1725
1728
|
return {
|
|
1726
|
-
status
|
|
1727
|
-
challengeId:
|
|
1728
|
-
purpose:
|
|
1729
|
-
sessionId:
|
|
1730
|
-
resourceDigest:
|
|
1731
|
-
transitionKey:
|
|
1732
|
-
...
|
|
1729
|
+
status,
|
|
1730
|
+
challengeId: challenge.challengeId,
|
|
1731
|
+
purpose: challenge.purpose,
|
|
1732
|
+
sessionId: challenge.sessionId,
|
|
1733
|
+
resourceDigest: challenge.resourceDigest,
|
|
1734
|
+
transitionKey: challenge.transition,
|
|
1735
|
+
...challenge.requestId === undefined ? {} : { requestId: challenge.requestId }
|
|
1733
1736
|
};
|
|
1734
1737
|
}
|
|
1735
|
-
function projectChallenge(
|
|
1736
|
-
const attestation =
|
|
1738
|
+
function projectChallenge(challenge) {
|
|
1739
|
+
const attestation = challenge.requestId === undefined ? undefined : attestations.get(challenge.requestId);
|
|
1737
1740
|
if (attestation !== undefined) {
|
|
1738
|
-
const
|
|
1741
|
+
const status = attestation.purpose === "session-disablement" && attestation.consumption === "consumed" ? "disabled" : "attested";
|
|
1739
1742
|
return {
|
|
1740
|
-
...projectionBase(
|
|
1743
|
+
...projectionBase(challenge, status),
|
|
1741
1744
|
consumption: attestation.consumption
|
|
1742
1745
|
};
|
|
1743
1746
|
}
|
|
1744
|
-
if (
|
|
1745
|
-
return projectionBase(
|
|
1747
|
+
if (challenge.state === "pending" || challenge.state === "bound") {
|
|
1748
|
+
return projectionBase(challenge, challenge.state);
|
|
1746
1749
|
}
|
|
1747
|
-
if (
|
|
1748
|
-
return projectionBase(
|
|
1750
|
+
if (challenge.state === "denied") {
|
|
1751
|
+
return projectionBase(challenge, "denied");
|
|
1749
1752
|
}
|
|
1750
1753
|
return { status: "unknown", reasonCode: "challenge-expired" };
|
|
1751
1754
|
}
|
|
1752
|
-
function removeActiveChallenge(
|
|
1753
|
-
const key = bindingKey(
|
|
1754
|
-
if (activeByBinding.get(key) ===
|
|
1755
|
+
function removeActiveChallenge(challenge) {
|
|
1756
|
+
const key = bindingKey(challenge, challenge.resourceDigest);
|
|
1757
|
+
if (activeByBinding.get(key) === challenge.challengeId) {
|
|
1755
1758
|
activeByBinding.delete(key);
|
|
1756
1759
|
}
|
|
1757
1760
|
}
|
|
@@ -1800,20 +1803,20 @@ function createQuestionAttestation(options = {}) {
|
|
|
1800
1803
|
if (parsed === null)
|
|
1801
1804
|
return rejected("invalid-input");
|
|
1802
1805
|
expireChallenges(readNow(clock));
|
|
1803
|
-
const
|
|
1804
|
-
if (
|
|
1806
|
+
const challenge = findBindChallenge(parsed);
|
|
1807
|
+
if (challenge === null)
|
|
1805
1808
|
return rejected("unknown-challenge");
|
|
1806
|
-
const stateRejection = bindStateRejection(
|
|
1809
|
+
const stateRejection = bindStateRejection(challenge, parsed);
|
|
1807
1810
|
if (stateRejection !== null)
|
|
1808
1811
|
return rejected(stateRejection);
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
challengeByRequest.set(parsed.requestId,
|
|
1812
|
+
challenge.state = "bound";
|
|
1813
|
+
challenge.callId = parsed.callId;
|
|
1814
|
+
challenge.requestId = parsed.requestId;
|
|
1815
|
+
challengeByRequest.set(parsed.requestId, challenge.challengeId);
|
|
1813
1816
|
seenRequestIds.add(parsed.requestId);
|
|
1814
1817
|
return {
|
|
1815
1818
|
status: "bound",
|
|
1816
|
-
challengeId:
|
|
1819
|
+
challengeId: challenge.challengeId,
|
|
1817
1820
|
requestId: parsed.requestId
|
|
1818
1821
|
};
|
|
1819
1822
|
} catch {
|
|
@@ -1826,32 +1829,32 @@ function createQuestionAttestation(options = {}) {
|
|
|
1826
1829
|
if (parsed === null)
|
|
1827
1830
|
return rejected("invalid-input");
|
|
1828
1831
|
expireChallenges(readNow(clock));
|
|
1829
|
-
const
|
|
1830
|
-
if (
|
|
1832
|
+
const challenge = requestChallenge(parsed.requestId);
|
|
1833
|
+
if (challenge === null) {
|
|
1831
1834
|
const replay = seenRequestIds.has(parsed.requestId);
|
|
1832
1835
|
seenRequestIds.add(parsed.requestId);
|
|
1833
1836
|
return rejected(replay ? "replay" : "unknown-request");
|
|
1834
1837
|
}
|
|
1835
|
-
const stateRejection = replyStateRejection(
|
|
1838
|
+
const stateRejection = replyStateRejection(challenge, parsed);
|
|
1836
1839
|
if (stateRejection !== null)
|
|
1837
1840
|
return rejected(stateRejection);
|
|
1838
1841
|
if (classifyQuestionAnswer(parsed.answer) !== "affirmative") {
|
|
1839
|
-
|
|
1840
|
-
removeActiveChallenge(
|
|
1842
|
+
challenge.state = "denied";
|
|
1843
|
+
removeActiveChallenge(challenge);
|
|
1841
1844
|
return rejected("non-affirmative");
|
|
1842
1845
|
}
|
|
1843
1846
|
const attestation = {
|
|
1844
|
-
purpose:
|
|
1845
|
-
sessionId:
|
|
1846
|
-
resourceDigest:
|
|
1847
|
-
transitionKey:
|
|
1847
|
+
purpose: challenge.purpose,
|
|
1848
|
+
sessionId: challenge.sessionId,
|
|
1849
|
+
resourceDigest: challenge.resourceDigest,
|
|
1850
|
+
transitionKey: challenge.transition,
|
|
1848
1851
|
requestId: parsed.requestId,
|
|
1849
1852
|
answer: "affirmed",
|
|
1850
1853
|
timestamp: readNow(clock),
|
|
1851
1854
|
consumption: "available"
|
|
1852
1855
|
};
|
|
1853
|
-
|
|
1854
|
-
removeActiveChallenge(
|
|
1856
|
+
challenge.state = "consumed";
|
|
1857
|
+
removeActiveChallenge(challenge);
|
|
1855
1858
|
attestations.set(parsed.requestId, attestation);
|
|
1856
1859
|
return { status: "accepted", attestation: cloneAttestation(attestation) };
|
|
1857
1860
|
} catch {
|
|
@@ -1864,17 +1867,17 @@ function createQuestionAttestation(options = {}) {
|
|
|
1864
1867
|
if (parsed === null)
|
|
1865
1868
|
return rejected("invalid-input");
|
|
1866
1869
|
expireChallenges(readNow(clock));
|
|
1867
|
-
const
|
|
1868
|
-
if (
|
|
1870
|
+
const challenge = requestChallenge(parsed.requestId);
|
|
1871
|
+
if (challenge === null) {
|
|
1869
1872
|
const replay = seenRequestIds.has(parsed.requestId);
|
|
1870
1873
|
seenRequestIds.add(parsed.requestId);
|
|
1871
1874
|
return rejected(replay ? "replay" : "unknown-request");
|
|
1872
1875
|
}
|
|
1873
|
-
const stateRejection = rejectStateRejection(
|
|
1876
|
+
const stateRejection = rejectStateRejection(challenge, parsed);
|
|
1874
1877
|
if (stateRejection !== null)
|
|
1875
1878
|
return rejected(stateRejection);
|
|
1876
|
-
|
|
1877
|
-
removeActiveChallenge(
|
|
1879
|
+
challenge.state = "denied";
|
|
1880
|
+
removeActiveChallenge(challenge);
|
|
1878
1881
|
return { status: "rejected", reasonCode: "rejected" };
|
|
1879
1882
|
} catch {
|
|
1880
1883
|
return rejected("invalid-input");
|
|
@@ -1924,10 +1927,10 @@ function createQuestionAttestation(options = {}) {
|
|
|
1924
1927
|
])) {
|
|
1925
1928
|
return { status: "unknown", reasonCode: "invalid-input" };
|
|
1926
1929
|
}
|
|
1927
|
-
const
|
|
1928
|
-
if (
|
|
1930
|
+
const challenge = statusChallenge(input);
|
|
1931
|
+
if (challenge === null)
|
|
1929
1932
|
return { status: "unknown", reasonCode: "unknown-challenge" };
|
|
1930
|
-
return projectChallenge(
|
|
1933
|
+
return projectChallenge(challenge);
|
|
1931
1934
|
} catch {
|
|
1932
1935
|
return { status: "unknown", reasonCode: "invalid-input" };
|
|
1933
1936
|
}
|
|
@@ -1941,9 +1944,9 @@ function createQuestionAttestation(options = {}) {
|
|
|
1941
1944
|
const sessionId = input.sessionId;
|
|
1942
1945
|
if (disabledSessions.has(sessionId))
|
|
1943
1946
|
return { status: "disabled", sessionId };
|
|
1944
|
-
for (const
|
|
1945
|
-
if (
|
|
1946
|
-
return { status:
|
|
1947
|
+
for (const challenge of challenges.values()) {
|
|
1948
|
+
if (challenge.sessionId === sessionId && challenge.purpose === "session-disablement" && (challenge.state === "pending" || challenge.state === "bound")) {
|
|
1949
|
+
return { status: challenge.state, sessionId };
|
|
1947
1950
|
}
|
|
1948
1951
|
}
|
|
1949
1952
|
return { status: "enabled", sessionId };
|
|
@@ -3862,10 +3865,10 @@ function createReceiptLedger(options = {}) {
|
|
|
3862
3865
|
return { status: "consumed", receipt: cloneEnvelope2(stored.envelope) };
|
|
3863
3866
|
}
|
|
3864
3867
|
function recoverReceipt(input, operationTargetIdentity) {
|
|
3865
|
-
const
|
|
3866
|
-
if (
|
|
3867
|
-
return
|
|
3868
|
-
const marker =
|
|
3868
|
+
const markerResult = getMintMarker(input);
|
|
3869
|
+
if (markerResult.status !== "valid")
|
|
3870
|
+
return markerResult;
|
|
3871
|
+
const marker = markerResult.marker;
|
|
3869
3872
|
if (marker.sessionSalt !== sessionSalt)
|
|
3870
3873
|
return { status: "rejected", category: "salt-mismatch" };
|
|
3871
3874
|
if (marker.envelope.schemaVersion === 1 && operationTargetIdentity !== undefined) {
|
|
@@ -4990,8 +4993,8 @@ var Language = class _Language {
|
|
|
4990
4993
|
if (input instanceof Uint8Array) {
|
|
4991
4994
|
binary2 = input;
|
|
4992
4995
|
} else if (globalThis.process?.versions.node) {
|
|
4993
|
-
const
|
|
4994
|
-
binary2 = await
|
|
4996
|
+
const fs2 = await import("fs/promises");
|
|
4997
|
+
binary2 = await fs2.readFile(input);
|
|
4995
4998
|
} else {
|
|
4996
4999
|
const response = await fetch(input);
|
|
4997
5000
|
if (!response.ok) {
|
|
@@ -5042,11 +5045,11 @@ async function Module2(moduleArg = {}) {
|
|
|
5042
5045
|
}, "quit_");
|
|
5043
5046
|
var _scriptName = import.meta.url;
|
|
5044
5047
|
var scriptDirectory = "";
|
|
5045
|
-
function locateFile(
|
|
5048
|
+
function locateFile(path) {
|
|
5046
5049
|
if (Module["locateFile"]) {
|
|
5047
|
-
return Module["locateFile"](
|
|
5050
|
+
return Module["locateFile"](path, scriptDirectory);
|
|
5048
5051
|
}
|
|
5049
|
-
return scriptDirectory +
|
|
5052
|
+
return scriptDirectory + path;
|
|
5050
5053
|
}
|
|
5051
5054
|
__name(locateFile, "locateFile");
|
|
5052
5055
|
var readAsync, readBinary;
|
|
@@ -9744,23 +9747,23 @@ function createWorkflowGuard(options) {
|
|
|
9744
9747
|
return recoveryUnitProgressionReason(progression);
|
|
9745
9748
|
}
|
|
9746
9749
|
function recoveryUnitProgressionReason(progression) {
|
|
9747
|
-
const
|
|
9750
|
+
const epoch = progression.epoch;
|
|
9748
9751
|
const unit = progression.unit;
|
|
9749
|
-
if (!
|
|
9752
|
+
if (!epoch)
|
|
9750
9753
|
return "invalid-recovery";
|
|
9751
9754
|
if (!unit) {
|
|
9752
|
-
return
|
|
9755
|
+
return epoch.state === "completed" ? "invalid-recovery" : undefined;
|
|
9753
9756
|
}
|
|
9754
|
-
const declarationFailure = recoveryUnitDeclarationReason(
|
|
9757
|
+
const declarationFailure = recoveryUnitDeclarationReason(epoch, unit);
|
|
9755
9758
|
if (declarationFailure)
|
|
9756
9759
|
return declarationFailure;
|
|
9757
|
-
return unit.resourceScopes.some((scope) => !unit.requiredOperations.includes(scope.operation)) ? "invalid-recovery" : recoveryCompletedPairReason(
|
|
9760
|
+
return unit.resourceScopes.some((scope) => !unit.requiredOperations.includes(scope.operation)) ? "invalid-recovery" : recoveryCompletedPairReason(epoch, unit);
|
|
9758
9761
|
}
|
|
9759
|
-
function recoveryUnitDeclarationReason(
|
|
9760
|
-
return unit.epochId ===
|
|
9762
|
+
function recoveryUnitDeclarationReason(epoch, unit) {
|
|
9763
|
+
return unit.epochId === epoch.epochId && unit.epochDigest === epoch.epochDigest && unit.unitDigest === options.ledger.digestIdentity("unit", unit.unitId) && unit.family === epoch.family ? undefined : "invalid-recovery";
|
|
9761
9764
|
}
|
|
9762
|
-
function recoveryCompletedPairReason(
|
|
9763
|
-
return
|
|
9765
|
+
function recoveryCompletedPairReason(epoch, unit) {
|
|
9766
|
+
return epoch.state === "completed" && unit.state !== "completed" ? "invalid-recovery" : undefined;
|
|
9764
9767
|
}
|
|
9765
9768
|
function recoveryBoundaryReason(envelope) {
|
|
9766
9769
|
if (envelope.canonical.workspaceDigest !== options.ledger.digestIdentity("workspace", currentWorkspaceIdentity)) {
|
|
@@ -9857,8 +9860,8 @@ function createWorkflowGuard(options) {
|
|
|
9857
9860
|
}
|
|
9858
9861
|
return;
|
|
9859
9862
|
}
|
|
9860
|
-
function recoveryEpochCompletionReason(
|
|
9861
|
-
if (
|
|
9863
|
+
function recoveryEpochCompletionReason(epoch, matching) {
|
|
9864
|
+
if (epoch?.state !== "completed")
|
|
9862
9865
|
return;
|
|
9863
9866
|
return matching.length > 0 && matching.every((envelope) => envelope.canonical.consumption === "consumed") ? undefined : "invalid-recovery";
|
|
9864
9867
|
}
|
|
@@ -10291,18 +10294,18 @@ function isWorkflowGuardBlockedError(value) {
|
|
|
10291
10294
|
return typeof candidate.reasonCode === "string" && REASON_CODES.has(candidate.reasonCode);
|
|
10292
10295
|
}
|
|
10293
10296
|
var startToolShape = {
|
|
10294
|
-
expected_operations:
|
|
10295
|
-
resource_scopes:
|
|
10297
|
+
expected_operations: array(_enum(OPERATIONS)).optional(),
|
|
10298
|
+
resource_scopes: record(string(), string()).optional()
|
|
10296
10299
|
};
|
|
10297
|
-
var completeToolShape = { target:
|
|
10300
|
+
var completeToolShape = { target: _enum(["unit", "epoch"]) };
|
|
10298
10301
|
var controlToolShape = {
|
|
10299
|
-
mode:
|
|
10302
|
+
mode: _enum(["protected", "disabled", "unavailable"])
|
|
10300
10303
|
};
|
|
10301
10304
|
var statusToolShape = {};
|
|
10302
|
-
var startToolSchema =
|
|
10303
|
-
var completeToolSchema =
|
|
10304
|
-
var controlToolSchema =
|
|
10305
|
-
var statusToolSchema =
|
|
10305
|
+
var startToolSchema = object(startToolShape).strict();
|
|
10306
|
+
var completeToolSchema = object(completeToolShape).strict();
|
|
10307
|
+
var controlToolSchema = object(controlToolShape).strict();
|
|
10308
|
+
var statusToolSchema = object(statusToolShape).strict();
|
|
10306
10309
|
function isRecord7(value) {
|
|
10307
10310
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10308
10311
|
}
|
|
@@ -10453,13 +10456,13 @@ function validationForCandidate(candidatePath, options, targetPath = candidatePa
|
|
|
10453
10456
|
}
|
|
10454
10457
|
function deriveFileTarget(rawPath, baseDirectory, parentTargetRoot, options, realPath, allowParentFastPath = true) {
|
|
10455
10458
|
const resolvedPath = path6.resolve(baseDirectory, rawPath);
|
|
10456
|
-
const
|
|
10457
|
-
if (!
|
|
10459
|
+
const canonicalPath = canonicalFileTarget(resolvedPath, realPath);
|
|
10460
|
+
if (!canonicalPath)
|
|
10458
10461
|
return unavailableOperationTarget();
|
|
10459
|
-
const parentResult = allowParentFastPath && !path6.isAbsolute(rawPath) ? trustedParentTarget(parentTargetRoot,
|
|
10462
|
+
const parentResult = allowParentFastPath && !path6.isAbsolute(rawPath) ? trustedParentTarget(parentTargetRoot, canonicalPath) : undefined;
|
|
10460
10463
|
if (parentResult)
|
|
10461
10464
|
return parentResult;
|
|
10462
|
-
return validationForCandidate(path6.dirname(
|
|
10465
|
+
return validationForCandidate(path6.dirname(canonicalPath), options, canonicalPath);
|
|
10463
10466
|
}
|
|
10464
10467
|
function sharedTargetRoot(targets, extraRoots = []) {
|
|
10465
10468
|
const roots = [...extraRoots];
|
|
@@ -11057,7 +11060,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
11057
11060
|
return classifyQuestionAnswer(answer) === "affirmative" ? answer : "no";
|
|
11058
11061
|
}
|
|
11059
11062
|
function challengeForTransition(sessionID, target) {
|
|
11060
|
-
const existing = [...pendingQuestionChallenges.values()].find((
|
|
11063
|
+
const existing = [...pendingQuestionChallenges.values()].find((pending) => pending.purpose === "transition" && pending.transition === target);
|
|
11061
11064
|
if (existing)
|
|
11062
11065
|
return existing;
|
|
11063
11066
|
const resource = questionResource(target);
|
|
@@ -11079,7 +11082,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
11079
11082
|
return pending;
|
|
11080
11083
|
}
|
|
11081
11084
|
function challengeForDisablement(sessionID) {
|
|
11082
|
-
const existing = [...pendingQuestionChallenges.values()].find((
|
|
11085
|
+
const existing = [...pendingQuestionChallenges.values()].find((pending) => pending.purpose === "session-disablement");
|
|
11083
11086
|
if (existing)
|
|
11084
11087
|
return existing;
|
|
11085
11088
|
const resource = `session/${sessionID}`;
|
|
@@ -11253,14 +11256,14 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
11253
11256
|
}
|
|
11254
11257
|
return;
|
|
11255
11258
|
}
|
|
11256
|
-
function candidateAgreesWithOwnIdentity(salt,
|
|
11259
|
+
function candidateAgreesWithOwnIdentity(salt, digest) {
|
|
11257
11260
|
try {
|
|
11258
11261
|
const probe = createReceiptLedger({
|
|
11259
11262
|
capabilityFlags: ["workflow-guard"],
|
|
11260
11263
|
registrationIdentity: options.registrationIdentity,
|
|
11261
11264
|
sessionSalt: salt
|
|
11262
11265
|
});
|
|
11263
|
-
return probe.metadata.registrationDigest ===
|
|
11266
|
+
return probe.metadata.registrationDigest === digest;
|
|
11264
11267
|
} catch {
|
|
11265
11268
|
return false;
|
|
11266
11269
|
}
|
|
@@ -12465,7 +12468,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
12465
12468
|
return;
|
|
12466
12469
|
}
|
|
12467
12470
|
}
|
|
12468
|
-
function buildOperationObservation(host, pending,
|
|
12471
|
+
function buildOperationObservation(host, pending, after, current, output, operation = operationCandidate(host.tool), remoteAfter) {
|
|
12469
12472
|
if (!current.epoch || !current.unit || !isLocalOperationTool(host.tool)) {
|
|
12470
12473
|
return;
|
|
12471
12474
|
}
|
|
@@ -12489,10 +12492,10 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
12489
12492
|
},
|
|
12490
12493
|
after: {
|
|
12491
12494
|
workspaceIdentity: options.workspaceIdentity,
|
|
12492
|
-
repositoryIdentity:
|
|
12493
|
-
worktreeIdentity:
|
|
12495
|
+
repositoryIdentity: after.repositoryRevisionDigest,
|
|
12496
|
+
worktreeIdentity: after.worktreeRevisionDigest,
|
|
12494
12497
|
...localOperation(operation) ? { operationTargetIdentity: pending.targetIdentity } : {},
|
|
12495
|
-
commitClosure:
|
|
12498
|
+
commitClosure: after.commitClosure,
|
|
12496
12499
|
...remoteAfter ? {
|
|
12497
12500
|
resourceIdentity: remoteAfter.resourceIdentity,
|
|
12498
12501
|
resourceRevisionIdentity: remoteAfter.resourceRevisionIdentity,
|
|
@@ -13093,7 +13096,7 @@ function createSkillTool(options) {
|
|
|
13093
13096
|
return cachedDescription;
|
|
13094
13097
|
},
|
|
13095
13098
|
args: {
|
|
13096
|
-
name:
|
|
13099
|
+
name: string().describe((() => {
|
|
13097
13100
|
if (cachedParameterHint == null) {
|
|
13098
13101
|
cachedParameterHint = buildParameterHint();
|
|
13099
13102
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type ArtifactPathResult = {
|
|
2
|
+
readonly ok: true;
|
|
3
|
+
readonly path: string;
|
|
4
|
+
} | {
|
|
5
|
+
readonly ok: false;
|
|
6
|
+
readonly message: string;
|
|
7
|
+
};
|
|
8
|
+
export type ReadArtifactResult = {
|
|
9
|
+
readonly ok: true;
|
|
10
|
+
readonly value: unknown;
|
|
11
|
+
} | {
|
|
12
|
+
readonly ok: false;
|
|
13
|
+
readonly message: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function formatReviewArtifactIssuePath(issuePath: readonly PropertyKey[]): string;
|
|
16
|
+
export declare function readReviewArtifact(filePath: string): ReadArtifactResult;
|
|
17
|
+
export declare function isLegacyReviewArtifact(value: unknown): boolean;
|
|
18
|
+
export declare function hasParentDirectoryTraversal(input: string): boolean;
|
|
19
|
+
export declare function pathContainsSymlink(candidate: string): boolean;
|
|
20
|
+
export declare function resolveReviewArtifactPath(input: string, cwd: string): ArtifactPathResult;
|
package/dist/pi.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/pi.ts
|
|
2
2
|
import path6 from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { Type as
|
|
4
|
+
import { Type as Type3 } from "typebox";
|
|
5
5
|
|
|
6
6
|
// src/lib/agent-resolver.ts
|
|
7
7
|
import fs2 from "node:fs";
|
|
@@ -3114,6 +3114,22 @@ function requireJsYaml() {
|
|
|
3114
3114
|
}
|
|
3115
3115
|
var jsYamlExports = requireJsYaml();
|
|
3116
3116
|
var yaml = /* @__PURE__ */ getDefaultExportFromCjs(jsYamlExports);
|
|
3117
|
+
var {
|
|
3118
|
+
Type,
|
|
3119
|
+
Schema,
|
|
3120
|
+
FAILSAFE_SCHEMA,
|
|
3121
|
+
JSON_SCHEMA,
|
|
3122
|
+
CORE_SCHEMA,
|
|
3123
|
+
DEFAULT_SCHEMA,
|
|
3124
|
+
load,
|
|
3125
|
+
loadAll,
|
|
3126
|
+
dump,
|
|
3127
|
+
YAMLException,
|
|
3128
|
+
types,
|
|
3129
|
+
safeLoad,
|
|
3130
|
+
safeLoadAll,
|
|
3131
|
+
safeDump
|
|
3132
|
+
} = yaml;
|
|
3117
3133
|
|
|
3118
3134
|
// src/lib/frontmatter.ts
|
|
3119
3135
|
function parseFrontmatter(content) {
|
|
@@ -3412,7 +3428,7 @@ import {
|
|
|
3412
3428
|
} from "@earendil-works/pi-coding-agent";
|
|
3413
3429
|
|
|
3414
3430
|
// src/lib/pi-delegate-tool.ts
|
|
3415
|
-
import { Type } from "typebox";
|
|
3431
|
+
import { Type as Type2 } from "typebox";
|
|
3416
3432
|
var MAX_DELEGATE_TURNS = 20;
|
|
3417
3433
|
var DELEGATE_TOOL_NAME = "systematic_delegate";
|
|
3418
3434
|
var DELEGATE_EXECUTION_MODE = "sequential";
|
|
@@ -3486,9 +3502,9 @@ function createPiDelegateTool(deps) {
|
|
|
3486
3502
|
};
|
|
3487
3503
|
}
|
|
3488
3504
|
function buildDelegateParametersSchema(catalog) {
|
|
3489
|
-
return
|
|
3490
|
-
agent:
|
|
3491
|
-
task:
|
|
3505
|
+
return Type2.Object({
|
|
3506
|
+
agent: Type2.String({ description: buildAgentParameterHint(catalog) }),
|
|
3507
|
+
task: Type2.String({
|
|
3492
3508
|
description: "The task to delegate to the persona."
|
|
3493
3509
|
})
|
|
3494
3510
|
});
|
|
@@ -4023,8 +4039,8 @@ async function systematicPiExtension(pi, deps = defaultPiExtensionDependencies)
|
|
|
4023
4039
|
label: "Systematic Skill",
|
|
4024
4040
|
description: buildSkillToolDescription(resolverOptions),
|
|
4025
4041
|
promptSnippet: "Use `systematic_skill` to load Systematic skills.",
|
|
4026
|
-
parameters:
|
|
4027
|
-
name:
|
|
4042
|
+
parameters: Type3.Object({
|
|
4043
|
+
name: Type3.String({
|
|
4028
4044
|
description: buildSkillToolParameterHint(resolverOptions)
|
|
4029
4045
|
})
|
|
4030
4046
|
}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fro.bot/systematic",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.1",
|
|
4
4
|
"description": "Compound-engineering loops for OpenCode, Pi, and Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://fro.bot/systematic",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"registry:drift": "bun scripts/generate-registry.ts --check",
|
|
58
58
|
"registry:validate": "bun scripts/build-registry.ts --validate-only",
|
|
59
59
|
"claude-code:build": "bun scripts/build-claude-code-plugin.ts",
|
|
60
|
-
"postupgrade": "bun run build && bun run agent-browser:build",
|
|
60
|
+
"postupgrade": "bun run build && bun run agent-browser:build && bun run schema:generate && bun run review-schema:generate && bun scripts/generate-registry.ts",
|
|
61
61
|
"prepublishOnly": "bun run build && bun run schema:generate"
|
|
62
62
|
},
|
|
63
63
|
"keywords": [
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
}
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
|
-
"@biomejs/biome": "2.5.
|
|
96
|
+
"@biomejs/biome": "2.5.11",
|
|
97
97
|
"@earendil-works/pi-coding-agent": "0.83.0",
|
|
98
98
|
"@opencode-ai/plugin": "1.18.21",
|
|
99
99
|
"@opencode-ai/sdk": "1.18.21",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"@tintinweb/pi-subagents": "0.14.3",
|
|
102
102
|
"@types/bun": "latest",
|
|
103
103
|
"@types/js-yaml": "4.0.9",
|
|
104
|
-
"@types/node": "26.
|
|
104
|
+
"@types/node": "26.4.0",
|
|
105
105
|
"agent-browser": "0.34.0",
|
|
106
106
|
"ajv": "8.20.0",
|
|
107
107
|
"ajv-formats": "3.0.1",
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"rimraf": "6.1.3",
|
|
111
111
|
"semantic-release": "25.0.9",
|
|
112
112
|
"semantic-release-export-data": "1.2.0",
|
|
113
|
-
"typebox": "1.3.
|
|
113
|
+
"typebox": "1.3.24",
|
|
114
114
|
"typescript": "7.0.2"
|
|
115
115
|
},
|
|
116
116
|
"dependencies": {
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"jsonc-parser": "^3.3.0",
|
|
119
119
|
"tree-sitter-bash": "0.25.1",
|
|
120
120
|
"web-tree-sitter": "0.26.12",
|
|
121
|
-
"zod": "4.4
|
|
121
|
+
"zod": "4.5.4"
|
|
122
122
|
},
|
|
123
123
|
"overrides": {
|
|
124
124
|
"@earendil-works/pi-ai": "0.83.0",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"completed_at": {
|
|
42
42
|
"type": "string",
|
|
43
43
|
"format": "date-time",
|
|
44
|
-
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d
|
|
44
|
+
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
|
|
45
45
|
},
|
|
46
46
|
"dispatches": {
|
|
47
47
|
"maxItems": 64,
|