devcoach 0.4.3 → 0.6.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 CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=UltimaPhoenix_dev-coach&metric=coverage)](https://sonarcloud.io/summary/new_code?id=UltimaPhoenix_dev-coach)
7
7
  [![Node](https://img.shields.io/badge/node-%E2%89%A524-brightgreen?logo=node.js)](https://nodejs.org/)
8
8
  [![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-purple)](https://ultimaphoenix.github.io/dev-coach/)
9
- [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
9
+ [![License](https://img.shields.io/badge/license-AGPL%203.0-blue)](LICENSE)
10
10
 
11
11
  **Stay sharp while your AI does the work.**
12
12
 
@@ -512,8 +512,27 @@ CI lints, type-checks, tests (Node 24 & 26), builds, and publishes to npm via **
512
512
 
513
513
  ## License
514
514
 
515
- Copyright 2026 [UltimaPhoenix](https://github.com/UltimaPhoenix)
515
+ Copyright (C) 2026 [UltimaPhoenix](https://github.com/UltimaPhoenix)
516
516
 
517
- Licensed under the [Apache License, Version 2.0](LICENSE). Free to use, modify, and distribute;
518
- commercial use and modifications must retain the license, copyright, and attribution notices and state
519
- any changes. You may not use the `devcoach` name or branding to endorse derived products without permission.
517
+ devcoach is licensed under the [GNU Affero General Public License v3.0](LICENSE) (`AGPL-3.0-only`).
518
+ You may use, modify, and distribute it — **provided that any modified version you distribute, or run
519
+ as a network service, is also released as open source under the AGPL**. A separate **commercial
520
+ license** is available for proprietary/closed use without AGPL's copyleft obligations —
521
+ [open an issue](https://github.com/UltimaPhoenix/dev-coach/issues) to enquire.
522
+
523
+ ### Licensing FAQ
524
+
525
+ > **devcoach is and stays 100% free** to download, install, and use — for everyone, forever, including
526
+ > at work and on commercial projects. AGPL is *not* a price tag: you only ever pay if you want to ship
527
+ > a **proprietary/closed derivative of devcoach itself** without complying with the AGPL.
528
+
529
+ **Using devcoach does not put your code under the AGPL.** It runs as a separate process over
530
+ stdio/MCP (`npx -y devcoach mcp`); talking to it at arm's length is not a derivative work — exactly
531
+ like querying an AGPL-licensed database. Your own projects keep whatever license you choose.
532
+
533
+ - ✅ *"I use devcoach inside Claude Code while building my closed-source startup app."* — Free. Your app stays proprietary, zero obligations.
534
+ - ✅ *"My whole team installs devcoach to get coaching on our internal/commercial repos."* — Free. Using the unmodified tool at a company is fine.
535
+ - ⚠️ *"I fork devcoach, add a feature, and publish the package or host its dashboard as a public service."* — You must release **your modified devcoach** source under the AGPL.
536
+ - 💼 *"I want to embed devcoach in my paid product and keep my changes closed."* — You need a commercial license.
537
+
538
+ Keep using devcoach as a tool/executable (not as an imported library) and the AGPL never reaches your own code.
package/assets/SKILL.md CHANGED
@@ -22,14 +22,6 @@ by teaching one thing at a time, at the right moment, based on what they actuall
22
22
 
23
23
  ---
24
24
 
25
- ## Plan-mode suppression
26
-
27
- If you are currently in **plan mode** (plan mode is active and `ExitPlanMode` has not
28
- yet been called in this session), **exit this skill immediately** — do not read any
29
- devcoach MCP resources, do not run onboarding, do not deliver or log any lesson.
30
-
31
- ---
32
-
33
25
  ## Onboarding flow
34
26
 
35
27
  The onboarding flow runs inline, immediately before delivering a lesson, whenever
@@ -94,15 +86,17 @@ Once the full topic list is agreed:
94
86
  These names emerge from the conversation — there is no fixed list.
95
87
  - Show the proposed grouping: *"Here's how I'd organise these — does this look
96
88
  right? Any changes?"*
97
- - When confirmed, call the MCP tool `complete_onboarding`:
89
+ - When confirmed, call the MCP tool `complete_onboarding`, including the personalized
90
+ `notebook` markdown you compose in Step 4 (so the profile and notebook are saved
91
+ together):
98
92
  ```json
99
93
  {
100
94
  "topics": { "lang_a": 7, "tool_b": 8, "practice_c": 7 },
101
- "groups": { "Languages": ["lang_a"], "DevOps": ["tool_b"], "Version Control": ["practice_c"] }
95
+ "groups": { "Languages": ["lang_a"], "DevOps": ["tool_b"], "Version Control": ["practice_c"] },
96
+ "notebook": "# devcoach — Coaching Notebook\n_Last updated: …_\n\n## Observations\n…"
102
97
  }
103
98
  ```
104
- - Continue to Step 4. Do not deliver a lesson in this turn — the rate-limit clock
105
- starts after onboarding.
99
+ - Do not deliver a lesson in this turn — the rate-limit clock starts after onboarding.
106
100
 
107
101
  **Rule:** Never ask about groups during topic collection. Propose them only in
108
102
  Step 3 after all topics are known.
@@ -121,30 +115,39 @@ Then tell the user **how to change any of it later**, across all three surfaces:
121
115
  - **UI** — `devcoach ui` (web dashboard at http://localhost:7860), or ask me to open
122
116
  it (the `open_ui` tool).
123
117
 
124
- ### Step 4 — Initialise the coaching notebook
118
+ ### Step 4 — Compose the coaching notebook (pass it to `complete_onboarding`)
125
119
 
126
- Write `~/.devcoach/learning-state.md` with observations from this conversation.
127
- If the file already exists (returning user or post-restore), integrate new
128
- observations without overwriting prior entries.
120
+ Do **not** write `learning-state.md` yourself — compose its full markdown and pass it
121
+ as the `notebook` field of the `complete_onboarding` call in Step 3. The tool saves it
122
+ to `~/.devcoach/learning-state.md` atomically with the profile (so it is never empty
123
+ and never created before the user finishes).
124
+
125
+ Make it **personalized**: draw on everything you know about *this* user — not only this
126
+ onboarding conversation, but how they work across **all their projects** (languages and
127
+ tools they reach for, recurring habits, strengths, and gaps you have observed elsewhere).
128
+ Generic boilerplate is a failure; write specific, real notes. Use this structure:
129
129
 
130
130
  ```markdown
131
131
  # devcoach — Coaching Notebook
132
132
  _Last updated: [ISO timestamp]_
133
133
 
134
134
  ## Observations
135
- [User background, confidence style, or gaps noted during onboarding.
136
- Leave empty if nothing notable was observed.]
135
+ [Specific, real notes about this user: background, how they work across their
136
+ projects, confidence style, gaps. Personalized — never generic.]
137
137
 
138
138
  ## Recurring patterns
139
- [Leave empty — nothing observed yet.]
139
+ [Patterns you have noticed in how they build, debug, or structure work.]
140
140
 
141
141
  ## Recommended focus
142
142
  [Topics the user flagged as priorities or areas of uncertainty.]
143
143
 
144
144
  ## Open hypotheses
145
- [Leave empty — nothing to track yet.]
145
+ [Things to watch for and confirm in future sessions.]
146
146
  ```
147
147
 
148
+ If re-onboarding or returning, fold prior notes into the markdown you pass —
149
+ `complete_onboarding` overwrites the file with exactly what you provide.
150
+
148
151
  ---
149
152
 
150
153
  ## Session context
@@ -342,21 +345,17 @@ it is central to the task and no applicable profile topic exists.
342
345
 
343
346
  ## 4. Lesson format
344
347
 
345
- Append the lesson **at the bottom of the response**, rendered as a card: a titled
346
- top band, the content **indented as a blockquote**, and a bottom band echoing the
347
- topic and level.
348
+ Append the lesson **at the bottom of the response**, rendered as a card: a titled top
349
+ band, the lesson as **plain markdown**, and a bottom band echoing the topic and level.
348
350
 
349
351
  ```
350
352
  ### ──────── 🎓 devcoach ────────
351
- > [Category] · Level: [Junior|Mid|Senior]
352
- >
353
- > **[Lesson title]**
354
- >
355
- > [Body: 3–6 paragraphs. Concise, practical, with a code example if useful.
356
- > Explain the WHY, not just the what. Connect it to the task just completed.]
357
- >
358
- > 💡 *Senior tip:* [One sentence a senior would say to a junior on this topic]
353
+ **[Lesson title]** · [Category] · [Junior|Mid|Senior]
359
354
 
355
+ [Body: 3–6 paragraphs. Concise, practical, with a code example if useful.
356
+ Explain the WHY, not just the what. Connect it to the task just completed.]
357
+
358
+ 💡 *Senior tip:* [One sentence a senior would say to a junior on this topic]
360
359
  ### ──────── [topic] · [level] ────────
361
360
  ```
362
361
 
@@ -365,16 +364,16 @@ Card rules:
365
364
  U+2500) around a centered title — the heading makes Claude Code colour the whole
366
365
  line. Do **not** use `---` (a real rule can't carry a title). Aim for a band
367
366
  width of ~34 characters and keep the top and bottom bands the same width.
368
- - Every content line is prefixed with `> ` (blank separators become a bare `>`).
369
- - Leave **one blank line before the bottom band** so the blockquote closes cleanly.
367
+ - The body is **plain markdown** between the bands — do **not** prefix lines with `> `
368
+ (a per-line blockquote breaks on multi-paragraph bodies and fenced code blocks).
370
369
 
371
- If `AskUserQuestion` is **not** available (Claude Desktop / claude.ai web), append
372
- this block — plain list format so the interface renders it as clickable buttons:
370
+ **Display vs storage:** the card above is for chat only. When you call `log_lesson`,
371
+ the `body` is **clean markdown** — no bands, no `> ` blockquote, and no title/`Category ·
372
+ Level` line (those go in their own fields). See Step 1 below.
373
373
 
374
- Did that land?
375
- - ✅ know — got it
376
- - ❌ don't know — need to revisit
377
- - ⏭️ skip
374
+ **Feedback is handled by the MCP protocol** — `log_lesson` runs an elicitation
375
+ (*"Did that land?"* → know / dont_know / skip) when the client supports it. Do **not**
376
+ render a feedback question yourself; just deliver the card and call `log_lesson`.
378
377
 
379
378
  **Tone:** direct, like a senior colleague explaining during a code review.
380
379
  Not academic, not verbose. Gets straight to the point.
@@ -396,7 +395,7 @@ Call `log_lesson` right after delivering the lesson, without waiting for feedbac
396
395
  "title": "Lesson title",
397
396
  "level": "junior|mid|senior",
398
397
  "summary": "One line — what was taught",
399
- "body": "The full lesson text exactly as delivered — all paragraphs, code blocks, and the senior tip. This is what the web UI displays on the lesson detail page.",
398
+ "body": "ONLY the lesson prose + the 💡 Senior tip, as CLEAN markdown — no card bands, no '>' blockquote, and do NOT repeat the title or the 'Category · Level' line (those are their own fields).",
400
399
  "task_context": "Brief description of the task that triggered it"
401
400
  }
402
401
  ```
@@ -435,6 +434,19 @@ Did that land?
435
434
 
436
435
  ---
437
436
 
437
+ ### Step 1c — Update the coaching notebook (only at every-10-lesson checkpoints)
438
+
439
+ The notebook's observations are refreshed only at **checkpoints — every 10 delivered
440
+ lessons**. The `lesson-ready` hook owns the count and tells you whether the current lesson
441
+ is a checkpoint; do not count yourself. **At a checkpoint**, after feedback is known, call
442
+ `update_notebook` with the full revised `learning-state.md` markdown — note what the user
443
+ absorbed (`know`) or should revisit (`dont_know`), any new recurring pattern, and updated
444
+ open hypotheses, keep the prior notes, and record `(updated after N lessons)`. **Between
445
+ checkpoints, do not touch the notebook.** This keeps `devcoach://notebook` driving future
446
+ lesson selection without churning it on every lesson.
447
+
448
+ ---
449
+
438
450
  ### Step 2 — Record feedback and conditionally adjust confidence (fallback only)
439
451
 
440
452
  When `log_lesson` returned `feedback: null` (elicitation declined or not supported),