geneseed 3.8.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/DESIGN.md +13 -10
- package/README.md +4 -4
- package/SHIPPED.md +3 -3
- package/adapters/opencode/GLOBAL-HARNESS-SPEC.md +1 -1
- package/adapters/opencode/README.md +3 -3
- package/adapters/opencode/plugins/geneseed-guard.js +9 -9
- package/adapters/opencode/plugins/geneseed-workflow.js +1 -1
- package/adapters/opencode/workflows/_runtime.js +2 -2
- package/adapters/opencode/workflows/dispatch.js +1 -1
- package/docs/extending.md +72 -40
- package/docs/web/harnesses.md +2 -2
- package/docs/web/plugin-guard.md +2 -2
- package/docs/web/rules.md +1 -1
- package/docs/web/themes-author.md +2 -2
- package/docs/web-ui.md +1 -1
- package/harness.config.json +1 -1
- package/js/README.md +4 -3
- package/js/build/render.mjs +6 -3
- package/js/build/source.mjs +105 -1
- package/js/build/stubs.mjs +7 -2
- package/js/cli-table.json +3 -3
- package/js/hosts/hooks.mjs +5 -5
- package/js/hosts/native.mjs +1 -1
- package/js/inspect/checks-authoring.mjs +149 -116
- package/js/inspect/inventory.mjs +1 -2
- package/js/ui/tui.mjs +1 -1
- package/js/web/api.mjs +6 -1
- package/package.json +1 -1
- package/registry.json +7 -0
- package/src/AGENT.md.tmpl +19 -15
- package/src/agents/_template.md +3 -3
- package/src/agents/advocate.md +3 -3
- package/src/agents/architect.md +3 -3
- package/src/agents/developer.md +4 -4
- package/src/agents/docs.md +3 -3
- package/src/agents/empiricist.md +4 -4
- package/src/agents/explorer.md +4 -4
- package/src/agents/framer.md +3 -3
- package/src/agents/historian.md +3 -3
- package/src/agents/operator.md +3 -3
- package/src/agents/pragmatist.md +3 -3
- package/src/agents/researcher.md +7 -7
- package/src/agents/reviewer.md +3 -3
- package/src/agents/security.md +3 -3
- package/src/agents/skeptic.md +3 -3
- package/src/agents/steward.md +3 -3
- package/src/agents/tester.md +3 -3
- package/src/agents/user-advocate.md +3 -3
- package/src/agents/visionary.md +3 -3
- package/src/doctrines/README.md +4 -3
- package/src/doctrines/comms.md +4 -4
- package/src/doctrines/craft.md +20 -20
- package/src/doctrines/ops.md +19 -19
- package/src/doctrines/process.md +20 -20
- package/src/doctrines/rigor.md +22 -22
- package/src/laws/universal.md +23 -44
- package/src/memory/README.md +3 -3
- package/src/modes/foreman.md +1 -1
- package/src/notebook/README.md +1 -1
- package/src/ontology/universal.md +7 -9
- package/src/postures/artisan.md +2 -2
- package/src/skills/_self-improvement.md +4 -4
- package/src/skills/_template.md +1 -1
- package/src/skills/brainstorm.md +3 -3
- package/src/skills/bruno-collection-generator.md +6 -6
- package/src/skills/bruno-test-writer.md +5 -5
- package/src/skills/ci-fix.md +4 -4
- package/src/skills/commit.md +11 -10
- package/src/skills/consolidate-memory.md +4 -4
- package/src/skills/council.md +2 -2
- package/src/skills/debug.md +4 -4
- package/src/skills/deps-audit.md +3 -3
- package/src/skills/develop.md +7 -7
- package/src/skills/document-project.md +6 -6
- package/src/skills/explain-changes/SKILL.md +69 -0
- package/src/skills/explain-changes/VENDOR.md +20 -0
- package/src/skills/explain-changes/scripts/render_changes.mjs +558 -0
- package/src/skills/forge-mcp.md +4 -4
- package/src/skills/fresh-eyes.md +4 -4
- package/src/skills/frontend-design.md +1 -1
- package/src/skills/geneseed.md +3 -3
- package/src/skills/git-archaeology.md +5 -5
- package/src/skills/git-rescue.md +7 -7
- package/src/skills/handoff.md +3 -3
- package/src/skills/ingest.md +5 -5
- package/src/skills/migrate.md +8 -8
- package/src/skills/parallel-agents.md +2 -2
- package/src/skills/pipeline.md +2 -2
- package/src/skills/plan.md +3 -3
- package/src/skills/ponytail.md +2 -2
- package/src/skills/profile.md +2 -2
- package/src/skills/prose.md +1 -1
- package/src/skills/prototype.md +1 -1
- package/src/skills/refactor.md +3 -3
- package/src/skills/release.md +5 -5
- package/src/skills/repo-map.md +4 -4
- package/src/skills/research.md +9 -9
- package/src/skills/review-response.md +4 -4
- package/src/skills/rule.md +3 -3
- package/src/skills/security-audit.md +5 -5
- package/src/skills/ship.md +5 -5
- package/src/skills/skill-forge.md +4 -4
- package/src/skills/wiki.md +5 -5
- package/src/skills/workflow.md +2 -3
- package/src/skills/worktree.md +4 -4
- package/themes/_TEMPLATE.json +37 -39
- package/themes/biker.json +37 -39
- package/themes/commentator.json +37 -39
- package/themes/cyberpunk.json +37 -39
- package/themes/gamer.json +37 -39
- package/themes/imperial.json +37 -39
- package/themes/joker.json +37 -39
- package/themes/marvin.json +37 -39
- package/themes/mean.json +37 -39
- package/themes/military.json +37 -39
- package/themes/neutral.json +37 -39
- package/themes/pirate.json +37 -39
- package/themes/sports.json +37 -39
- package/themes/verstappen.json +37 -39
- package/themes/wizard.json +37 -39
- package/web/dist/assets/Activity-DAzV-qQj.js +1 -0
- package/web/dist/assets/ActivityDetail-CwEwMtKl.js +1 -0
- package/web/dist/assets/Dashboard-C2ELBW-X.js +2 -0
- package/web/dist/assets/{Docs-DrJNDPwI.js → Docs-iZrvQP8J.js} +2 -2
- package/web/dist/assets/FilterInput-CVyqmYWM.js +1 -0
- package/web/dist/assets/GreenhouseView-Bq1QmaGO.js +2 -0
- package/web/dist/assets/Installs-BiqR8xdO.js +2 -0
- package/web/dist/assets/JournalView-6wilG5Zd.js +1 -0
- package/web/dist/assets/Laws-D8YXD_XE.js +3 -0
- package/web/dist/assets/Library-DwuTZ2-L.js +1 -0
- package/web/dist/assets/{Markdown-BQAvN8xx.js → Markdown-CkFyfgNf.js} +14 -14
- package/web/dist/assets/OperatorHudView-B-HVBqfY.js +2 -0
- package/web/dist/assets/Personal-BbUTmZQR.js +1 -0
- package/web/dist/assets/Tabs-_pjUFIEI.js +1 -0
- package/web/dist/assets/drawable-CoIulEH2.js +1 -0
- package/web/dist/assets/geist-mono-latin-400-normal-DTRLJnHl.woff2 +0 -0
- package/web/dist/assets/geist-mono-latin-500-normal-YINYabwD.woff2 +0 -0
- package/web/dist/assets/index-BMwSp8BP.js +2 -0
- package/web/dist/assets/index-CDPDk2vj.css +1 -0
- package/web/dist/assets/{react-DbkvxWG5.js → react-B9Z_tXRV.js} +1 -1
- package/web/dist/assets/sections-GalMS0Zv.js +1 -0
- package/web/dist/assets/usePoll-O0sJEw1Y.js +1 -0
- package/web/dist/index.html +4 -4
- package/web/src/pages/Laws.jsx +616 -361
- package/web/dist/assets/Activity-CH-7cPIM.js +0 -1
- package/web/dist/assets/ActivityDetail-DZvz0xS5.js +0 -1
- package/web/dist/assets/CatalogRow-DftXpZHY.js +0 -1
- package/web/dist/assets/Diff-DvwdG0L9.js +0 -2
- package/web/dist/assets/Doctor-OTmwmYZg.js +0 -1
- package/web/dist/assets/FilterInput-BakJLvaV.js +0 -1
- package/web/dist/assets/GreenhouseView-XxrAdriX.js +0 -2
- package/web/dist/assets/Harness-C_LYNk5c.js +0 -1
- package/web/dist/assets/JournalView-BcuyeEaR.js +0 -1
- package/web/dist/assets/Laws-CWHrTKY4.js +0 -3
- package/web/dist/assets/Library-CA9IHghn.js +0 -1
- package/web/dist/assets/OperatorHudView-BMRY1Tt4.js +0 -2
- package/web/dist/assets/Profile-wceET1JY.js +0 -1
- package/web/dist/assets/Rules-BEXvY4Tx.js +0 -1
- package/web/dist/assets/Settings-DS2zF0Ez.js +0 -1
- package/web/dist/assets/Skills-DahlOJuI.js +0 -1
- package/web/dist/assets/StatusBadge-Cg6j-NJL.js +0 -1
- package/web/dist/assets/activity-iWaWVtsR.js +0 -1
- package/web/dist/assets/audiowide-latin-400-normal-6GFCX7ni.woff2 +0 -0
- package/web/dist/assets/drawable-BTHjTzF7.js +0 -1
- package/web/dist/assets/geist-mono-latin-400-normal-DKaoCDn5.woff2 +0 -0
- package/web/dist/assets/geist-mono-latin-500-normal-C3sF8Y1B.woff2 +0 -0
- package/web/dist/assets/geist-mono-latin-600-normal-BHzjB6_C.woff2 +0 -0
- package/web/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/web/dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/web/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
- package/web/dist/assets/ibm-plex-serif-latin-400-normal-BIGslYFI.woff2 +0 -0
- package/web/dist/assets/ibm-plex-serif-latin-500-normal-REKAfBVG.woff2 +0 -0
- package/web/dist/assets/ibm-plex-serif-latin-600-normal-DAxitmSu.woff2 +0 -0
- package/web/dist/assets/index-AN5Emnrg.js +0 -2
- package/web/dist/assets/index-Ruh93A3A.css +0 -1
- package/web/dist/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
- package/web/dist/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
- package/web/dist/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
- package/web/dist/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
- package/web/dist/assets/lawCats-Btjp3Hk_.js +0 -1
- package/web/dist/assets/oswald-latin-400-normal-BAFo8sP8.woff2 +0 -0
- package/web/dist/assets/oswald-latin-500-normal-B-eyT0Dw.woff2 +0 -0
- package/web/dist/assets/oswald-latin-600-normal-plFmSr5g.woff2 +0 -0
- package/web/dist/assets/oswald-latin-700-normal-vy6hmKSr.woff2 +0 -0
- package/web/dist/assets/poppins-latin-400-normal-cpxAROuN.woff2 +0 -0
- package/web/dist/assets/poppins-latin-500-normal-C8OXljZJ.woff2 +0 -0
- package/web/dist/assets/poppins-latin-600-normal-zEkxB9Mr.woff2 +0 -0
- package/web/dist/assets/poppins-latin-700-normal-Qrb0O0WB.woff2 +0 -0
- package/web/dist/assets/rolldown-runtime-CbXtAM7H.js +0 -1
package/js/build/render.mjs
CHANGED
|
@@ -34,7 +34,7 @@ import { readText } from '../lib/fs.mjs';
|
|
|
34
34
|
import { parseJson } from '../lib/json.mjs';
|
|
35
35
|
import { normcase, comparePaths } from '../lib/paths.mjs';
|
|
36
36
|
// `js/build/source.mjs` imports nothing but node builtins, so this direction cannot cycle.
|
|
37
|
-
import { PACK_ORDER, readPackText } from './source.mjs';
|
|
37
|
+
import { PACK_ORDER, readPackText, resolveRuleIds } from './source.mjs';
|
|
38
38
|
|
|
39
39
|
/** Document STRUCTURE is theme-INDEPENDENT — mirrors `_build_render.STRUCTURE`. */
|
|
40
40
|
export const STRUCTURE = {
|
|
@@ -216,7 +216,8 @@ function readSource(cfg, p) {
|
|
|
216
216
|
let seen = SRC_TEXT.get(cfg);
|
|
217
217
|
if (!seen) SRC_TEXT.set(cfg, (seen = new Map()));
|
|
218
218
|
let text = seen.get(p);
|
|
219
|
-
|
|
219
|
+
// Rule ids resolve here, once per file, so every stage after sees the addressed form.
|
|
220
|
+
if (text === undefined) seen.set(p, (text = resolveRuleIds(readText(p), cfg.src)));
|
|
220
221
|
return text;
|
|
221
222
|
}
|
|
222
223
|
|
|
@@ -250,7 +251,9 @@ export function renderFile(cfg, filePath, theme, footprint = 'full', lawsPrefix
|
|
|
250
251
|
function registerBody(cfg, theme, dir, selected, fallback) {
|
|
251
252
|
for (const name of [selected, fallback]) {
|
|
252
253
|
const p = path.join(cfg.src, dir, `${name}.md`);
|
|
253
|
-
if (existsSync(p) && statSync(p).isFile())
|
|
254
|
+
if (existsSync(p) && statSync(p).isFile()) {
|
|
255
|
+
return substitute(resolveRuleIds(readText(p), cfg.src), theme).trim();
|
|
256
|
+
}
|
|
254
257
|
}
|
|
255
258
|
return '';
|
|
256
259
|
}
|
package/js/build/source.mjs
CHANGED
|
@@ -37,7 +37,7 @@ import path from 'node:path';
|
|
|
37
37
|
* on raw or folded text, so one behaviour serves both.
|
|
38
38
|
*/
|
|
39
39
|
const _packTexts = new Map();
|
|
40
|
-
export function
|
|
40
|
+
export function readRawText(file) {
|
|
41
41
|
const key = path.resolve(file);
|
|
42
42
|
const mtime = statSync(file).mtimeMs;
|
|
43
43
|
const hit = _packTexts.get(key);
|
|
@@ -47,6 +47,110 @@ export function readPackText(file) {
|
|
|
47
47
|
return text;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* A doctrine pack as the render sees it: ids resolved, so the heading reads
|
|
52
|
+
* `### {{DOCTRINE}} process 5 — {{DOC_CONSENT_BEFORE_PUSH}}` again. Every reader that keys on the
|
|
53
|
+
* `<pack> <n>` address (`knownRuleIds`, the exclusion filter, the survives gate) goes through
|
|
54
|
+
* here and keeps working unchanged — the address is computed, only the source stopped typing it.
|
|
55
|
+
*/
|
|
56
|
+
export function readPackText(file) {
|
|
57
|
+
return resolveRuleIds(readRawText(file), path.dirname(path.dirname(file)));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* STABLE RULE IDS. Every law and doctrine rule is DECLARED by its heading —
|
|
62
|
+
* `### {{LAW:verify-before-asserting}} Verify Before Asserting` — and CITED by its id —
|
|
63
|
+
* `{{LAW:verify-before-asserting}}`. The id is permanent; the number is not stored anywhere. It
|
|
64
|
+
* is the rule's position (Roman in `laws/universal.md`, Arabic within its pack), computed here
|
|
65
|
+
* at render time, so removing or reordering a rule renumbers every heading after it and rewires
|
|
66
|
+
* nothing: no citation ever named the number.
|
|
67
|
+
*
|
|
68
|
+
* WHY CITATIONS RENDER AS THE NAME, NOT THE NUMBER. A citation is the one place a number would
|
|
69
|
+
* leak into text that outlives the build — an agent reads "Law III", writes "Law III" into its
|
|
70
|
+
* memory, and the memory is wrong the day the canon moves. The rendered harness models what it
|
|
71
|
+
* asks of the agent: a rule is cited by its principle, in English, identical in every voice. The
|
|
72
|
+
* number survives only where it is structural — the rule's own heading.
|
|
73
|
+
*
|
|
74
|
+
* Retired ids live in `RETIRED_RULE_IDS` so the doctor can refuse their reuse: an id that meant
|
|
75
|
+
* one thing in someone's notes must never come back meaning another.
|
|
76
|
+
*/
|
|
77
|
+
const DECL_RE = /^### \{\{(LAW|DOCTRINE):([a-z0-9]+(?:-[a-z0-9]+)*)\}\}[ \t]+(\S[^\n]*?)[ \t]*$/gm;
|
|
78
|
+
const CITE_RE = /\{\{(LAW|DOCTRINE):([a-z0-9-]+)\}\}/g;
|
|
79
|
+
export const RULE_ID_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Ids that no longer name a live rule, and must never be declared again. `liveAs` names the one
|
|
83
|
+
* tier that may still declare it — `external-gate` was Law IX before it became a rigor rule, so
|
|
84
|
+
* the doctrine keeps it and `{{LAW:external-gate}}` is refused; `null` means gone for good.
|
|
85
|
+
*/
|
|
86
|
+
export const RETIRED_RULE_IDS = {
|
|
87
|
+
'external-gate': { was: 'Law IX', liveAs: 'DOCTRINE', note: 'moved to the rigor pack' },
|
|
88
|
+
'absence-is-a-claim': { was: 'Law XI', liveAs: null, note: 'folded into verify-before-asserting' },
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const ROMAN = [[1000, 'M'], [900, 'CM'], [500, 'D'], [400, 'CD'], [100, 'C'], [90, 'XC'],
|
|
92
|
+
[50, 'L'], [40, 'XL'], [10, 'X'], [9, 'IX'], [5, 'V'], [4, 'IV'], [1, 'I']];
|
|
93
|
+
export function toRoman(n) {
|
|
94
|
+
let out = '';
|
|
95
|
+
for (const [v, r] of ROMAN) while (n >= v) { out += r; n -= v; }
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** `sealed-secrets` -> `LEX_SEALED_SECRETS`; a doctrine rule's title key is `DOC_<ID>`. */
|
|
100
|
+
export const titleKey = (kind, id) =>
|
|
101
|
+
`${kind === 'LAW' ? 'LEX' : 'DOC'}_${id.toUpperCase().replaceAll('-', '_')}`;
|
|
102
|
+
|
|
103
|
+
/** The files that may declare rules, in canon order: `[kind, pack|null, file]`. */
|
|
104
|
+
export function canonFiles(src = SRC) {
|
|
105
|
+
return [['LAW', null, path.join(src, 'laws', 'universal.md')],
|
|
106
|
+
...PACK_ORDER.map((p) => ['DOCTRINE', p, path.join(src, 'doctrines', `${p}.md`)])];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const _canons = new Map();
|
|
110
|
+
/**
|
|
111
|
+
* Every declared rule, in render order: `{ kind, pack, id, name, n, label }`, where `label` is
|
|
112
|
+
* the address the heading renders (`III`, `process 5`). Memoised on the raw texts' identity —
|
|
113
|
+
* `readRawText` hands back the same string until a file's mtime moves.
|
|
114
|
+
*/
|
|
115
|
+
export function ruleCanon(src = SRC) {
|
|
116
|
+
const files = canonFiles(src);
|
|
117
|
+
const texts = files.map(([, , f]) => { try { return readRawText(f); } catch { return ''; } });
|
|
118
|
+
const key = path.resolve(src);
|
|
119
|
+
const hit = _canons.get(key);
|
|
120
|
+
if (hit && hit.texts.every((t, i) => t === texts[i])) return hit.canon;
|
|
121
|
+
const rules = [];
|
|
122
|
+
files.forEach(([kind, pack], i) => {
|
|
123
|
+
let n = 0;
|
|
124
|
+
for (const m of texts[i].matchAll(DECL_RE)) {
|
|
125
|
+
if (m[1] !== kind) continue; // a wrong-tier declaration is the doctor's to name
|
|
126
|
+
n += 1;
|
|
127
|
+
rules.push({ kind, pack, id: m[2], name: m[3], n, label: kind === 'LAW' ? toRoman(n) : `${pack} ${n}` });
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
const byId = new Map();
|
|
131
|
+
for (const r of rules) if (!byId.has(r.id)) byId.set(r.id, r);
|
|
132
|
+
const canon = { rules, byId };
|
|
133
|
+
_canons.set(key, { texts, canon });
|
|
134
|
+
return canon;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Resolve every declaration and citation in `text` against the canon under `src`. An unknown id
|
|
139
|
+
* is left exactly as written — visible in the output, and named by the doctor — rather than
|
|
140
|
+
* guessed at.
|
|
141
|
+
*/
|
|
142
|
+
export function resolveRuleIds(text, src = SRC) {
|
|
143
|
+
if (!text.includes('{{LAW:') && !text.includes('{{DOCTRINE:')) return text;
|
|
144
|
+
const { byId } = ruleCanon(src);
|
|
145
|
+
const known = (kind, id) => { const r = byId.get(id); return r && r.kind === kind ? r : null; };
|
|
146
|
+
return text
|
|
147
|
+
.replace(DECL_RE, (whole, kind, id) => {
|
|
148
|
+
const r = known(kind, id);
|
|
149
|
+
return r ? `### {{${kind}}} ${r.label} — {{${titleKey(kind, id)}}}` : whole;
|
|
150
|
+
})
|
|
151
|
+
.replace(CITE_RE, (whole, kind, id) => { const r = known(kind, id); return r ? `*${r.name}*` : whole; });
|
|
152
|
+
}
|
|
153
|
+
|
|
50
154
|
/**
|
|
51
155
|
* `_build_core.ROOT` — the checkout, from this file's own location (`js/..`).
|
|
52
156
|
*
|
package/js/build/stubs.mjs
CHANGED
|
@@ -137,8 +137,13 @@ the project's own. Follow the root \`AGENTS.md\`.
|
|
|
137
137
|
/** `_build_render.PROFILE_FILE`. */
|
|
138
138
|
const PROFILE_FILE = 'PROFILE.md';
|
|
139
139
|
|
|
140
|
-
/**
|
|
141
|
-
|
|
140
|
+
/**
|
|
141
|
+
* `_build_render.PROFILE_STUB`.
|
|
142
|
+
*
|
|
143
|
+
* Exported for the web console: `/api/profile` answers `seeded: true` while PROFILE.md is
|
|
144
|
+
* still byte-for-byte this text, which is how the Overview knows to ask for it to be filled in.
|
|
145
|
+
*/
|
|
146
|
+
export const PROFILE_STUB = `\
|
|
142
147
|
# Your profile
|
|
143
148
|
|
|
144
149
|
Who you are and how you like to work — so the agent can meet you where you are
|
package/js/cli-table.json
CHANGED
|
@@ -488,7 +488,7 @@
|
|
|
488
488
|
},
|
|
489
489
|
{
|
|
490
490
|
"name": "git-gate",
|
|
491
|
-
"help": "PreToolUse hook: ASK before a history-discarding git act (
|
|
491
|
+
"help": "PreToolUse hook: ASK before a history-discarding git act (Deletion Is Deliberate) and before every git commit/push (Consent Before Push backstop)",
|
|
492
492
|
"description": "",
|
|
493
493
|
"positionals": [],
|
|
494
494
|
"options": [
|
|
@@ -528,7 +528,7 @@
|
|
|
528
528
|
],
|
|
529
529
|
"dest": "no_consent",
|
|
530
530
|
"metavar": null,
|
|
531
|
-
"help": "skip the
|
|
531
|
+
"help": "skip the Consent Before Push commit/push ask (set by the emit when the process pack or that rule is off); Deletion Is Deliberate still asks",
|
|
532
532
|
"choices": null,
|
|
533
533
|
"default": false,
|
|
534
534
|
"required": false,
|
|
@@ -766,7 +766,7 @@
|
|
|
766
766
|
},
|
|
767
767
|
{
|
|
768
768
|
"name": "rule-gate",
|
|
769
|
-
"help": "PreToolUse hook: force an ASK before any write to user-rules.md or memory (
|
|
769
|
+
"help": "PreToolUse hook: force an ASK before any write to user-rules.md or memory (Persist Insight backstop)",
|
|
770
770
|
"description": "",
|
|
771
771
|
"positionals": [],
|
|
772
772
|
"options": [
|
package/js/hosts/hooks.mjs
CHANGED
|
@@ -700,14 +700,14 @@ function gitDecide(args, payload) {
|
|
|
700
700
|
const command = ((payload && payload.tool_input) || {}).command;
|
|
701
701
|
if (typeof command !== 'string') return 0;
|
|
702
702
|
if (DESTRUCTIVE_GIT_RE.test(command)) {
|
|
703
|
-
return ask(args, 'git-gate', 'law-4', 'Geneseed
|
|
703
|
+
return ask(args, 'git-gate', 'law-4', 'Geneseed (Deletion Is Deliberate) \u2014 a history-rewriting or '
|
|
704
704
|
+ 'discarding git act needs confirmation bound to this specific command');
|
|
705
705
|
}
|
|
706
706
|
// `--no-consent`: the process pack (or process 5 alone) is off, so the commit/push ask has
|
|
707
707
|
// no rule behind it — but Law IV above is universal and has already run.
|
|
708
708
|
if (args.noConsent || !GIT_GATE_RE.test(command)) return 0;
|
|
709
|
-
return ask(args, 'git-gate', 'process-5', 'Geneseed
|
|
710
|
-
+ 'commit/push needs explicit approval');
|
|
709
|
+
return ask(args, 'git-gate', 'process-5', 'Geneseed (Consent Before Push) \u2014 every git '
|
|
710
|
+
+ 'commit/push needs explicit approval; to see the change first, use the explain-changes skill');
|
|
711
711
|
}
|
|
712
712
|
export const cmdGitGate = guardGate(gitGate, 'git-gate');
|
|
713
713
|
|
|
@@ -764,13 +764,13 @@ function ruleDecide(args, payload) {
|
|
|
764
764
|
const body = [ti.content, ti.new_string, ti.file_text, ti.new_str]
|
|
765
765
|
.find((v) => typeof v === 'string') || '';
|
|
766
766
|
if (body && !DOTENV_RE.test(p) && SECRET_RE.test(body)) {
|
|
767
|
-
return ask(args, 'rule-gate', 'law-1', `Geneseed
|
|
767
|
+
return ask(args, 'rule-gate', 'law-1', `Geneseed (Sealed Secrets) — ${p} would carry a `
|
|
768
768
|
+ 'credential-shaped string. Secrets live in .env or a secret manager, never in a '
|
|
769
769
|
+ 'tracked file.');
|
|
770
770
|
}
|
|
771
771
|
const target = ruleGateTarget(p, args.root);
|
|
772
772
|
if (!target) return 0;
|
|
773
|
-
return ask(args, 'rule-gate', 'process-1', `Geneseed
|
|
773
|
+
return ask(args, 'rule-gate', 'process-1', `Geneseed (Persist Insight) \u2014 writing to `
|
|
774
774
|
+ `${target}: a standing rule, or a fact to remember? That choice is the user's. Run the `
|
|
775
775
|
+ 'rule skill first.');
|
|
776
776
|
}
|
package/js/hosts/native.mjs
CHANGED
|
@@ -34,7 +34,7 @@ import { writeText, copyFile, readText } from '../lib/fs.mjs';
|
|
|
34
34
|
import { jsonDumps, parseJson, formatValue, formatRepr, isTruthy, isDict } from '../lib/json.mjs';
|
|
35
35
|
|
|
36
36
|
/** Mirrors `_build_core.VENDORED_SKILL_DIRS`. */
|
|
37
|
-
export const VENDORED_SKILL_DIRS = new Set(['react-view-transitions', 'daydream', 'token-report']);
|
|
37
|
+
export const VENDORED_SKILL_DIRS = new Set(['react-view-transitions', 'daydream', 'token-report', 'explain-changes']);
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* `PurePath(rel).parts` — split on EITHER separator, empties dropped.
|