@rness/cli 0.9.1 → 0.10.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/README.md +57 -1
- package/dist/bin/rness.js +1 -1
- package/dist/{chunk-N3F6N6GA.js → chunk-R4BRAAC2.js} +577 -321
- package/dist/chunk-R4BRAAC2.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-N3F6N6GA.js.map +0 -1
|
@@ -558,8 +558,8 @@ async function getOrgMembership(org, options) {
|
|
|
558
558
|
}
|
|
559
559
|
if (status2 === 404) return "not-member";
|
|
560
560
|
if (status2 === 403) {
|
|
561
|
-
const
|
|
562
|
-
if (/OAuth App access restrictions/i.test(
|
|
561
|
+
const message2 = body !== null && typeof body === "object" ? String(body["message"] ?? "") : "";
|
|
562
|
+
if (/OAuth App access restrictions/i.test(message2)) return "restricted";
|
|
563
563
|
}
|
|
564
564
|
return "unknown";
|
|
565
565
|
}
|
|
@@ -581,8 +581,8 @@ async function createRepository(owner, name, options) {
|
|
|
581
581
|
throw new Error(`cannot reach the GitHub API: ${reason2(e)}`, { cause: e });
|
|
582
582
|
}
|
|
583
583
|
const body = await res.json().catch(() => void 0);
|
|
584
|
-
const
|
|
585
|
-
return { status: res.status, message };
|
|
584
|
+
const message2 = body !== null && typeof body === "object" ? String(body["message"] ?? "") : "";
|
|
585
|
+
return { status: res.status, message: message2 };
|
|
586
586
|
};
|
|
587
587
|
let answer = await post2(`/orgs/${encodeURIComponent(owner)}/repos`);
|
|
588
588
|
if (answer.status === 404 && options.self !== void 0 && options.self !== null && options.self.toLowerCase() === owner.toLowerCase())
|
|
@@ -775,9 +775,9 @@ async function originUrl(dir) {
|
|
|
775
775
|
async function init(dir) {
|
|
776
776
|
await git(["init", "-q", "-b", "main"], dir);
|
|
777
777
|
}
|
|
778
|
-
async function commitAll(dir,
|
|
778
|
+
async function commitAll(dir, message2) {
|
|
779
779
|
await git(["add", "-A"], dir);
|
|
780
|
-
await git(["commit", "-q", "-m",
|
|
780
|
+
await git(["commit", "-q", "-m", message2], dir);
|
|
781
781
|
}
|
|
782
782
|
|
|
783
783
|
// src/core/remote.ts
|
|
@@ -812,7 +812,7 @@ function classifyProbe(url, exitCode, stderr) {
|
|
|
812
812
|
var STDERR_FLUSH_MS = 200;
|
|
813
813
|
async function probeRemote(url, timeoutMs = 6e4, credentials) {
|
|
814
814
|
positional(url, "repository url");
|
|
815
|
-
return new Promise((
|
|
815
|
+
return new Promise((resolve8) => {
|
|
816
816
|
const auth = withCredentials(credentials);
|
|
817
817
|
const child = spawn(
|
|
818
818
|
"git",
|
|
@@ -831,7 +831,7 @@ async function probeRemote(url, timeoutMs = 6e4, credentials) {
|
|
|
831
831
|
settled = true;
|
|
832
832
|
clearTimeout(timer);
|
|
833
833
|
child.stderr?.destroy();
|
|
834
|
-
|
|
834
|
+
resolve8(probe);
|
|
835
835
|
};
|
|
836
836
|
const timer = setTimeout(() => {
|
|
837
837
|
child.kill("SIGKILL");
|
|
@@ -876,8 +876,8 @@ function isWorkspaceClone(name) {
|
|
|
876
876
|
var NAME_RULE = "lowercase letters, digits, '.', '_' and '-', not starting with '-'";
|
|
877
877
|
var ORG_NAME = /^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$/;
|
|
878
878
|
var KEYS = ["contract", "org", "agents", "repos", "scopes"];
|
|
879
|
-
function fail(
|
|
880
|
-
throw new Error(`rness.json: ${
|
|
879
|
+
function fail(message2) {
|
|
880
|
+
throw new Error(`rness.json: ${message2}`);
|
|
881
881
|
}
|
|
882
882
|
function isRecord(value) {
|
|
883
883
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -1263,7 +1263,7 @@ async function detectGithubSsh(opts) {
|
|
|
1263
1263
|
...opts.interactive ? [] : ["-o", "BatchMode=yes"],
|
|
1264
1264
|
"git@github.com"
|
|
1265
1265
|
];
|
|
1266
|
-
return new Promise((
|
|
1266
|
+
return new Promise((resolve8) => {
|
|
1267
1267
|
const child = spawn2(opts.command ?? "ssh", args, {
|
|
1268
1268
|
stdio: [opts.interactive ? "inherit" : "ignore", "ignore", "pipe"]
|
|
1269
1269
|
});
|
|
@@ -1276,7 +1276,7 @@ async function detectGithubSsh(opts) {
|
|
|
1276
1276
|
settled = true;
|
|
1277
1277
|
clearTimeout(timer);
|
|
1278
1278
|
child.stderr?.destroy();
|
|
1279
|
-
|
|
1279
|
+
resolve8(access2);
|
|
1280
1280
|
};
|
|
1281
1281
|
const timer = setTimeout(() => {
|
|
1282
1282
|
child.kill("SIGKILL");
|
|
@@ -1397,15 +1397,15 @@ function reportError(e) {
|
|
|
1397
1397
|
process.stderr.write(`${e.stack}
|
|
1398
1398
|
`);
|
|
1399
1399
|
} else {
|
|
1400
|
-
const
|
|
1401
|
-
process.stderr.write(`${paint("error",
|
|
1400
|
+
const message2 = e instanceof Error ? e.message : String(e);
|
|
1401
|
+
process.stderr.write(`${paint("error", message2, process.stderr)}
|
|
1402
1402
|
`);
|
|
1403
1403
|
}
|
|
1404
1404
|
return 1;
|
|
1405
1405
|
}
|
|
1406
1406
|
|
|
1407
1407
|
// src/version.ts
|
|
1408
|
-
var VERSION = "0.
|
|
1408
|
+
var VERSION = "0.10.0";
|
|
1409
1409
|
|
|
1410
1410
|
// src/core/block.ts
|
|
1411
1411
|
import { createHash } from "crypto";
|
|
@@ -1473,8 +1473,8 @@ function isCurrentBlock(blockLines, freshHash) {
|
|
|
1473
1473
|
// src/core/frontmatter.ts
|
|
1474
1474
|
import { parse as parse2 } from "yaml";
|
|
1475
1475
|
var FRONT_MATTER = /^---\r?\n(?:([\s\S]*?)\r?\n)?---(?:\r?\n|$)/;
|
|
1476
|
-
function fail2(
|
|
1477
|
-
throw new Error(`front matter: ${
|
|
1476
|
+
function fail2(message2) {
|
|
1477
|
+
throw new Error(`front matter: ${message2}`);
|
|
1478
1478
|
}
|
|
1479
1479
|
function stripBom(source) {
|
|
1480
1480
|
return source.startsWith("\uFEFF") ? source.slice(1) : source;
|
|
@@ -1706,6 +1706,46 @@ import { mkdir as mkdir2 } from "fs/promises";
|
|
|
1706
1706
|
import { dirname as dirname4, join as join9 } from "path";
|
|
1707
1707
|
|
|
1708
1708
|
// src/core/agents.ts
|
|
1709
|
+
var PINNED_BIN = "node_modules/@rness/cli/dist/bin/rness.js";
|
|
1710
|
+
function hookLine(rness, event) {
|
|
1711
|
+
const run3 = `f="$CLAUDE_PROJECT_DIR/${rness}/${PINNED_BIN}"; if [ -f "$f" ]; then node "$f" hook ${event};`;
|
|
1712
|
+
if (event === "post-tool-use") return `${run3} fi`;
|
|
1713
|
+
const missing = JSON.stringify({
|
|
1714
|
+
systemMessage: `rness: ${rness} is not installed, so the workspace context is not loaded. Clone the workspace, then install its dependencies in .rness.`
|
|
1715
|
+
});
|
|
1716
|
+
return `${run3} else echo '${missing}'; fi`;
|
|
1717
|
+
}
|
|
1718
|
+
function hooks(rness) {
|
|
1719
|
+
return [
|
|
1720
|
+
{
|
|
1721
|
+
path: ["hooks", "SessionStart"],
|
|
1722
|
+
contains: {
|
|
1723
|
+
hooks: [
|
|
1724
|
+
{
|
|
1725
|
+
type: "command",
|
|
1726
|
+
command: hookLine(rness, "session-start"),
|
|
1727
|
+
timeout: 10
|
|
1728
|
+
}
|
|
1729
|
+
]
|
|
1730
|
+
},
|
|
1731
|
+
label: "the rness session-start hook"
|
|
1732
|
+
},
|
|
1733
|
+
{
|
|
1734
|
+
path: ["hooks", "PostToolUse"],
|
|
1735
|
+
contains: {
|
|
1736
|
+
matcher: "Edit|Write",
|
|
1737
|
+
hooks: [
|
|
1738
|
+
{
|
|
1739
|
+
type: "command",
|
|
1740
|
+
command: hookLine(rness, "post-tool-use"),
|
|
1741
|
+
timeout: 10
|
|
1742
|
+
}
|
|
1743
|
+
]
|
|
1744
|
+
},
|
|
1745
|
+
label: "the rness post-tool-use hook"
|
|
1746
|
+
}
|
|
1747
|
+
];
|
|
1748
|
+
}
|
|
1709
1749
|
var TARGETS = {
|
|
1710
1750
|
claude: {
|
|
1711
1751
|
name: "claude",
|
|
@@ -1713,6 +1753,7 @@ var TARGETS = {
|
|
|
1713
1753
|
files: [
|
|
1714
1754
|
{
|
|
1715
1755
|
file: ".claude/settings.json",
|
|
1756
|
+
at: "clones",
|
|
1716
1757
|
guarantees: [
|
|
1717
1758
|
// Read the context repository from a repository without a prompt.
|
|
1718
1759
|
// Resolved against the project directory, and applied once Claude
|
|
@@ -1720,11 +1761,13 @@ var TARGETS = {
|
|
|
1720
1761
|
{
|
|
1721
1762
|
path: ["permissions", "additionalDirectories"],
|
|
1722
1763
|
contains: "../../.rness"
|
|
1723
|
-
}
|
|
1764
|
+
},
|
|
1765
|
+
...hooks("../../.rness")
|
|
1724
1766
|
]
|
|
1725
1767
|
},
|
|
1726
1768
|
{
|
|
1727
1769
|
file: ".mcp.json",
|
|
1770
|
+
at: "clones",
|
|
1728
1771
|
guarantees: [
|
|
1729
1772
|
// The pinned copy, by a path relative to the repository — the
|
|
1730
1773
|
// directory Claude Code starts the server in (spec 0014 §6). Not
|
|
@@ -1742,6 +1785,13 @@ var TARGETS = {
|
|
|
1742
1785
|
}
|
|
1743
1786
|
}
|
|
1744
1787
|
]
|
|
1788
|
+
},
|
|
1789
|
+
// A session opened at the workspace root reads this file, one opened
|
|
1790
|
+
// in a clone does not (spec 0011 §1): the hooks only, `.rness` inside.
|
|
1791
|
+
{
|
|
1792
|
+
file: ".claude/settings.json",
|
|
1793
|
+
at: "root",
|
|
1794
|
+
guarantees: hooks(".rness")
|
|
1745
1795
|
}
|
|
1746
1796
|
]
|
|
1747
1797
|
}
|
|
@@ -1755,6 +1805,7 @@ function unsupportedMessage(name) {
|
|
|
1755
1805
|
}
|
|
1756
1806
|
|
|
1757
1807
|
// src/core/json-guarantees.ts
|
|
1808
|
+
import { isDeepStrictEqual } from "util";
|
|
1758
1809
|
function isObject(value) {
|
|
1759
1810
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1760
1811
|
}
|
|
@@ -1798,14 +1849,15 @@ function apply(root, g, create) {
|
|
|
1798
1849
|
}
|
|
1799
1850
|
if (value === void 0) {
|
|
1800
1851
|
if (!create) return { holds: false, changed: false };
|
|
1801
|
-
parent[last] = [g.contains];
|
|
1852
|
+
parent[last] = [structuredClone(g.contains)];
|
|
1802
1853
|
return { holds: true, changed: true };
|
|
1803
1854
|
}
|
|
1804
1855
|
if (!Array.isArray(value))
|
|
1805
1856
|
return { invalid: `${g.path.join(".")} is not a list` };
|
|
1806
|
-
if (value.
|
|
1857
|
+
if (value.some((entry) => isDeepStrictEqual(entry, g.contains)))
|
|
1858
|
+
return { holds: true, changed: false };
|
|
1807
1859
|
if (!create) return { holds: false, changed: false };
|
|
1808
|
-
value.push(g.contains);
|
|
1860
|
+
value.push(structuredClone(g.contains));
|
|
1809
1861
|
return { holds: true, changed: true };
|
|
1810
1862
|
}
|
|
1811
1863
|
function styleOf(text) {
|
|
@@ -1849,21 +1901,33 @@ function missingGuarantees(existing, guarantees) {
|
|
|
1849
1901
|
return missing;
|
|
1850
1902
|
}
|
|
1851
1903
|
function describeGuarantee(g) {
|
|
1852
|
-
|
|
1904
|
+
if ("value" in g) return `${g.path.join(".")} is missing`;
|
|
1905
|
+
const what = g.label ?? (typeof g.contains === "string" ? g.contains : JSON.stringify(g.contains));
|
|
1906
|
+
return `${g.path.join(".")} lacks ${what}`;
|
|
1853
1907
|
}
|
|
1854
1908
|
|
|
1855
1909
|
// src/core/agent-targets.ts
|
|
1856
1910
|
async function filesOf(root, manifest, targets) {
|
|
1857
1911
|
const files = [];
|
|
1912
|
+
if (!await exists(join9(root, "org"))) return files;
|
|
1913
|
+
for (const target of targets)
|
|
1914
|
+
for (const owned of target.files)
|
|
1915
|
+
if (owned.at === "root")
|
|
1916
|
+
files.push({
|
|
1917
|
+
guarantees: owned.guarantees,
|
|
1918
|
+
file: join9(root, ...owned.file.split("/")),
|
|
1919
|
+
label: owned.file
|
|
1920
|
+
});
|
|
1858
1921
|
for (const repo of Object.keys(manifest.repos)) {
|
|
1859
1922
|
if (!await exists(join9(root, "org", repo))) continue;
|
|
1860
1923
|
for (const target of targets)
|
|
1861
1924
|
for (const owned of target.files)
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1925
|
+
if (owned.at === "clones")
|
|
1926
|
+
files.push({
|
|
1927
|
+
guarantees: owned.guarantees,
|
|
1928
|
+
file: join9(root, "org", repo, ...owned.file.split("/")),
|
|
1929
|
+
label: `org/${repo}/${owned.file}`
|
|
1930
|
+
});
|
|
1867
1931
|
}
|
|
1868
1932
|
return files;
|
|
1869
1933
|
}
|
|
@@ -1876,7 +1940,9 @@ var BLOCK_FILES = ["AGENTS.md", "CLAUDE.md"];
|
|
|
1876
1940
|
function writtenFiles(manifest) {
|
|
1877
1941
|
return [
|
|
1878
1942
|
...BLOCK_FILES,
|
|
1879
|
-
...declared(manifest).flatMap(
|
|
1943
|
+
...declared(manifest).flatMap(
|
|
1944
|
+
(t) => t.files.filter((f) => f.at === "clones").map((f) => f.file)
|
|
1945
|
+
)
|
|
1880
1946
|
];
|
|
1881
1947
|
}
|
|
1882
1948
|
async function agentTargets(root, manifest, opts) {
|
|
@@ -2064,8 +2130,8 @@ function sessionUi(p) {
|
|
|
2064
2130
|
intro: (title) => {
|
|
2065
2131
|
p.intro(badge(title));
|
|
2066
2132
|
},
|
|
2067
|
-
outro: (
|
|
2068
|
-
p.outro(badge(
|
|
2133
|
+
outro: (message2, tone = "done") => {
|
|
2134
|
+
p.outro(badge(message2, tone));
|
|
2069
2135
|
},
|
|
2070
2136
|
line: (verb, rest, sentence) => {
|
|
2071
2137
|
say(verb, sentence ?? `${rest} ${verb}`);
|
|
@@ -2088,7 +2154,7 @@ function sessionUi(p) {
|
|
|
2088
2154
|
async step(options, work, done) {
|
|
2089
2155
|
const label = options.sentence ?? tidy(options.doing);
|
|
2090
2156
|
const finish2 = (result) => done?.(result) ?? null;
|
|
2091
|
-
const label_ = (line2) => `${line2[1]} ${line2[0]}`;
|
|
2157
|
+
const label_ = (line2) => line2[2] ?? `${line2[1]} ${line2[0]}`;
|
|
2092
2158
|
if (options.git === true && !this.gitIsSilent) {
|
|
2093
2159
|
p.log.message(paint("idle", `${label}\u2026`));
|
|
2094
2160
|
const result = await work();
|
|
@@ -3109,19 +3175,32 @@ async function runPinnedSync(root) {
|
|
|
3109
3175
|
};
|
|
3110
3176
|
}
|
|
3111
3177
|
}
|
|
3178
|
+
var SYNC_VERBS = ["updated", "unchanged", "stale"];
|
|
3179
|
+
function counted(noun, counts) {
|
|
3180
|
+
const total = [...counts.values()].reduce((a, b) => a + b, 0);
|
|
3181
|
+
const detail = SYNC_VERBS.filter((verb) => counts.has(verb)).map((verb) => `${counts.get(verb) ?? 0} ${verb}`).join(", ");
|
|
3182
|
+
return `${total} ${noun}${total === 1 ? "" : "s"}${detail === "" ? "" : `: ${detail}`}`;
|
|
3183
|
+
}
|
|
3112
3184
|
function summariseSync(stdout) {
|
|
3113
|
-
const
|
|
3185
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
3186
|
+
const agentFiles = /* @__PURE__ */ new Map();
|
|
3114
3187
|
const others = [];
|
|
3115
3188
|
for (const line2 of stdout.split("\n")) {
|
|
3116
3189
|
if (line2.trim() === "") continue;
|
|
3117
|
-
const
|
|
3118
|
-
if (
|
|
3119
|
-
|
|
3190
|
+
const m = /^(updated|unchanged|stale)\s+(\S+)/.exec(line2);
|
|
3191
|
+
if (m === null) {
|
|
3192
|
+
others.push(line2);
|
|
3193
|
+
continue;
|
|
3194
|
+
}
|
|
3195
|
+
const [, verb = "", path = ""] = m;
|
|
3196
|
+
const counts = /(^|\/)(AGENTS|CLAUDE)\.md$/.test(path) ? blocks : agentFiles;
|
|
3197
|
+
counts.set(verb, (counts.get(verb) ?? 0) + 1);
|
|
3120
3198
|
}
|
|
3121
|
-
const total = [...counts.values()].reduce((a, b) => a + b, 0);
|
|
3122
|
-
const detail = [...counts].map(([verb, n]) => `${n} ${verb}`).join(", ");
|
|
3123
3199
|
return {
|
|
3124
|
-
summary:
|
|
3200
|
+
summary: [
|
|
3201
|
+
counted("block", blocks),
|
|
3202
|
+
...agentFiles.size > 0 ? [counted("agent file", agentFiles)] : []
|
|
3203
|
+
].join("; "),
|
|
3125
3204
|
others
|
|
3126
3205
|
};
|
|
3127
3206
|
}
|
|
@@ -3227,13 +3306,13 @@ function scaffoldMessage(subject, version) {
|
|
|
3227
3306
|
|
|
3228
3307
|
${SCAFFOLD_TRAILER}: ${version}`;
|
|
3229
3308
|
}
|
|
3230
|
-
async function commitUpgrade(rnessDir,
|
|
3309
|
+
async function commitUpgrade(rnessDir, message2) {
|
|
3231
3310
|
const add = await run(rnessDir, ["add", "-A"]);
|
|
3232
3311
|
if (add.code !== 0) return { kind: "refused", output: add.stderr.trim() };
|
|
3233
3312
|
const staged = await run(rnessDir, ["diff", "--cached", "--quiet"]);
|
|
3234
3313
|
if (staged.code === 0 && !await mergeInProgress(rnessDir))
|
|
3235
3314
|
return { kind: "nothing" };
|
|
3236
|
-
const commit = await run(rnessDir, ["commit", "-q", "-m",
|
|
3315
|
+
const commit = await run(rnessDir, ["commit", "-q", "-m", message2]);
|
|
3237
3316
|
if (commit.code !== 0)
|
|
3238
3317
|
return {
|
|
3239
3318
|
kind: "refused",
|
|
@@ -3474,7 +3553,10 @@ async function syncBlocks(ui, root, shown, inPlace, sshWorks) {
|
|
|
3474
3553
|
sentence: "Writing the rness block into every AGENTS.md"
|
|
3475
3554
|
},
|
|
3476
3555
|
() => runPinnedSync(root),
|
|
3477
|
-
(r) => r === null || r.code !== 0 ? null :
|
|
3556
|
+
(r) => r === null || r.code !== 0 ? null : (() => {
|
|
3557
|
+
const { summary } = summariseSync(r.stdout);
|
|
3558
|
+
return ["synced", summary, `Synced ${summary}`];
|
|
3559
|
+
})()
|
|
3478
3560
|
);
|
|
3479
3561
|
if (result === null) {
|
|
3480
3562
|
if (inPlace !== void 0) return inPlace();
|
|
@@ -3751,9 +3833,9 @@ async function cloneSelection(input) {
|
|
|
3751
3833
|
manifest = result.manifest;
|
|
3752
3834
|
ui.line("declared", `scope ${result.name} (org/${result.name})`);
|
|
3753
3835
|
} catch (e) {
|
|
3754
|
-
const
|
|
3755
|
-
ui.error(`${spec}: ${
|
|
3756
|
-
failures.push({ spec, message });
|
|
3836
|
+
const message2 = firstLine4(e instanceof Error ? e.message : String(e));
|
|
3837
|
+
ui.error(`${spec}: ${message2}`);
|
|
3838
|
+
failures.push({ spec, message: message2 });
|
|
3757
3839
|
}
|
|
3758
3840
|
}
|
|
3759
3841
|
return failures;
|
|
@@ -4246,36 +4328,89 @@ ${next2.map((l) => ` ${l}`).join("\n")}
|
|
|
4246
4328
|
}
|
|
4247
4329
|
}
|
|
4248
4330
|
|
|
4249
|
-
// src/
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4331
|
+
// src/core/blocks.ts
|
|
4332
|
+
import { join as join20 } from "path";
|
|
4333
|
+
var PROBLEM = /* @__PURE__ */ new Set(["stale", "malformed"]);
|
|
4334
|
+
async function checkBlocks({
|
|
4335
|
+
root,
|
|
4336
|
+
rnessDir,
|
|
4337
|
+
manifest,
|
|
4338
|
+
org
|
|
4339
|
+
}) {
|
|
4340
|
+
const checks = [];
|
|
4341
|
+
const note = (label, status2, message2 = null) => {
|
|
4342
|
+
checks.push({ label, status: status2, message: message2 });
|
|
4343
|
+
};
|
|
4344
|
+
const derive = () => ({
|
|
4345
|
+
problems: checks.filter((c) => PROBLEM.has(c.status) && c.message !== null).map((c) => c.message),
|
|
4346
|
+
warnings: checks.filter((c) => !PROBLEM.has(c.status) && c.message !== null).map((c) => c.message),
|
|
4347
|
+
checks
|
|
4348
|
+
});
|
|
4349
|
+
if (!await exists(join20(root, "org"))) return derive();
|
|
4350
|
+
const targets = [
|
|
4351
|
+
{ scope: null, dir: root, depth: 0, file: "AGENTS.md", label: "AGENTS.md" },
|
|
4352
|
+
{ scope: null, dir: root, depth: 0, file: "CLAUDE.md", label: "CLAUDE.md" }
|
|
4353
|
+
];
|
|
4354
|
+
for (const [name, entry] of Object.entries(manifest.scopes)) {
|
|
4355
|
+
const segments = entry.path.split("/");
|
|
4356
|
+
targets.push({
|
|
4357
|
+
scope: name,
|
|
4358
|
+
dir: join20(root, ...segments),
|
|
4359
|
+
depth: segments.length,
|
|
4360
|
+
file: "AGENTS.md",
|
|
4361
|
+
label: `${entry.path}/AGENTS.md`
|
|
4362
|
+
});
|
|
4363
|
+
}
|
|
4364
|
+
for (const t of targets) {
|
|
4365
|
+
if (!await exists(t.dir)) {
|
|
4366
|
+
note(
|
|
4367
|
+
t.label,
|
|
4368
|
+
"missing-dir",
|
|
4369
|
+
`${t.label}: directory not present, block not checked`
|
|
4370
|
+
);
|
|
4371
|
+
continue;
|
|
4258
4372
|
}
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4373
|
+
const text = await readOrNull(join20(t.dir, t.file));
|
|
4374
|
+
const lines = text === null ? [] : text.split(/\r?\n/);
|
|
4375
|
+
const found = findBlock(lines);
|
|
4376
|
+
if (found.kind === "none") {
|
|
4377
|
+
note(
|
|
4378
|
+
t.label,
|
|
4379
|
+
"no-block",
|
|
4380
|
+
`${t.label}: no rness block yet (run ${rnessCommand()} sync)`
|
|
4263
4381
|
);
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
`
|
|
4382
|
+
continue;
|
|
4383
|
+
}
|
|
4384
|
+
if (found.kind === "error") {
|
|
4385
|
+
note(t.label, "malformed", `${t.label}: ${found.message}`);
|
|
4386
|
+
continue;
|
|
4387
|
+
}
|
|
4388
|
+
const context2 = await assembleContext({
|
|
4389
|
+
rnessDir,
|
|
4390
|
+
manifest,
|
|
4391
|
+
scope: t.scope
|
|
4392
|
+
});
|
|
4393
|
+
const fresh2 = renderBlock({
|
|
4394
|
+
scope: t.scope,
|
|
4395
|
+
org,
|
|
4396
|
+
depth: t.depth,
|
|
4397
|
+
context: context2
|
|
4398
|
+
});
|
|
4399
|
+
const pointerLeft = t.file === "CLAUDE.md" && lines.some((l) => l.trim() === "@AGENTS.md");
|
|
4400
|
+
if (isCurrentBlock(lines.slice(found.begin, found.end + 1), fresh2.hash) && !pointerLeft)
|
|
4401
|
+
note(t.label, "current");
|
|
4402
|
+
else
|
|
4403
|
+
note(
|
|
4404
|
+
t.label,
|
|
4405
|
+
"stale",
|
|
4406
|
+
`${t.label}: stale rness block (run ${rnessCommand()} sync)`
|
|
4268
4407
|
);
|
|
4269
|
-
process.stdout.write(`revoke rness on GitHub: ${revokeUrl()}
|
|
4270
|
-
`);
|
|
4271
|
-
return 0;
|
|
4272
|
-
} catch (e) {
|
|
4273
|
-
return reportError(e);
|
|
4274
4408
|
}
|
|
4409
|
+
return derive();
|
|
4275
4410
|
}
|
|
4276
4411
|
|
|
4277
4412
|
// src/core/contract.ts
|
|
4278
|
-
import { join as
|
|
4413
|
+
import { join as join21 } from "path";
|
|
4279
4414
|
var STATUSES = {
|
|
4280
4415
|
adr: ["Proposed", "Accepted", "Rejected", "Superseded"],
|
|
4281
4416
|
specs: [
|
|
@@ -4294,7 +4429,7 @@ async function checkContract(rnessDir) {
|
|
|
4294
4429
|
const problems = [];
|
|
4295
4430
|
for (const name of COLLECTIONS) {
|
|
4296
4431
|
const allowed = STATUSES[name];
|
|
4297
|
-
const items = await collectMarkdown(
|
|
4432
|
+
const items = await collectMarkdown(join21(rnessDir, name));
|
|
4298
4433
|
for (const item of items) {
|
|
4299
4434
|
const where = `${name}/${item.rel}`;
|
|
4300
4435
|
if (SKIP.has(where)) continue;
|
|
@@ -4330,11 +4465,39 @@ async function checkContract(rnessDir) {
|
|
|
4330
4465
|
return problems;
|
|
4331
4466
|
}
|
|
4332
4467
|
|
|
4468
|
+
// src/commands/logout.ts
|
|
4469
|
+
async function logoutCommand() {
|
|
4470
|
+
try {
|
|
4471
|
+
const stored = await readAuth();
|
|
4472
|
+
await clearAuth();
|
|
4473
|
+
const undone = await removeGitSetup().catch(() => false);
|
|
4474
|
+
if (stored === null && !undone) {
|
|
4475
|
+
process.stdout.write("not logged in\n");
|
|
4476
|
+
return 0;
|
|
4477
|
+
}
|
|
4478
|
+
if (stored !== null)
|
|
4479
|
+
process.stdout.write(
|
|
4480
|
+
`${status("logged out", `${stored.login} (github.com)`)}
|
|
4481
|
+
`
|
|
4482
|
+
);
|
|
4483
|
+
if (undone)
|
|
4484
|
+
process.stdout.write(
|
|
4485
|
+
`${status("updated", "git: rness no longer answers for https://github.com")}
|
|
4486
|
+
`
|
|
4487
|
+
);
|
|
4488
|
+
process.stdout.write(`revoke rness on GitHub: ${revokeUrl()}
|
|
4489
|
+
`);
|
|
4490
|
+
return 0;
|
|
4491
|
+
} catch (e) {
|
|
4492
|
+
return reportError(e);
|
|
4493
|
+
}
|
|
4494
|
+
}
|
|
4495
|
+
|
|
4333
4496
|
// src/commands/upgrade.ts
|
|
4334
4497
|
import { execFile as execFile6 } from "child_process";
|
|
4335
4498
|
import { mkdtemp as mkdtemp3, readFile as readFile9, rm as rm7 } from "fs/promises";
|
|
4336
4499
|
import { tmpdir as tmpdir3 } from "os";
|
|
4337
|
-
import { basename as basename5, join as
|
|
4500
|
+
import { basename as basename5, join as join22, relative as relative5 } from "path";
|
|
4338
4501
|
import { promisify as promisify6 } from "util";
|
|
4339
4502
|
var execFileP6 = promisify6(execFile6);
|
|
4340
4503
|
var NOTES = "https://github.com/rness-dev/rness/tree/main/packages/cli#readme";
|
|
@@ -4354,10 +4517,10 @@ async function latestVersion() {
|
|
|
4354
4517
|
async function scaffoldFor(version, rnessDir) {
|
|
4355
4518
|
if (version === VERSION) return { dir: scaffoldDir() };
|
|
4356
4519
|
const installed = await readPinnedCli(rnessDir);
|
|
4357
|
-
const
|
|
4358
|
-
if (installed?.version === version &&
|
|
4359
|
-
return { dir:
|
|
4360
|
-
const scratch = await mkdtemp3(
|
|
4520
|
+
const inside2 = installed === null ? null : join22(installed.dir, "scaffold");
|
|
4521
|
+
if (installed?.version === version && inside2 !== null && await exists(join22(inside2, "package.json")))
|
|
4522
|
+
return { dir: inside2 };
|
|
4523
|
+
const scratch = await mkdtemp3(join22(tmpdir3(), "rness-pack-"));
|
|
4361
4524
|
const cleanup = () => rm7(scratch, { recursive: true, force: true });
|
|
4362
4525
|
try {
|
|
4363
4526
|
const { stdout } = await execFileP6(
|
|
@@ -4372,8 +4535,8 @@ async function scaffoldFor(version, rnessDir) {
|
|
|
4372
4535
|
{ timeout: 6e4 }
|
|
4373
4536
|
);
|
|
4374
4537
|
const tarball = stdout.trim().split("\n").at(-1) ?? "";
|
|
4375
|
-
await execFileP6("tar", ["-xzf",
|
|
4376
|
-
return { dir:
|
|
4538
|
+
await execFileP6("tar", ["-xzf", join22(scratch, tarball), "-C", scratch]);
|
|
4539
|
+
return { dir: join22(scratch, "package", "scaffold"), cleanup };
|
|
4377
4540
|
} catch (e) {
|
|
4378
4541
|
await cleanup();
|
|
4379
4542
|
throw new Error(
|
|
@@ -4385,7 +4548,7 @@ async function scaffoldFor(version, rnessDir) {
|
|
|
4385
4548
|
async function declaredManager(rnessDir, pm) {
|
|
4386
4549
|
try {
|
|
4387
4550
|
const pkg = JSON.parse(
|
|
4388
|
-
await readFile9(
|
|
4551
|
+
await readFile9(join22(rnessDir, "package.json"), "utf8")
|
|
4389
4552
|
);
|
|
4390
4553
|
if (typeof pkg.packageManager === "string") return pkg.packageManager;
|
|
4391
4554
|
} catch {
|
|
@@ -4396,7 +4559,7 @@ async function clonesToCommit(root, cwd, manifest) {
|
|
|
4396
4559
|
const files = writtenFiles(manifest);
|
|
4397
4560
|
const clones = [];
|
|
4398
4561
|
for (const repo of Object.keys(manifest.repos)) {
|
|
4399
|
-
const dir =
|
|
4562
|
+
const dir = join22(root, "org", repo);
|
|
4400
4563
|
if (!await exists(dir)) continue;
|
|
4401
4564
|
try {
|
|
4402
4565
|
const paths = await changedPaths(dir, files);
|
|
@@ -4409,14 +4572,14 @@ async function clonesToCommit(root, cwd, manifest) {
|
|
|
4409
4572
|
}
|
|
4410
4573
|
function finish(ui, cwd, rnessDir, label, target, ending) {
|
|
4411
4574
|
const rel = relative5(cwd, rnessDir) || ".";
|
|
4412
|
-
const
|
|
4575
|
+
const message2 = `chore: rness ${target}`;
|
|
4413
4576
|
const next = [];
|
|
4414
4577
|
if (ending.commit === "committed") next.push(`git -C ${rel} push`);
|
|
4415
4578
|
if (ending.commit === "refused")
|
|
4416
|
-
next.push(`git -C ${rel} commit -m "${
|
|
4579
|
+
next.push(`git -C ${rel} commit -m "${message2}"`);
|
|
4417
4580
|
for (const c of ending.clones)
|
|
4418
4581
|
next.push(
|
|
4419
|
-
`git -C ${c.dir} add ${c.paths.join(" ")} && git -C ${c.dir} commit -m "${
|
|
4582
|
+
`git -C ${c.dir} add ${c.paths.join(" ")} && git -C ${c.dir} commit -m "${message2}"`
|
|
4420
4583
|
);
|
|
4421
4584
|
if (ending.commit !== "nothing")
|
|
4422
4585
|
next.push("# teammates: git pull \u2014 the next rness command installs it");
|
|
@@ -4589,7 +4752,7 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
4589
4752
|
await source.cleanup?.();
|
|
4590
4753
|
}
|
|
4591
4754
|
}
|
|
4592
|
-
const packageFile =
|
|
4755
|
+
const packageFile = join22(ws.rnessDir, "package.json");
|
|
4593
4756
|
const restore = /* @__PURE__ */ new Map([
|
|
4594
4757
|
[packageFile, await readFile9(packageFile, "utf8")]
|
|
4595
4758
|
]);
|
|
@@ -4605,8 +4768,8 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
4605
4768
|
() => ["installed", `dependencies with ${pm}`]
|
|
4606
4769
|
);
|
|
4607
4770
|
} catch (e) {
|
|
4608
|
-
const
|
|
4609
|
-
ui.error(
|
|
4771
|
+
const message3 = e instanceof Error ? e.message : String(e);
|
|
4772
|
+
ui.error(message3);
|
|
4610
4773
|
if (!merged) {
|
|
4611
4774
|
for (const [file, text] of restore) await writeFileAtomic(file, text);
|
|
4612
4775
|
ui.hint(
|
|
@@ -4619,7 +4782,7 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
4619
4782
|
`the scaffold merge is still staged; undo it with: git -C ${relative5(cwd, ws.rnessDir) || "."} merge --abort`,
|
|
4620
4783
|
"stderr"
|
|
4621
4784
|
);
|
|
4622
|
-
if (/minimum.?release.?age|NO_MATURE/i.test(
|
|
4785
|
+
if (/minimum.?release.?age|NO_MATURE/i.test(message3))
|
|
4623
4786
|
ui.hint(
|
|
4624
4787
|
"pnpm refuses versions published less than 24 h ago: add '@rness/cli' under minimumReleaseAgeExclude in .rness/pnpm-workspace.yaml",
|
|
4625
4788
|
"stderr"
|
|
@@ -4638,13 +4801,13 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
4638
4801
|
ui.gitIsSilent = true;
|
|
4639
4802
|
const code = await syncBlocks(ui, ws.root, basename5(ws.root));
|
|
4640
4803
|
if (code !== 0) return code;
|
|
4641
|
-
const
|
|
4642
|
-
const committed = await commitUpgrade(ws.rnessDir,
|
|
4804
|
+
const message2 = `chore: rness ${target}`;
|
|
4805
|
+
const committed = await commitUpgrade(ws.rnessDir, message2);
|
|
4643
4806
|
if (committed.kind === "committed")
|
|
4644
4807
|
ui.line(
|
|
4645
4808
|
"committed",
|
|
4646
|
-
`${label} \u2014 ${
|
|
4647
|
-
`Committed ${label}: ${
|
|
4809
|
+
`${label} \u2014 ${message2}`,
|
|
4810
|
+
`Committed ${label}: ${message2}`
|
|
4648
4811
|
);
|
|
4649
4812
|
if (committed.kind === "refused") {
|
|
4650
4813
|
ui.error(
|
|
@@ -4666,85 +4829,28 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
4666
4829
|
}
|
|
4667
4830
|
}
|
|
4668
4831
|
|
|
4669
|
-
// src/core/
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
const checks = [];
|
|
4679
|
-
const note = (label, status2, message = null) => {
|
|
4680
|
-
checks.push({ label, status: status2, message });
|
|
4681
|
-
};
|
|
4682
|
-
const derive = () => ({
|
|
4683
|
-
problems: checks.filter((c) => PROBLEM.has(c.status) && c.message !== null).map((c) => c.message),
|
|
4684
|
-
warnings: checks.filter((c) => !PROBLEM.has(c.status) && c.message !== null).map((c) => c.message),
|
|
4685
|
-
checks
|
|
4832
|
+
// src/core/check-workspace.ts
|
|
4833
|
+
async function checkWorkspace(ws, manifest) {
|
|
4834
|
+
for (const s of Object.keys(manifest.scopes)) scopeChain(manifest, s);
|
|
4835
|
+
const problems = await checkContract(ws.rnessDir);
|
|
4836
|
+
const blocks = await checkBlocks({
|
|
4837
|
+
root: ws.root,
|
|
4838
|
+
rnessDir: ws.rnessDir,
|
|
4839
|
+
manifest,
|
|
4840
|
+
org: workspaceName(manifest, ws.root)
|
|
4686
4841
|
});
|
|
4687
|
-
|
|
4688
|
-
const
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
scope: name,
|
|
4696
|
-
dir: join22(root, ...segments),
|
|
4697
|
-
depth: segments.length,
|
|
4698
|
-
file: "AGENTS.md",
|
|
4699
|
-
label: `${entry.path}/AGENTS.md`
|
|
4700
|
-
});
|
|
4701
|
-
}
|
|
4702
|
-
for (const t of targets) {
|
|
4703
|
-
if (!await exists(t.dir)) {
|
|
4704
|
-
note(
|
|
4705
|
-
t.label,
|
|
4706
|
-
"missing-dir",
|
|
4707
|
-
`${t.label}: directory not present, block not checked`
|
|
4708
|
-
);
|
|
4709
|
-
continue;
|
|
4710
|
-
}
|
|
4711
|
-
const text = await readOrNull(join22(t.dir, t.file));
|
|
4712
|
-
const lines = text === null ? [] : text.split(/\r?\n/);
|
|
4713
|
-
const found = findBlock(lines);
|
|
4714
|
-
if (found.kind === "none") {
|
|
4715
|
-
note(
|
|
4716
|
-
t.label,
|
|
4717
|
-
"no-block",
|
|
4718
|
-
`${t.label}: no rness block yet (run ${rnessCommand()} sync)`
|
|
4719
|
-
);
|
|
4720
|
-
continue;
|
|
4721
|
-
}
|
|
4722
|
-
if (found.kind === "error") {
|
|
4723
|
-
note(t.label, "malformed", `${t.label}: ${found.message}`);
|
|
4724
|
-
continue;
|
|
4725
|
-
}
|
|
4726
|
-
const context2 = await assembleContext({
|
|
4727
|
-
rnessDir,
|
|
4728
|
-
manifest,
|
|
4729
|
-
scope: t.scope
|
|
4730
|
-
});
|
|
4731
|
-
const fresh2 = renderBlock({
|
|
4732
|
-
scope: t.scope,
|
|
4733
|
-
org,
|
|
4734
|
-
depth: t.depth,
|
|
4735
|
-
context: context2
|
|
4736
|
-
});
|
|
4737
|
-
const pointerLeft = t.file === "CLAUDE.md" && lines.some((l) => l.trim() === "@AGENTS.md");
|
|
4738
|
-
if (isCurrentBlock(lines.slice(found.begin, found.end + 1), fresh2.hash) && !pointerLeft)
|
|
4739
|
-
note(t.label, "current");
|
|
4740
|
-
else
|
|
4741
|
-
note(
|
|
4742
|
-
t.label,
|
|
4743
|
-
"stale",
|
|
4744
|
-
`${t.label}: stale rness block (run ${rnessCommand()} sync)`
|
|
4842
|
+
problems.push(...blocks.problems);
|
|
4843
|
+
for (const name of unsupportedAgents(manifest.agents ?? []))
|
|
4844
|
+
problems.push(unsupportedMessage(name));
|
|
4845
|
+
const targets = await agentTargets(ws.root, manifest, { check: true });
|
|
4846
|
+
for (const o of targets)
|
|
4847
|
+
if (o.status === "stale")
|
|
4848
|
+
problems.push(
|
|
4849
|
+
`${o.label}: ${o.detail ?? ""} (run ${rnessCommand()} sync)`
|
|
4745
4850
|
);
|
|
4746
|
-
|
|
4747
|
-
|
|
4851
|
+
else if (o.status === "invalid")
|
|
4852
|
+
problems.push(`${o.label}: ${o.detail ?? "unreadable"}`);
|
|
4853
|
+
return { problems, blocks, targets };
|
|
4748
4854
|
}
|
|
4749
4855
|
|
|
4750
4856
|
// src/commands/validate.ts
|
|
@@ -4753,26 +4859,8 @@ async function validateCommand(opts, deps = {}) {
|
|
|
4753
4859
|
try {
|
|
4754
4860
|
const ws = await findWorkspace(cwd);
|
|
4755
4861
|
const manifest = await loadManifest(ws.rnessDir);
|
|
4756
|
-
for (const s of Object.keys(manifest.scopes)) scopeChain(manifest, s);
|
|
4757
4862
|
const org = workspaceName(manifest, ws.root);
|
|
4758
|
-
const problems = await
|
|
4759
|
-
const blocks = await checkBlocks({
|
|
4760
|
-
root: ws.root,
|
|
4761
|
-
rnessDir: ws.rnessDir,
|
|
4762
|
-
manifest,
|
|
4763
|
-
org
|
|
4764
|
-
});
|
|
4765
|
-
problems.push(...blocks.problems);
|
|
4766
|
-
for (const name of unsupportedAgents(manifest.agents ?? []))
|
|
4767
|
-
problems.push(unsupportedMessage(name));
|
|
4768
|
-
const targets = await agentTargets(ws.root, manifest, { check: true });
|
|
4769
|
-
for (const o of targets)
|
|
4770
|
-
if (o.status === "stale")
|
|
4771
|
-
problems.push(
|
|
4772
|
-
`${o.label}: ${o.detail ?? ""} (run ${rnessCommand()} sync)`
|
|
4773
|
-
);
|
|
4774
|
-
else if (o.status === "invalid")
|
|
4775
|
-
problems.push(`${o.label}: ${o.detail ?? "unreadable"}`);
|
|
4863
|
+
const { problems, blocks, targets } = await checkWorkspace(ws, manifest);
|
|
4776
4864
|
const scaffoldWarnings = [];
|
|
4777
4865
|
if (await isRepository2(ws.rnessDir) && !await isShallow(ws.rnessDir)) {
|
|
4778
4866
|
const pin = await readPin(ws.rnessDir);
|
|
@@ -4849,134 +4937,9 @@ password=${resolved.token}
|
|
|
4849
4937
|
return 0;
|
|
4850
4938
|
}
|
|
4851
4939
|
|
|
4852
|
-
// src/commands/
|
|
4853
|
-
import {
|
|
4854
|
-
|
|
4855
|
-
// src/mcp/protocol.ts
|
|
4856
|
-
var MODERN_VERSIONS = ["2026-07-28"];
|
|
4857
|
-
var LEGACY_VERSIONS = [
|
|
4858
|
-
"2025-11-25",
|
|
4859
|
-
"2025-06-18",
|
|
4860
|
-
"2025-03-26",
|
|
4861
|
-
"2024-11-05"
|
|
4862
|
-
];
|
|
4863
|
-
var SUPPORTED = [...MODERN_VERSIONS, ...LEGACY_VERSIONS];
|
|
4864
|
-
var VERSION_KEY = "io.modelcontextprotocol/protocolVersion";
|
|
4865
|
-
var CAPABILITIES_KEY = "io.modelcontextprotocol/clientCapabilities";
|
|
4866
|
-
var SERVER_INFO_KEY = "io.modelcontextprotocol/serverInfo";
|
|
4867
|
-
function isObject2(value) {
|
|
4868
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4869
|
-
}
|
|
4870
|
-
function errorLine(id, code, message, data) {
|
|
4871
|
-
return JSON.stringify({
|
|
4872
|
-
jsonrpc: "2.0",
|
|
4873
|
-
id,
|
|
4874
|
-
error: data === void 0 ? { code, message } : { code, message, data }
|
|
4875
|
-
});
|
|
4876
|
-
}
|
|
4877
|
-
function createProtocol(opts) {
|
|
4878
|
-
const serverInfo = { name: opts.name, version: opts.version };
|
|
4879
|
-
return {
|
|
4880
|
-
async handle(line2) {
|
|
4881
|
-
let message;
|
|
4882
|
-
try {
|
|
4883
|
-
message = JSON.parse(line2);
|
|
4884
|
-
} catch {
|
|
4885
|
-
return errorLine(null, -32700, "Parse error");
|
|
4886
|
-
}
|
|
4887
|
-
const rawId = isObject2(message) ? message["id"] : void 0;
|
|
4888
|
-
const id = typeof rawId === "string" || typeof rawId === "number" ? rawId : null;
|
|
4889
|
-
if (!isObject2(message) || message["jsonrpc"] !== "2.0" || typeof message["method"] !== "string")
|
|
4890
|
-
return errorLine(id, -32600, "Invalid Request");
|
|
4891
|
-
if (!("id" in message)) return null;
|
|
4892
|
-
if (id === null) return errorLine(null, -32600, "Invalid Request");
|
|
4893
|
-
const method = message["method"];
|
|
4894
|
-
const params = isObject2(message["params"]) ? message["params"] : {};
|
|
4895
|
-
const meta = isObject2(params["_meta"]) ? params["_meta"] : null;
|
|
4896
|
-
const modern = meta !== null && typeof meta[VERSION_KEY] === "string";
|
|
4897
|
-
if (modern) {
|
|
4898
|
-
const requested = meta[VERSION_KEY];
|
|
4899
|
-
if (!MODERN_VERSIONS.includes(requested))
|
|
4900
|
-
return errorLine(id, -32022, "Unsupported protocol version", {
|
|
4901
|
-
supported: SUPPORTED,
|
|
4902
|
-
requested
|
|
4903
|
-
});
|
|
4904
|
-
if (!isObject2(meta[CAPABILITIES_KEY]))
|
|
4905
|
-
return errorLine(
|
|
4906
|
-
id,
|
|
4907
|
-
-32602,
|
|
4908
|
-
`Invalid params: ${CAPABILITIES_KEY} is required`
|
|
4909
|
-
);
|
|
4910
|
-
}
|
|
4911
|
-
const answer = (result) => JSON.stringify({
|
|
4912
|
-
jsonrpc: "2.0",
|
|
4913
|
-
id,
|
|
4914
|
-
result: modern ? {
|
|
4915
|
-
resultType: "complete",
|
|
4916
|
-
...result,
|
|
4917
|
-
_meta: { [SERVER_INFO_KEY]: serverInfo }
|
|
4918
|
-
} : result
|
|
4919
|
-
});
|
|
4920
|
-
switch (method) {
|
|
4921
|
-
case "server/discover":
|
|
4922
|
-
return answer({
|
|
4923
|
-
supportedVersions: SUPPORTED,
|
|
4924
|
-
capabilities: { tools: {} }
|
|
4925
|
-
});
|
|
4926
|
-
case "initialize": {
|
|
4927
|
-
const asked = params["protocolVersion"];
|
|
4928
|
-
const protocolVersion = typeof asked === "string" && LEGACY_VERSIONS.includes(asked) ? asked : LEGACY_VERSIONS[0];
|
|
4929
|
-
return JSON.stringify({
|
|
4930
|
-
jsonrpc: "2.0",
|
|
4931
|
-
id,
|
|
4932
|
-
result: {
|
|
4933
|
-
protocolVersion,
|
|
4934
|
-
capabilities: { tools: {} },
|
|
4935
|
-
serverInfo
|
|
4936
|
-
}
|
|
4937
|
-
});
|
|
4938
|
-
}
|
|
4939
|
-
case "ping":
|
|
4940
|
-
return answer({});
|
|
4941
|
-
case "tools/list":
|
|
4942
|
-
return answer({
|
|
4943
|
-
tools: opts.tools.map((t) => ({
|
|
4944
|
-
name: t.name,
|
|
4945
|
-
title: t.title,
|
|
4946
|
-
description: t.description,
|
|
4947
|
-
inputSchema: t.inputSchema
|
|
4948
|
-
}))
|
|
4949
|
-
});
|
|
4950
|
-
case "tools/call": {
|
|
4951
|
-
const name = params["name"];
|
|
4952
|
-
const tool = opts.tools.find((t) => t.name === name);
|
|
4953
|
-
if (tool === void 0)
|
|
4954
|
-
return errorLine(id, -32602, `Unknown tool: ${String(name)}`);
|
|
4955
|
-
const args = isObject2(params["arguments"]) ? params["arguments"] : {};
|
|
4956
|
-
try {
|
|
4957
|
-
const r = await tool.call(args);
|
|
4958
|
-
return answer({
|
|
4959
|
-
content: [{ type: "text", text: r.text }],
|
|
4960
|
-
isError: r.isError === true
|
|
4961
|
-
});
|
|
4962
|
-
} catch (e) {
|
|
4963
|
-
return answer({
|
|
4964
|
-
content: [
|
|
4965
|
-
{
|
|
4966
|
-
type: "text",
|
|
4967
|
-
text: `${tool.name} failed: ${e instanceof Error ? e.message : String(e)}`
|
|
4968
|
-
}
|
|
4969
|
-
],
|
|
4970
|
-
isError: true
|
|
4971
|
-
});
|
|
4972
|
-
}
|
|
4973
|
-
}
|
|
4974
|
-
default:
|
|
4975
|
-
return errorLine(id, -32601, "Method not found");
|
|
4976
|
-
}
|
|
4977
|
-
}
|
|
4978
|
-
};
|
|
4979
|
-
}
|
|
4940
|
+
// src/commands/hook.ts
|
|
4941
|
+
import { realpath as realpath4 } from "fs/promises";
|
|
4942
|
+
import { isAbsolute as isAbsolute2, posix as posix5, relative as relative7, resolve as resolve7, sep as sep5 } from "path";
|
|
4980
4943
|
|
|
4981
4944
|
// src/mcp/tools.ts
|
|
4982
4945
|
import { readFile as readFile10, realpath as realpath3, stat as stat4 } from "fs/promises";
|
|
@@ -5057,21 +5020,31 @@ async function context(cwd, args) {
|
|
|
5057
5020
|
manifest,
|
|
5058
5021
|
relative6(ws.root, cwd).split(sep4).join(posix4.sep)
|
|
5059
5022
|
);
|
|
5023
|
+
const summary = await scopeSummary(ws, manifest, scope);
|
|
5024
|
+
return {
|
|
5025
|
+
text: [
|
|
5026
|
+
...summary.lines,
|
|
5027
|
+
"Read one with rness_read; search with rness_search."
|
|
5028
|
+
].join("\n")
|
|
5029
|
+
};
|
|
5030
|
+
}
|
|
5031
|
+
async function scopeSummary(ws, manifest, scope) {
|
|
5060
5032
|
const entry = scope === null ? void 0 : manifest.scopes[scope];
|
|
5061
5033
|
const where = scope === null || entry === void 0 ? "global scope" : `scope ${scope} (${entry.path}${entry.extends.length > 0 ? `, extends ${entry.extends.join(", ")}` : ""})`;
|
|
5062
5034
|
const ctx = await assembleContext({ rnessDir: ws.rnessDir, manifest, scope });
|
|
5063
5035
|
const index = new Map(
|
|
5064
5036
|
(await documents(ws.rnessDir)).map((d) => [d.path, d])
|
|
5065
5037
|
);
|
|
5066
|
-
const
|
|
5038
|
+
const lines = [`Workspace ${workspaceName(manifest, ws.root)} \xB7 ${where}`];
|
|
5039
|
+
const counts = {};
|
|
5067
5040
|
for (const collection of ctx.collections) {
|
|
5068
5041
|
const docs = collection.files.map((f) => index.get(`${collection.name}/${f.rel}`)).filter((d) => d !== void 0);
|
|
5069
5042
|
if (docs.length === 0) continue;
|
|
5070
|
-
|
|
5071
|
-
|
|
5043
|
+
counts[collection.name] = docs.length;
|
|
5044
|
+
lines.push(`${LABELS[collection.name]} (${docs.length}):`);
|
|
5045
|
+
for (const d of docs) lines.push(line(d));
|
|
5072
5046
|
}
|
|
5073
|
-
|
|
5074
|
-
return { text: out.join("\n") };
|
|
5047
|
+
return { where, counts, lines };
|
|
5075
5048
|
}
|
|
5076
5049
|
async function list(cwd, args) {
|
|
5077
5050
|
const { ws } = await workspaceAt(cwd);
|
|
@@ -5232,6 +5205,285 @@ function mcpTools(cwd) {
|
|
|
5232
5205
|
];
|
|
5233
5206
|
}
|
|
5234
5207
|
|
|
5208
|
+
// src/commands/hook.ts
|
|
5209
|
+
var NOUNS = {
|
|
5210
|
+
standards: ["standard", "standards"],
|
|
5211
|
+
adr: ["decision", "decisions"],
|
|
5212
|
+
specs: ["specification", "specifications"],
|
|
5213
|
+
plans: ["plan", "plans"],
|
|
5214
|
+
skills: ["skill", "skills"]
|
|
5215
|
+
};
|
|
5216
|
+
var SHOWN_PROBLEMS = 3;
|
|
5217
|
+
async function readInput(input) {
|
|
5218
|
+
if (input.isTTY === true) return {};
|
|
5219
|
+
let text = "";
|
|
5220
|
+
for await (const chunk of input) text += String(chunk);
|
|
5221
|
+
try {
|
|
5222
|
+
const data = JSON.parse(text);
|
|
5223
|
+
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : {};
|
|
5224
|
+
} catch {
|
|
5225
|
+
return {};
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
var message = (e) => e instanceof Error ? e.message : String(e);
|
|
5229
|
+
function cwdOf(input, env) {
|
|
5230
|
+
const cwd = input["cwd"];
|
|
5231
|
+
if (typeof cwd === "string" && cwd !== "") return cwd;
|
|
5232
|
+
return env["CLAUDE_PROJECT_DIR"] ?? process.cwd();
|
|
5233
|
+
}
|
|
5234
|
+
var toPosix2 = (p) => p.split(sep5).join(posix5.sep);
|
|
5235
|
+
function count(n, [one, many]) {
|
|
5236
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
5237
|
+
}
|
|
5238
|
+
async function safetyNet(ws, manifest) {
|
|
5239
|
+
const notes = [];
|
|
5240
|
+
const drift = await pinDrift(ws.rnessDir);
|
|
5241
|
+
if (drift !== null)
|
|
5242
|
+
notes.push(
|
|
5243
|
+
`.rness pins @rness/cli ${drift.pin} but ${drift.installed ?? "nothing"} is installed \u2014 run ${await workspacePackageManager(ws.rnessDir)} install in .rness`
|
|
5244
|
+
);
|
|
5245
|
+
try {
|
|
5246
|
+
const { problems } = await checkWorkspace(ws, manifest);
|
|
5247
|
+
if (problems.length > 0)
|
|
5248
|
+
notes.push(
|
|
5249
|
+
`${count(problems.length, ["problem", "problems"])} in the workspace context \u2014 run rness validate`,
|
|
5250
|
+
...problems.slice(0, SHOWN_PROBLEMS).map((p) => ` ${p}`)
|
|
5251
|
+
);
|
|
5252
|
+
} catch (e) {
|
|
5253
|
+
notes.push(message(e));
|
|
5254
|
+
}
|
|
5255
|
+
return notes;
|
|
5256
|
+
}
|
|
5257
|
+
async function sessionStart(input, env) {
|
|
5258
|
+
const cwd = cwdOf(input, env);
|
|
5259
|
+
let banner2 = null;
|
|
5260
|
+
let context2 = [];
|
|
5261
|
+
let notes;
|
|
5262
|
+
try {
|
|
5263
|
+
const ws = await findWorkspace(cwd);
|
|
5264
|
+
const manifest = await loadManifest(ws.rnessDir);
|
|
5265
|
+
const scope = resolveScope(manifest, toPosix2(relative7(ws.root, cwd)));
|
|
5266
|
+
const summary = await scopeSummary(ws, manifest, scope);
|
|
5267
|
+
const counts = COLLECTIONS.flatMap((c) => {
|
|
5268
|
+
const n = summary.counts[c];
|
|
5269
|
+
return n === void 0 ? [] : [count(n, NOUNS[c])];
|
|
5270
|
+
});
|
|
5271
|
+
banner2 = `rness ${VERSION} \xB7 ${workspaceName(manifest, ws.root)} \xB7 ${scope === null ? "global scope" : `scope ${scope}`} \u2014 ${counts.length === 0 ? "nothing applies yet" : counts.join(", ")}`;
|
|
5272
|
+
const at = toPosix2(relative7(cwd, ws.rnessDir)) || ".rness";
|
|
5273
|
+
context2 = [
|
|
5274
|
+
...summary.lines,
|
|
5275
|
+
`These documents are in ${at}: read one there, or with rness_read when the rness MCP server is connected.`
|
|
5276
|
+
];
|
|
5277
|
+
notes = await safetyNet(ws, manifest);
|
|
5278
|
+
} catch (e) {
|
|
5279
|
+
notes = [message(e)];
|
|
5280
|
+
}
|
|
5281
|
+
const warnings = notes.map((n) => `rness: ${n}`);
|
|
5282
|
+
const shown = [
|
|
5283
|
+
...banner2 !== null && input["source"] !== "compact" ? [banner2] : [],
|
|
5284
|
+
...warnings
|
|
5285
|
+
];
|
|
5286
|
+
return {
|
|
5287
|
+
...shown.length > 0 ? { systemMessage: shown.join("\n") } : {},
|
|
5288
|
+
hookSpecificOutput: {
|
|
5289
|
+
hookEventName: "SessionStart",
|
|
5290
|
+
additionalContext: [...context2, ...warnings].join("\n")
|
|
5291
|
+
}
|
|
5292
|
+
};
|
|
5293
|
+
}
|
|
5294
|
+
function inside(from, to) {
|
|
5295
|
+
const rel = relative7(from, to);
|
|
5296
|
+
return rel === "" || rel.startsWith("..") || isAbsolute2(rel) ? null : toPosix2(rel);
|
|
5297
|
+
}
|
|
5298
|
+
async function postToolUse(input, io) {
|
|
5299
|
+
const toolInput = input["tool_input"];
|
|
5300
|
+
const path = toolInput !== null && typeof toolInput === "object" ? toolInput["file_path"] : void 0;
|
|
5301
|
+
if (typeof path !== "string" || path === "") return 0;
|
|
5302
|
+
const cwd = cwdOf(input, io.env);
|
|
5303
|
+
let ws;
|
|
5304
|
+
try {
|
|
5305
|
+
ws = await findWorkspace(cwd);
|
|
5306
|
+
} catch {
|
|
5307
|
+
return 0;
|
|
5308
|
+
}
|
|
5309
|
+
const file = resolve7(cwd, path);
|
|
5310
|
+
const rel = inside(ws.rnessDir, file) ?? inside(
|
|
5311
|
+
await realpath4(ws.rnessDir).catch(() => ws.rnessDir),
|
|
5312
|
+
await realpath4(file).catch(() => file)
|
|
5313
|
+
);
|
|
5314
|
+
if (rel === null) return 0;
|
|
5315
|
+
const first = rel.split("/")[0] ?? "";
|
|
5316
|
+
let problems = [];
|
|
5317
|
+
if (rel === "rness.json") {
|
|
5318
|
+
try {
|
|
5319
|
+
const manifest = await loadManifest(ws.rnessDir);
|
|
5320
|
+
for (const s of Object.keys(manifest.scopes)) scopeChain(manifest, s);
|
|
5321
|
+
} catch (e) {
|
|
5322
|
+
problems = [message(e)];
|
|
5323
|
+
}
|
|
5324
|
+
} else if (COLLECTIONS.includes(first) && rel.endsWith(".md"))
|
|
5325
|
+
problems = (await checkContract(ws.rnessDir)).filter(
|
|
5326
|
+
(p) => p.startsWith(`${rel}:`)
|
|
5327
|
+
);
|
|
5328
|
+
if (problems.length === 0) return 0;
|
|
5329
|
+
io.error.write(
|
|
5330
|
+
[
|
|
5331
|
+
...problems.map((p) => `rness: ${p}`),
|
|
5332
|
+
`Fix it in ${rel}; rness validate checks the whole workspace.`,
|
|
5333
|
+
""
|
|
5334
|
+
].join("\n")
|
|
5335
|
+
);
|
|
5336
|
+
return 2;
|
|
5337
|
+
}
|
|
5338
|
+
async function hookCommand(event, io = {
|
|
5339
|
+
input: process.stdin,
|
|
5340
|
+
output: process.stdout,
|
|
5341
|
+
error: process.stderr,
|
|
5342
|
+
env: process.env
|
|
5343
|
+
}) {
|
|
5344
|
+
if (event !== "session-start" && event !== "post-tool-use") {
|
|
5345
|
+
io.error.write(
|
|
5346
|
+
`unknown hook event ${JSON.stringify(event)} (known: session-start, post-tool-use)
|
|
5347
|
+
`
|
|
5348
|
+
);
|
|
5349
|
+
return 1;
|
|
5350
|
+
}
|
|
5351
|
+
const input = await readInput(io.input);
|
|
5352
|
+
if (event === "post-tool-use") return postToolUse(input, io);
|
|
5353
|
+
io.output.write(`${JSON.stringify(await sessionStart(input, io.env))}
|
|
5354
|
+
`);
|
|
5355
|
+
return 0;
|
|
5356
|
+
}
|
|
5357
|
+
|
|
5358
|
+
// src/commands/mcp.ts
|
|
5359
|
+
import { createInterface } from "readline";
|
|
5360
|
+
|
|
5361
|
+
// src/mcp/protocol.ts
|
|
5362
|
+
var MODERN_VERSIONS = ["2026-07-28"];
|
|
5363
|
+
var LEGACY_VERSIONS = [
|
|
5364
|
+
"2025-11-25",
|
|
5365
|
+
"2025-06-18",
|
|
5366
|
+
"2025-03-26",
|
|
5367
|
+
"2024-11-05"
|
|
5368
|
+
];
|
|
5369
|
+
var SUPPORTED = [...MODERN_VERSIONS, ...LEGACY_VERSIONS];
|
|
5370
|
+
var VERSION_KEY = "io.modelcontextprotocol/protocolVersion";
|
|
5371
|
+
var CAPABILITIES_KEY = "io.modelcontextprotocol/clientCapabilities";
|
|
5372
|
+
var SERVER_INFO_KEY = "io.modelcontextprotocol/serverInfo";
|
|
5373
|
+
function isObject2(value) {
|
|
5374
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5375
|
+
}
|
|
5376
|
+
function errorLine(id, code, message2, data) {
|
|
5377
|
+
return JSON.stringify({
|
|
5378
|
+
jsonrpc: "2.0",
|
|
5379
|
+
id,
|
|
5380
|
+
error: data === void 0 ? { code, message: message2 } : { code, message: message2, data }
|
|
5381
|
+
});
|
|
5382
|
+
}
|
|
5383
|
+
function createProtocol(opts) {
|
|
5384
|
+
const serverInfo = { name: opts.name, version: opts.version };
|
|
5385
|
+
return {
|
|
5386
|
+
async handle(line2) {
|
|
5387
|
+
let message2;
|
|
5388
|
+
try {
|
|
5389
|
+
message2 = JSON.parse(line2);
|
|
5390
|
+
} catch {
|
|
5391
|
+
return errorLine(null, -32700, "Parse error");
|
|
5392
|
+
}
|
|
5393
|
+
const rawId = isObject2(message2) ? message2["id"] : void 0;
|
|
5394
|
+
const id = typeof rawId === "string" || typeof rawId === "number" ? rawId : null;
|
|
5395
|
+
if (!isObject2(message2) || message2["jsonrpc"] !== "2.0" || typeof message2["method"] !== "string")
|
|
5396
|
+
return errorLine(id, -32600, "Invalid Request");
|
|
5397
|
+
if (!("id" in message2)) return null;
|
|
5398
|
+
if (id === null) return errorLine(null, -32600, "Invalid Request");
|
|
5399
|
+
const method = message2["method"];
|
|
5400
|
+
const params = isObject2(message2["params"]) ? message2["params"] : {};
|
|
5401
|
+
const meta = isObject2(params["_meta"]) ? params["_meta"] : null;
|
|
5402
|
+
const modern = meta !== null && typeof meta[VERSION_KEY] === "string";
|
|
5403
|
+
if (modern) {
|
|
5404
|
+
const requested = meta[VERSION_KEY];
|
|
5405
|
+
if (!MODERN_VERSIONS.includes(requested))
|
|
5406
|
+
return errorLine(id, -32022, "Unsupported protocol version", {
|
|
5407
|
+
supported: SUPPORTED,
|
|
5408
|
+
requested
|
|
5409
|
+
});
|
|
5410
|
+
if (!isObject2(meta[CAPABILITIES_KEY]))
|
|
5411
|
+
return errorLine(
|
|
5412
|
+
id,
|
|
5413
|
+
-32602,
|
|
5414
|
+
`Invalid params: ${CAPABILITIES_KEY} is required`
|
|
5415
|
+
);
|
|
5416
|
+
}
|
|
5417
|
+
const answer = (result) => JSON.stringify({
|
|
5418
|
+
jsonrpc: "2.0",
|
|
5419
|
+
id,
|
|
5420
|
+
result: modern ? {
|
|
5421
|
+
resultType: "complete",
|
|
5422
|
+
...result,
|
|
5423
|
+
_meta: { [SERVER_INFO_KEY]: serverInfo }
|
|
5424
|
+
} : result
|
|
5425
|
+
});
|
|
5426
|
+
switch (method) {
|
|
5427
|
+
case "server/discover":
|
|
5428
|
+
return answer({
|
|
5429
|
+
supportedVersions: SUPPORTED,
|
|
5430
|
+
capabilities: { tools: {} }
|
|
5431
|
+
});
|
|
5432
|
+
case "initialize": {
|
|
5433
|
+
const asked = params["protocolVersion"];
|
|
5434
|
+
const protocolVersion = typeof asked === "string" && LEGACY_VERSIONS.includes(asked) ? asked : LEGACY_VERSIONS[0];
|
|
5435
|
+
return JSON.stringify({
|
|
5436
|
+
jsonrpc: "2.0",
|
|
5437
|
+
id,
|
|
5438
|
+
result: {
|
|
5439
|
+
protocolVersion,
|
|
5440
|
+
capabilities: { tools: {} },
|
|
5441
|
+
serverInfo
|
|
5442
|
+
}
|
|
5443
|
+
});
|
|
5444
|
+
}
|
|
5445
|
+
case "ping":
|
|
5446
|
+
return answer({});
|
|
5447
|
+
case "tools/list":
|
|
5448
|
+
return answer({
|
|
5449
|
+
tools: opts.tools.map((t) => ({
|
|
5450
|
+
name: t.name,
|
|
5451
|
+
title: t.title,
|
|
5452
|
+
description: t.description,
|
|
5453
|
+
inputSchema: t.inputSchema
|
|
5454
|
+
}))
|
|
5455
|
+
});
|
|
5456
|
+
case "tools/call": {
|
|
5457
|
+
const name = params["name"];
|
|
5458
|
+
const tool = opts.tools.find((t) => t.name === name);
|
|
5459
|
+
if (tool === void 0)
|
|
5460
|
+
return errorLine(id, -32602, `Unknown tool: ${String(name)}`);
|
|
5461
|
+
const args = isObject2(params["arguments"]) ? params["arguments"] : {};
|
|
5462
|
+
try {
|
|
5463
|
+
const r = await tool.call(args);
|
|
5464
|
+
return answer({
|
|
5465
|
+
content: [{ type: "text", text: r.text }],
|
|
5466
|
+
isError: r.isError === true
|
|
5467
|
+
});
|
|
5468
|
+
} catch (e) {
|
|
5469
|
+
return answer({
|
|
5470
|
+
content: [
|
|
5471
|
+
{
|
|
5472
|
+
type: "text",
|
|
5473
|
+
text: `${tool.name} failed: ${e instanceof Error ? e.message : String(e)}`
|
|
5474
|
+
}
|
|
5475
|
+
],
|
|
5476
|
+
isError: true
|
|
5477
|
+
});
|
|
5478
|
+
}
|
|
5479
|
+
}
|
|
5480
|
+
default:
|
|
5481
|
+
return errorLine(id, -32601, "Method not found");
|
|
5482
|
+
}
|
|
5483
|
+
}
|
|
5484
|
+
};
|
|
5485
|
+
}
|
|
5486
|
+
|
|
5235
5487
|
// src/commands/mcp.ts
|
|
5236
5488
|
async function mcpCommand(opts, io = {
|
|
5237
5489
|
input: process.stdin,
|
|
@@ -5321,6 +5573,9 @@ function buildProgram(state) {
|
|
|
5321
5573
|
program.command("git-credential", { hidden: true }).argument("<operation>").action(async (operation) => {
|
|
5322
5574
|
state.code = await gitCredentialCommand(operation);
|
|
5323
5575
|
});
|
|
5576
|
+
program.command("hook", { hidden: true }).argument("<event>", "session-start or post-tool-use").action(async (event) => {
|
|
5577
|
+
state.code = await hookCommand(event);
|
|
5578
|
+
});
|
|
5324
5579
|
program.command("upgrade").alias("update").description(
|
|
5325
5580
|
"Move this workspace to another @rness/cli: pin it in .rness/package.json, install, sync"
|
|
5326
5581
|
).argument("[version]", "an exact version (default: the latest release)").option("-y, --yes", "do not ask for confirmation").addOption(new Option("--cwd <dir>").hideHelp()).action(async (version, opts) => {
|
|
@@ -5398,7 +5653,8 @@ var OWN_COMMANDS = [
|
|
|
5398
5653
|
"update",
|
|
5399
5654
|
"login",
|
|
5400
5655
|
"logout",
|
|
5401
|
-
"git-credential"
|
|
5656
|
+
"git-credential",
|
|
5657
|
+
"hook"
|
|
5402
5658
|
];
|
|
5403
5659
|
var CATCH_UP_DONE = "RNESS_CATCH_UP_DONE";
|
|
5404
5660
|
async function catchUp(argv, deps = {}) {
|
|
@@ -5493,14 +5749,14 @@ export {
|
|
|
5493
5749
|
copyScaffold,
|
|
5494
5750
|
loginCommand,
|
|
5495
5751
|
createCommand,
|
|
5496
|
-
|
|
5752
|
+
checkBlocks,
|
|
5497
5753
|
STATUSES,
|
|
5498
5754
|
checkContract,
|
|
5755
|
+
logoutCommand,
|
|
5499
5756
|
upgradeCommand,
|
|
5500
|
-
checkBlocks,
|
|
5501
5757
|
validateCommand,
|
|
5502
5758
|
run2 as run,
|
|
5503
5759
|
OWN_COMMANDS,
|
|
5504
5760
|
catchUp
|
|
5505
5761
|
};
|
|
5506
|
-
//# sourceMappingURL=chunk-
|
|
5762
|
+
//# sourceMappingURL=chunk-R4BRAAC2.js.map
|