claude-code-autoconfig 1.0.192 → 1.0.193

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.
@@ -11,6 +11,7 @@
11
11
 
12
12
  Tokens (substituted at runtime):
13
13
  {{TITLE_FILE}} — absolute path to this session's title file the model writes
14
+ {{ASK_FILE}} — absolute path to this session's one-shot {sid}.ask flag (PENDING block)
14
15
  {{FOLDER}} — the working-directory folder name (scope fallback)
15
16
  {{EMDASH}} — the ' — ' segment separator
16
17
  {{CMD}} — the slash-command name (COMMAND block only)
@@ -63,9 +64,14 @@ already exists, read it first then overwrite.
63
64
  <!-- /DIRECTIVE:SHIFT -->
64
65
 
65
66
  <!-- DIRECTIVE:PENDING -->
66
- Pending-question signal: if you END this turn by asking the user a question they must answer
67
- before you can proceed, phrase it so your FINAL line ends with a question mark ('?') -- the tab
68
- indicator then flips to the AWAITING half-circle automatically (instead of the idle asterisk).
67
+ Pending-question signal: when you END this turn on a question the user must answer before you can
68
+ proceed, do BOTH of these as near-final actions so the tab flips to the AWAITING half-circle
69
+ (instead of the idle asterisk):
70
+ 1. Write the flag file {{ASK_FILE}} (any short content, e.g. "1"). This is the RELIABLE trigger --
71
+ it is on disk before the turn ends, so it never misses (the transcript-text check in 2 can race
72
+ the turn-end write and silently miss). The flag is one-shot: it is consumed at turn end and
73
+ auto-cleared next turn, so write it ONLY on a turn you are genuinely blocked on an answer.
74
+ 2. Phrase your FINAL line so it ends with a question mark ('?') -- a backup signal, and good UX.
69
75
  Make the closing question self-contained: answerable from the question alone, without re-reading
70
- the response above it. Only end on a '?' for a genuine blocking question, never a rhetorical one.
76
+ the response above it. Only do this for a genuine blocking question, never a rhetorical one or a recap.
71
77
  <!-- /DIRECTIVE:PENDING -->
@@ -2,7 +2,8 @@
2
2
  /**
3
3
  * Terminal Title — distributable plugin hook (installed to <project>/.claude/hooks/terminal-title.js).
4
4
  * ONE self-dispatching hook for five events (keyed on hook_event_name):
5
- * UserPromptSubmit -> ⬤ working + inject the title directive into the model's context
5
+ * UserPromptSubmit -> ⬤ working + inject the title directive (incl. the {sid}.ask path) +
6
+ * clear any stale {sid}.ask flag so it reflects only the turn about to run
6
7
  * PostToolUse -> ⬤ working (refresh, so a mid-turn title flip shows live + clears a stale ◐)
7
8
  * Notification -> ◐ awaiting your approval (permission_prompt matcher only)
8
9
  * Stop -> ✻ idle / done — OR ◐ awaiting (+ a 2nd BEL = gold tab) when the turn ended
@@ -65,6 +66,10 @@ function handle(data) {
65
66
  // Ensure the state dir exists, but NOT the file — the model's Write tool refuses to overwrite a
66
67
  // file it hasn't read, so a pre-created empty file would make its first title write fail.
67
68
  try { fs.mkdirSync(dir, { recursive: true }); } catch (_) { /* ignore */ }
69
+ // Clear any stale {sid}.ask left by an interrupted prior turn (Stop never ran to consume it), so a
70
+ // leftover flag can't paint a false ◐ on this turn's end. The flag must reflect ONLY this turn.
71
+ const askFile = path.join(dir, `${sid}.ask`);
72
+ if (fileExists(askFile)) { try { fs.unlinkSync(askFile); } catch (_) { /* ignore */ } }
68
73
  const title = normalize(readTitle(file) || folderName(cwd));
69
74
  const out = setTitle(GLYPH.working, title);
70
75
  out.hookSpecificOutput = {
@@ -221,6 +226,7 @@ function buildDirective(data, file, cwd) {
221
226
  const combined = pending ? `${block}\n\n${pending}` : block;
222
227
  return combined
223
228
  .split('{{TITLE_FILE}}').join(file)
229
+ .split('{{ASK_FILE}}').join(file.replace(/\.txt$/, '.ask'))
224
230
  .split('{{FOLDER}}').join(folderName(cwd))
225
231
  .split('{{EMDASH}}').join(EMDASH)
226
232
  .split('{{CMD}}').join(cmd);
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.0.193
4
+ - fix(installer): always refresh cca-managed title hooks on upgrade
5
+ - fix(terminal-title): arm the {sid}.ask flag so awaiting ◐ is race-free
6
+ - docs(publish): document web-auth/passkey publish flow in Discoveries
7
+
3
8
  ## v1.0.192
4
9
  - fix(pkg): exclude runtime .titles/ from published tarball
5
10
 
@@ -142,6 +147,3 @@
142
147
  ## v1.0.144
143
148
  - feat: swagger-style docs, wider layout, better install UX
144
149
 
145
- ## v1.0.143
146
- - feat: add /validate-cca-install command
147
-
package/CLAUDE.md CHANGED
@@ -42,6 +42,18 @@ See `.claude/feedback/` for corrections and guidance from the team.
42
42
  ## Discoveries
43
43
  <!-- Claude: append project-specific learnings, gotchas, and context below. This section persists across /autoconfig runs. -->
44
44
 
45
+ ### Publishing to npm — web-auth (passkey) flow, run by the human
46
+
47
+ `npm publish` for this package is a **two-actor** flow; a bare in-agent `npm publish` will FAIL. (Supersedes the auto-generated "## Publishing" one-liner above.)
48
+
49
+ - The npm account has **2FA**. A sandboxed/agent shell can't open a browser, so `npm publish` there dies with `npm error code EOTP`. Don't retry it in-agent; don't default to asking for a typed OTP.
50
+ - **Working flow:** the agent runs `npm test` + `npm version patch` (commit + tag), then the **human runs the publish in their own terminal** (needs a browser):
51
+ ```
52
+ cd C:\CODE\claude-code-autoconfig && npm login --auth-type=web && npm publish
53
+ ```
54
+ → browser opens → pick the Google passkey → close it → `+ claude-code-autoconfig@<version>`.
55
+ - **After** the success line, the agent pushes: `git push origin main --follow-tags`. Never double-bump if the version is already bumped. Full procedure: `.claude/commands/publish.md`.
56
+
45
57
  ## Debugging Methodology — Evidence Before Solutions
46
58
 
47
59
  **NEVER jump to a fix based on assumptions.** When investigating a bug:
package/bin/cli.js CHANGED
@@ -767,10 +767,21 @@ if (fs.existsSync(feedbackSrc)) {
767
767
  copyFn(feedbackSrc, path.join(claudeDest, 'feedback'));
768
768
  }
769
769
 
770
- // Copy hooks directory (preserve user customizations unless --force)
770
+ // Copy hooks directory. Genuinely user-authorable hooks are preserved on upgrade
771
+ // (copyDirIfMissing), BUT the cca-managed title-hook files are ALWAYS refreshed so bug-fixes
772
+ // reach existing installs — without this, copyDirIfMissing leaves stale hooks in place forever
773
+ // (same always-overwrite rationale as scripts/ below). --force already overwrites everything.
774
+ const MANAGED_HOOKS = ['terminal-title.js', 'terminal-title.directive.md'];
771
775
  if (fs.existsSync(hooksSrc)) {
772
776
  const copyFn = forceMode ? copyDir : copyDirIfMissing;
773
777
  copyFn(hooksSrc, path.join(claudeDest, 'hooks'));
778
+ if (!forceMode) {
779
+ const hooksDestDir = path.join(claudeDest, 'hooks');
780
+ for (const name of MANAGED_HOOKS) {
781
+ const src = path.join(hooksSrc, name);
782
+ if (fs.existsSync(src)) fs.copyFileSync(src, path.join(hooksDestDir, name));
783
+ }
784
+ }
774
785
  }
775
786
 
776
787
  // Copy scripts directory (always overwrite — these are utility scripts, not user-customizable)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-autoconfig",
3
- "version": "1.0.192",
3
+ "version": "1.0.193",
4
4
  "description": "Intelligent, self-configuring setup for Claude Code. One command analyzes your project, configures Claude, and shows you what it did.",
5
5
  "author": "ADAC 1001 <info@adac1001.com>",
6
6
  "license": "MIT",