arcane-cli 0.33.8 → 0.34.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.
|
@@ -136,6 +136,12 @@ See also: [[README]], [[DECISIONS]], [[governance/git-conventions|Git Convention
|
|
|
136
136
|
[[governance/git-conventions#content-verified-branch-deletion-todomd-merged-branch-cleanup-finding|Content-Verified
|
|
137
137
|
Branch Deletion]] already applies to branches specifically.
|
|
138
138
|
|
|
139
|
+
25. **Never quote a denylisted token, even when documenting its removal. Enforcement: explicitly advisory prose (ARC-023) — the org-token gate itself is a CI-only executable check; nothing local catches an agent re-typing the flagged string, which is exactly the failure mode this rule addresses.** A privacy-denylist gate (e.g. `ARCANE_ORG_TOKENS`, ARC-031) can only scan for the literal string it's configured to catch — it cannot tell "quoting a leak to explain the fix" from "the leak itself." Confirmed live: a real client name leaked into shipped content, was fixed, and the commit message describing that fix quoted the same name while narrating its removal — retriggering the identical CI failure minutes later. When describing a leak or its removal, name the class of thing that leaked ("a real client name," "an internal machine name") rather than repeating the flagged string, in commit messages, journals, and any other content a portability gate scans.
|
|
140
|
+
|
|
141
|
+
26. **A zero-match search is evidence about the pattern, not the thing. Enforcement: explicitly advisory prose (ARC-023) — recognizing that a search's own shape (case sensitivity, exact wording, scope) can produce a false negative depends on agent judgment; no check re-runs a prior search with a different shape before a conclusion is accepted.** Concluding "X doesn't exist" or "X is still true" from one grep, one case-sensitive match attempt, or one narrowly-worded query treats the search as if it were exhaustive. Confirmed live: a case-sensitive grep for a lowercase term missed a real match spelled with a capital letter, producing an on-the-record false "still open" conclusion about an item that had, in fact, already shipped. Before stating an absence as fact, run at least one differently-shaped search (case-insensitive, a synonym, a broader scope) and say which searches actually ran, rather than reporting the first search's silence as the answer.
|
|
142
|
+
|
|
143
|
+
27. **Dispatched-agent supervision: review the diff, not the summary. Enforcement: explicitly advisory prose (ARC-023) — no subagent registry or diff-review gate ships in this repo; supervising a dispatched agent's actual output, rather than trusting its self-report, depends on the dispatching agent's own judgment.** A dispatched agent's summary describes what it intended to do, not necessarily what it did — verify by reading its actual changes before reporting the work as complete. When multiple agents edit concurrently, assign at most one agent per file to avoid silently-overwritten or merge-conflicting work. A dispatched agent may override an instruction it was given after independently verifying that instruction is wrong for the situation at hand — but it must say so explicitly on the record, not silently substitute its own judgment.
|
|
144
|
+
|
|
139
145
|
---
|
|
140
146
|
|
|
141
147
|
## Client-Specific Instruction Locations
|
package/dist/index.js
CHANGED
|
@@ -4817,6 +4817,9 @@ async function runDoctor(targetDir, options = {}, assetsDir) {
|
|
|
4817
4817
|
}
|
|
4818
4818
|
}
|
|
4819
4819
|
|
|
4820
|
+
// src/commands/ward.ts
|
|
4821
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
4822
|
+
|
|
4820
4823
|
// src/modules/ward.ts
|
|
4821
4824
|
import { readdir as readdir6, readFile as readFile10 } from "fs/promises";
|
|
4822
4825
|
import { join as join13, relative as relative2 } from "path";
|
|
@@ -4942,8 +4945,24 @@ function parseTerms(raw) {
|
|
|
4942
4945
|
if (!raw) return [];
|
|
4943
4946
|
return raw.split(",").map((t) => t.trim()).filter(Boolean);
|
|
4944
4947
|
}
|
|
4948
|
+
function parseTermsFileContent(raw) {
|
|
4949
|
+
return raw.split(/[,\r\n]+/).map((t) => t.trim()).filter(Boolean);
|
|
4950
|
+
}
|
|
4951
|
+
async function readTermsFile(filePath) {
|
|
4952
|
+
try {
|
|
4953
|
+
return parseTermsFileContent(await readFile11(filePath, "utf8"));
|
|
4954
|
+
} catch (error) {
|
|
4955
|
+
console.warn(
|
|
4956
|
+
`\u26A0 arcane: could not read --terms-file "${filePath}": ${error.message}`
|
|
4957
|
+
);
|
|
4958
|
+
return [];
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4945
4961
|
async function runWardCli(targetDir, options = {}, exclusions = []) {
|
|
4946
|
-
const terms =
|
|
4962
|
+
const terms = [
|
|
4963
|
+
...parseTerms(options.terms),
|
|
4964
|
+
...options.termsFile ? await readTermsFile(options.termsFile) : []
|
|
4965
|
+
];
|
|
4947
4966
|
const report = await runWard(targetDir, { terms, exclusions });
|
|
4948
4967
|
console.log("\nspell ward \u2014 scanning for leaked identifiers\n");
|
|
4949
4968
|
const leaks = report.findings.filter((f) => f.category === "leak");
|
|
@@ -5154,6 +5173,9 @@ program.command("doctor").description("Check your environment for Arcane prerequ
|
|
|
5154
5173
|
program.command("ward").description("Scan the repo for leaked identifiers -- third-party trademarks and the operator's own personal identifiers alike (T18)").option(
|
|
5155
5174
|
"--terms <terms>",
|
|
5156
5175
|
"Comma-separated denylist terms, in addition to the built-in vendor-identifier list. Seed this from your OWN identity too, not just org/venture names -- usernames, machine names, and personal handles leak the same way a private venture name does (I1)"
|
|
5176
|
+
).option(
|
|
5177
|
+
"--terms-file <path>",
|
|
5178
|
+
"Read denylist terms from a file instead of --terms, to avoid shell-history exposure (ARC-041). Same comma/newline-separated format as ARCANE_ORG_TOKENS."
|
|
5157
5179
|
).option("--gate", "Exit non-zero if any leak is found (for CI)").action(async (opts) => {
|
|
5158
5180
|
await runWardCli(process.cwd(), opts);
|
|
5159
5181
|
});
|