@su-record/vibe 4.2.38 → 4.2.40

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/hooks/notify.js CHANGED
@@ -4,7 +4,8 @@
4
4
  *
5
5
  * post PostToolUse(Edit|Write): runs `vibe state --json` and tells the model about a voided DONE or open inbox items.
6
6
  * pre PreToolUse(Bash): an irreversible command with no recent authorize record is blocked (exit 2) under the
7
- * strict and irreversible token policies, and only warned about under off.
7
+ * strict, irreversible and human token policies, and only warned about under off. Under human the model's
8
+ * own approve, authorize, held-out seal or drop and inbox answer are blocked: those are the person's commands.
8
9
  * Partial Bash reads of protected files are blocked; other source/document slices are warned.
9
10
  * A test command that already passed on unchanged code is blocked or warned about (retest.cjs).
10
11
  * PreToolUse(Read): when the file is over READ_ADVISE_LINES, tells the model that `vibe read <file> --ask`
@@ -103,6 +104,11 @@ const IRREVERSIBLE = [
103
104
  ['apply', /\bterraform\s+apply\b|\bkubectl\s+apply\b/i],
104
105
  ['send', /\b(sendmail|mail\s+-s|curl\s+[^|]*-X\s*POST)\b/],
105
106
  ];
107
+ // Under the `human` token policy approving and authorizing are the person's own commands. Claude Code runs a
108
+ // `! vibe approve` typed in the prompt without calling this hook, so only the model's call reaches it and is stopped.
109
+ const PERSON_ONLY = /(?:^|[\s/])(?:vibe|cli\.js)\s+(?:approve|authorize|heldout\s+(?:seal|drop)|inbox\s+answer)\b/;
110
+ const PREVIEW = /\s--preview\b/;
111
+ const HUMAN_POLICY = 'human';
106
112
  const READS_ONLY = /^\s*(?:grep|rg|cat|head|tail|less|ls|find|wc|echo|printf|sed\s+-n|git\s+(?:log|diff|show|status|grep|blame|branch|ls-files))\b/;
107
113
 
108
114
  const hasProjectDir = () => fs.existsSync(path.join(root, PROJECT_DIR));
@@ -126,15 +132,26 @@ function recentAuthorize(action) {
126
132
 
127
133
  if (!ANYWHERE_MODES.includes(mode) && !hasProjectDir()) process.exit(0);
128
134
 
129
- function irreversibleNotice(action, blocking) {
135
+ function irreversibleNotice(action, policy) {
136
+ const blocking = policy !== 'off';
137
+ const how = policy === HUMAN_POLICY
138
+ ? `ask the user to type \`! vibe authorize --action ${action}\` in the prompt or run it in their terminal,`
139
+ : `get a human token with \`vibe ask --needs authorize:${action}\` and run \`vibe authorize\` first,`;
130
140
  return [
131
141
  `[vibe] "${action}" is irreversible and no authorize record exists in the last ${AUTHORIZE_WINDOW_MS / MS_PER_MINUTE} minutes —`,
132
- `${blocking ? 'blocked: ' : ''}get a human token with \`vibe ask --needs authorize:${action}\``,
133
- 'and run `vibe authorize` first, as its own command: the gate reads the ledger before this command runs,',
142
+ `${blocking ? 'blocked: ' : ''}${how}`,
143
+ 'as its own command: the gate reads the ledger before this command runs,',
134
144
  'so an authorize chained in front of the action is not seen',
135
145
  ].join(' ');
136
146
  }
137
147
 
148
+ function personNotice(segment) {
149
+ return [
150
+ `[vibe] blocked: under tokens: human, \`${segment}\` is the user's own command —`,
151
+ `stop and ask the user to type \`! ${segment}\` in the prompt (Claude Code) or run it in their terminal`,
152
+ ].join(' ');
153
+ }
154
+
138
155
  function tokenPolicy() {
139
156
  try {
140
157
  return JSON.parse(fs.readFileSync(path.join(root, PROJECT_DIR, 'config.json'), 'utf-8')).tokens || 'off';
@@ -212,14 +229,17 @@ if (mode === 'pre') {
212
229
  if (slice.decision === 'warn') notes.push(slice.message);
213
230
  if (!hasProjectDir()) leave(0);
214
231
  // Every segment is judged — `echo x && git push`, `ls; rm -rf build`, `cat x | git push` carry the action in a later one
232
+ const parts = command.split(/&&|\|\||;|\||\n/).map((s) => s.trim()).filter(Boolean);
233
+ const policy = tokenPolicy();
234
+ const ownCommand = policy === HUMAN_POLICY && parts.find((s) => PERSON_ONLY.test(s) && !PREVIEW.test(s));
235
+ if (ownCommand) { process.stderr.write(`${personNotice(ownCommand)}\n`); process.exit(BLOCK_EXIT); }
215
236
  // Vibe gates its own execution; its approval and inbox commands must remain reachable.
216
- const segments = command.split(/&&|\|\||;|\||\n/).map((s) => s.trim()).filter((s) => s && !READS_ONLY.test(s) && !/^vibe(?:\s|$)/.test(s));
217
- // Under strict and irreversible the gate blocks (exit 2 stops the tool call in Claude Code); under off it only warns.
237
+ const segments = parts.filter((s) => !READS_ONLY.test(s) && !/^vibe(?:\s|$)/.test(s));
238
+ // Under strict, irreversible and human the gate blocks (exit 2 stops the tool call in Claude Code); under off it only warns.
218
239
  for (const [action, re] of IRREVERSIBLE) {
219
240
  if (segments.some((s) => re.test(s)) && !recentAuthorize(action)) {
220
- const blocking = tokenPolicy() !== 'off';
221
- process.stderr.write(`${irreversibleNotice(action, blocking)}\n`);
222
- if (blocking) process.exit(BLOCK_EXIT);
241
+ process.stderr.write(`${irreversibleNotice(action, policy)}\n`);
242
+ if (policy !== 'off') process.exit(BLOCK_EXIT);
223
243
  leave(0);
224
244
  }
225
245
  }
@@ -4,7 +4,7 @@ Use when the task needs a missing capability or there is a concrete reason an ex
4
4
 
5
5
  1. Name the operation and expected benefit. Reuse tools, connectors, skill metadata and findings already in context. Follow the environment's tool priority; it does not require rediscovering known capabilities. Use `vibe skill list` or a focused lookup only when the supplied information leaves a relevant gap. Read only the selected skill's instructions. These are sources to choose from, not a mandatory sequence of lookups.
6
6
  2. If the available capability is insufficient or a meaningful improvement is plausible, use `vibe skill search <query>` or `vibe research <query>` with the actual task and constraints. Start with one focused search and inspect a small shortlist. Expand only when a specific unresolved requirement justifies it; stop when a suitable option is found or further search is less useful than direct work. Do not run a periodic scanner or a separate model to choose skills.
7
- 3. Search combines GitHub catalogs with optional SkillsMP discovery. SkillsMP descriptions are unverified hints; inspect the original GitHub skill, not just its catalog page. Inspect the candidate's instructions, executable effects, source/revision, maintenance evidence, dependencies, permissions and failure behavior. A popular name or attractive description is not proof of quality. Check the actual host requirements: Claude/Codex labels alone establish neither compatibility nor incompatibility. Instructions may transfer while client-specific tools, hooks or shell commands need adaptation. Do not claim compatibility before testing the required operation.
7
+ 3. Search reads the skill index first: every skill of the default catalogs, spread over domains (design, video, diagrams, documents, marketing, research, web data, backend, mobile, workspace, security), matched by name and description. Each candidate says how Claude and Codex can use it — install as is, adjust a few host-specific lines, or convert — and what it needs (scripts, an MCP server); that line is an automatic reading of the text, not a test. `vibe skill index` builds or refreshes the index. Prefer a skill that produces the requested result over one that coaches the working method. Search also combines GitHub catalogs with optional SkillsMP discovery. SkillsMP descriptions are unverified hints; inspect the original GitHub skill, not just its catalog page. Inspect the candidate's instructions, executable effects, source/revision, maintenance evidence, dependencies, permissions and failure behavior. A popular name or attractive description is not proof of quality. Check the actual host requirements: Claude/Codex labels alone establish neither compatibility nor incompatibility. Instructions may transfer while client-specific tools, hooks or shell commands need adaptation. Do not claim compatibility before testing the required operation.
8
8
  4. For an evaluation-only request, stop with a supported recommendation and explicit unknowns; installation and execution verification below apply when adoption or use is requested. Reuse an installed skill when it fits. For an external candidate, use the existing installation path, including `vibe skill add owner/repo[@name] --pin <revision>` where supported. Honor existing installation authority; if new authority is necessary, prepare the exact candidate, revision, effects and target before asking once. Preserve existing user files and register project skills internally rather than adding public Vibe commands. Search permission is not permission for unrelated external effects.
9
9
  5. Verify the relevant operation on representative local input and important failure cases. Check that it stays within the requested scope; successful installation is not successful task execution. Reuse trustworthy evidence for the same revision and environment, and recheck affected behavior when they change. Do not run paid generation or external mutations merely as a probe. Separate a plausible benefit from a measured improvement, counting setup and extra model calls when comparing cost.
10
10
  6. If no candidate fits, solve one-off work directly. Create or adapt a skill only when the procedure is worth reusing: `vibe skill create <name> --check run|file|http|eval` is a starting point, not a finished capability. Do not build a new plugin manager or capability registry to complete a single task.
@@ -58,8 +58,8 @@ Paths are project-relative regular files, with no traversal or symlinks, outside
58
58
 
59
59
  ## Select and resume without repeating work
60
60
 
61
- For an existing tracked task, use `vibe internal verification [ids] [--all] --json` when deciding what to run or resuming after interruption. It shares the executor's selection rules and reads current evidence without checking, reserving a run or changing state. Read its blockers before using any reusable result. Default `vibe check` runs checks without a fresh pass; explicit ids rerun those checks and include prerequisites without a fresh pass; `--all` explicitly reruns everything. Checks outside an explicit selection remain required for completion. A preview is not execution permission or a DONE verdict; execution revalidates the contract, consent and risks.
61
+ For an existing tracked task, use `vibe internal verification [ids] [--all] --json` when deciding what to run or resuming after interruption. It shares the executor's selection rules and reads current evidence without checking, reserving a run or changing state. Read its blockers before using any reusable result. Default `vibe check` runs checks without a fresh pass; explicit ids rerun those checks and include prerequisites without a fresh pass; `--all` runs every check whose inputs changed and reuses the rest; `--fresh` reruns everything. Checks outside an explicit selection remain required for completion. A preview is not execution permission or a DONE verdict; execution revalidates the contract, consent and risks.
62
62
 
63
- Keep existing repository-required gates. During development, select the smallest meaningful check that covers the change; before integration, satisfy required broader checks. Reuse evidence only within its known inputs and environment. Vibe currently invalidates passes conservatively when the source tree changes; do not infer narrower dependency coverage from filenames alone. Remote service state, environment changes and undeclared ignored inputs are not fingerprinted by that rule: explicitly rerun affected checks. Do not add an automatic full-suite run to Stop or every edit.
63
+ Keep existing repository-required gates. During development, select the smallest meaningful check that covers the change; before integration, satisfy required broader checks. Reuse evidence only within its known inputs and environment. Give every run or eval scenario `inputs:` — the files and directories its check reads (sources, tests, fixtures, lockfiles); the imports of declared sources are followed. A pass is reused while they are unchanged; without them any edit in the tree reruns the check, and `intent draft` names such scenarios. Leave out generated or build output folders. `verifiers:` holds only files that contain tests (test files, test scripts and fixtures, a source with inline tests): a verifier change needs a new approval, so an application source listed there stops work on every edit. Do not infer narrower dependency coverage from filenames alone. Remote service state, environment changes and undeclared ignored inputs are not fingerprinted by that rule: explicitly rerun affected checks. Do not add an automatic full-suite run to Stop or every edit.
64
64
 
65
65
  On resumption, confirm the saved objective belongs to the current request, inspect reusable evidence and outstanding work, then continue at the first unresolved dependency. The preview marks checks `blocked` when execution blockers exist, retains their prior evidence and requested selection, and names the next action; resolve the blocker before treating a recorded pass as reusable. Check an external job by its saved ID before resubmitting it. If the evidence is missing, stale or cannot establish the target environment's behavior, report that limit instead of repeating completed work merely to reconstruct a narrative.
@@ -39,7 +39,7 @@ Needed before building (if any): {tools · skills · access}
39
39
  To proceed, {paste {token} | say yes}.
40
40
  ```
41
41
 
42
- 7. When the user pastes the number (or says yes when no token was issued), run `vibe approve "{number}" --json` (or `vibe approve --json`). Unanswered material questions or changed evidence need resolution first; never substitute their defaults. On `code 3` show the actual reason and follow it. A material change returns to step 3; an unchanged approval needs no new interview. An old authorization does not cover a new action or target.
42
+ 7. When the user pastes the number (or says yes when no token was issued), run `vibe approve "{number}" --json` (or `vibe approve --json`). Under `tokens: human` the approval is the user's own command: ask them to type `! vibe approve` in the prompt or run it in their terminal, and never run it yourself (the hook blocks it). Unanswered material questions or changed evidence need resolution first; never substitute their defaults. On `code 3` show the actual reason and follow it. A material change returns to step 3; an unchanged approval needs no new interview. An old authorization does not cover a new action or target.
43
43
  8. When the state is APPROVED and any accepted skill is installed, move to `vibe-build`.
44
44
 
45
45
  ## Never
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@su-record/vibe",
3
- "version": "4.2.38",
3
+ "version": "4.2.40",
4
4
  "description": "Your personal FDE in Claude and Codex. Understand the work, use the right tools, deliver and retain useful context. One entry: vibe.",
5
5
  "type": "module",
6
6
  "bin": {