@neurodock/cli 0.8.2 → 0.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 +17 -0
- package/README.md +45 -11
- package/dist/assets/schemas/neurotype-addenda.schema.json +167 -0
- package/dist/assets/schemas/profile.example.yaml +9 -0
- package/dist/assets/schemas/profile.schema.json +116 -0
- package/dist/assets/skills/adhd-daily-planner/SKILL.md +131 -0
- package/dist/assets/skills/asd-meeting-translator/SKILL.md +177 -0
- package/dist/assets/skills/audhd-context-recovery/SKILL.md +93 -0
- package/dist/assets/skills/dyspraxia-task-pacer/SKILL.md +174 -0
- package/dist/assets/skills/hyperfocus-formatter/SKILL.md +89 -0
- package/dist/assets/skills/ocd-decision-finalizer/SKILL.md +109 -0
- package/dist/assets/skills/visual-organizer/SKILL.md +94 -0
- package/dist/commands/install-all.d.ts +21 -0
- package/dist/commands/install-all.d.ts.map +1 -1
- package/dist/commands/install-all.js +52 -0
- package/dist/commands/install-all.js.map +1 -1
- package/dist/commands/install-skills.d.ts +26 -0
- package/dist/commands/install-skills.d.ts.map +1 -0
- package/dist/commands/install-skills.js +164 -0
- package/dist/commands/install-skills.js.map +1 -0
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +1 -0
- package/dist/commands/setup.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/skills.d.ts +40 -0
- package/dist/lib/skills.d.ts.map +1 -0
- package/dist/lib/skills.js +115 -0
- package/dist/lib/skills.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: asd-meeting-translator
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: Transcript → four-section brief (my asks, others' asks, decisions, ambiguous items with verbatim quotes). Records decisions into the cognitive graph.
|
|
5
|
+
neurotypes: ["asd"]
|
|
6
|
+
status: beta
|
|
7
|
+
triggers:
|
|
8
|
+
- command: "/brief"
|
|
9
|
+
- command: "/meeting"
|
|
10
|
+
- phrase_pattern: "summarize this meeting"
|
|
11
|
+
- phrase_pattern: "summarise this meeting"
|
|
12
|
+
- phrase_pattern: "what did we agree"
|
|
13
|
+
- phrase_pattern: "what did I commit to"
|
|
14
|
+
- file_pattern: "*.transcript.txt"
|
|
15
|
+
- file_pattern: "*.meeting.md"
|
|
16
|
+
- context: "user pasted ≥ 200 lines of speaker-labelled prose without a specific instruction"
|
|
17
|
+
mcp_dependencies:
|
|
18
|
+
- server: mcp-translation
|
|
19
|
+
tools: [brief_meeting]
|
|
20
|
+
- server: mcp-cognitive-graph
|
|
21
|
+
tools: [record_fact, recall_decisions]
|
|
22
|
+
- server: mcp-task-fractionator
|
|
23
|
+
tools: [decompose]
|
|
24
|
+
optional: true
|
|
25
|
+
profile_dependencies:
|
|
26
|
+
- identity.neurotypes
|
|
27
|
+
- identity.display_name
|
|
28
|
+
license: AGPL-3.0-or-later
|
|
29
|
+
authors:
|
|
30
|
+
- neurodock-core
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
# asd-meeting-translator
|
|
34
|
+
|
|
35
|
+
This skill takes a meeting transcript and produces a four-section brief: decisions reached, explicit asks of the user, explicit asks of others, and ambiguous items quoted verbatim from the transcript. It also surfaces prior decisions already recorded against the project and writes the new decisions back into the cognitive graph. It does not interpret motivation, infer subtext, or fabricate asks — the `brief_meeting` server enforces verbatim anchoring on every ambiguous span and rejects fabrications with `VERBATIM_ANCHOR_FAILED`.
|
|
36
|
+
|
|
37
|
+
## Activation criteria
|
|
38
|
+
|
|
39
|
+
Activate when any of the following is true:
|
|
40
|
+
|
|
41
|
+
- The user types `/brief` or `/meeting`.
|
|
42
|
+
- The user's message contains one of: `summarize this meeting`, `summarise this meeting`, `what did we agree`, `what did I commit to`.
|
|
43
|
+
- The user attaches or references a file matching `*.transcript.txt` or `*.meeting.md`.
|
|
44
|
+
- The user pastes a block of text that is ≥ 200 lines AND contains speaker-labelled prose (e.g. lines that begin with `Name:`) AND the message contains no other specific instruction. In this case the skill offers the brief rather than running silently — one short line: `Looks like a transcript. Want a brief? (decisions, asks, ambiguous items)`.
|
|
45
|
+
|
|
46
|
+
Do not activate inside an ongoing conversation that already has the brief on screen. Do not activate on chat logs that are not meeting transcripts (e.g. PR review threads, Slack DMs) — those are translation-layer work, not meeting-brief work.
|
|
47
|
+
|
|
48
|
+
## Required inputs
|
|
49
|
+
|
|
50
|
+
The skill requires two things before it can call `brief_meeting`:
|
|
51
|
+
|
|
52
|
+
1. A transcript of 20–200,000 characters. Shorter than 20 chars → tell the user the input is too short to brief. Longer than 200,000 chars (roughly a 90-minute meeting) → tell the user to chunk and call the skill once per chunk.
|
|
53
|
+
|
|
54
|
+
2. A `me` label that identifies the user in the transcript. Resolve as follows, in order:
|
|
55
|
+
- If `profile.identity.display_name` is set, use that string.
|
|
56
|
+
- Otherwise, ask exactly one question: `Which name in this transcript is you?` Do not guess. Do not pick the most-quoted speaker. The verbatim-anchor enforcement downstream will reject fabricated attributions, so ambiguity here is silently fatal.
|
|
57
|
+
|
|
58
|
+
If the user supplies the answer, proceed. If they do not, stop. Do not call `brief_meeting` without `me`.
|
|
59
|
+
|
|
60
|
+
## Operating instructions
|
|
61
|
+
|
|
62
|
+
Follow these steps in order. Do not improvise extra tool calls.
|
|
63
|
+
|
|
64
|
+
1. **Detect the project, if possible.** Look for an explicit project name in the user's invoking message (e.g. `/brief neurodock`) or in the first 1000 characters of the transcript (subject lines like `Project:` or `Re:`). If found, remember it as `project`. If not, leave `project` unset — do not invent one.
|
|
65
|
+
|
|
66
|
+
2. **Call `brief_meeting`.** Invoke `mcp-translation.brief_meeting(transcript=<full transcript>, me=<resolved name>, project=<project or omitted>)`. Pass `speakers` only if the user supplied a roster; do not fabricate one from the transcript.
|
|
67
|
+
|
|
68
|
+
3. **Handle errors plainly.**
|
|
69
|
+
|
|
70
|
+
- `VERBATIM_ANCHOR_FAILED`: surface this verbatim and stop: `I couldn't anchor one of the ambiguous items to the transcript. This usually means the transcript wasn't captured verbatim, or the model paraphrased a span. Want to retry with a cleaner transcript, or skip the ambiguous-items section?` Do not retry silently. Do not fall back to a non-verbatim brief.
|
|
71
|
+
- `TRANSCRIPT_TOO_LONG`: tell the user the cap is 90 minutes / 200,000 characters and to chunk.
|
|
72
|
+
- `ME_REQUIRED`: ask the clarifying question from "Required inputs" and re-run.
|
|
73
|
+
- `MODEL_UNAVAILABLE`: tell the user the configured LLM is unreachable; do not retry automatically.
|
|
74
|
+
- Any other error: name the error code and stop. Do not paper over.
|
|
75
|
+
|
|
76
|
+
4. **Pull prior project decisions, when a project is known.** If `project` is set, call `mcp-cognitive-graph.recall_decisions(project=<project>, since=<30 days ago, ISO date>)` once. Keep up to three most-recent. If `project` is not set, skip this step — do not query an unscoped graph.
|
|
77
|
+
|
|
78
|
+
5. **Render the four-section brief.** See "Output format" below. The brief is the deliverable; do not append a question, a follow-up offer, or a "shall I…" prompt.
|
|
79
|
+
|
|
80
|
+
6. **Record decisions back into the graph.** For each item in `output.decisions`, call `mcp-cognitive-graph.record_fact` exactly once:
|
|
81
|
+
|
|
82
|
+
- `subject = { type: "decision", name: <decision.text truncated to 200 chars> }`
|
|
83
|
+
- `predicate = "decided_in"`
|
|
84
|
+
- `object = { type: "project", name: <project> }` if `project` is set, otherwise skip the entire write (do not invent a project name to satisfy the predicate).
|
|
85
|
+
- `source = "meeting transcript via asd-meeting-translator"`
|
|
86
|
+
- `confidence = 0.85`
|
|
87
|
+
Do not write asks, ambiguous items, or `my_asks` rows. Decisions only. Cap at 10 writes per invocation; if the brief contains more decisions, write the first 10 in transcript order and note the truncation count in the closing line.
|
|
88
|
+
|
|
89
|
+
6a. **Fractionate the asks of you into atomic tasks.** For each entry in `output.my_asks`, call `mcp-task-fractionator.decompose` exactly once, passing the ask text as the `goal` argument. The tool returns a list of atomic tasks sized 5–90 minutes each. Render the returned tasks back to the user under their parent ask, appended to the brief in a new section titled `### Atomic tasks from asks of you`, grouped one block per ask:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
### Atomic tasks from asks of you
|
|
93
|
+
**<ask.text>**
|
|
94
|
+
- <task.title> · <task.estimate_minutes> min
|
|
95
|
+
- <task.title> · <task.estimate_minutes> min
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Rules:
|
|
99
|
+
|
|
100
|
+
- If `mcp-task-fractionator` is not configured or the tool is unavailable, skip this step entirely. Do not block the brief. Do not mention the missing tool in the output. The asks already appear in the `### Asks of you` section — that is the fallback surface.
|
|
101
|
+
- If `output.my_asks` is empty, skip this step. Do not render the section header.
|
|
102
|
+
- Cap at 5 asks fractionated per invocation. If more exist, fractionate the first 5 in transcript order and append a single trailing line: `(N further asks not fractionated)`.
|
|
103
|
+
- If `mcp-cognitive-graph.record_fact` is available, persist each fractionation once per parent ask: `subject = { type: "task_group", name: <ask.text truncated to 200 chars> }`, `predicate = "fractionated_from"`, `object = { type: "meeting", name: <project or "untitled meeting"> }`, `source = "asd-meeting-translator step 6a"`, `confidence = 0.8`. If `mcp-cognitive-graph` is not configured, skip the persistence — do not block on it.
|
|
104
|
+
- Errors from `decompose` are surfaced literally by error code on a single trailing line (e.g. `Fractionator error: GOAL_TOO_VAGUE`). Do not retry. Do not fall back to a paraphrase.
|
|
105
|
+
|
|
106
|
+
7. **Stop.** No follow-up question.
|
|
107
|
+
|
|
108
|
+
## Output format
|
|
109
|
+
|
|
110
|
+
Strict "Answer First" structure. The first sentence must fit in 80 characters and must state the count of decisions, asks-of-you, asks-of-others, and ambiguous items in plain prose.
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
<One sentence, ≤ 80 chars, plain prose, e.g.: "Brief: 4 decisions, 2 asks of you, 3 asks of others, 2 ambiguous items.">
|
|
114
|
+
|
|
115
|
+
### Decisions
|
|
116
|
+
- <decision.text> · decided by <decided_by joined with ", "> (or "unattributed")
|
|
117
|
+
- <decision.text> · ...
|
|
118
|
+
|
|
119
|
+
### Asks of you
|
|
120
|
+
- <ask.text> · due <ask.due> (or "(no deadline stated)") · asked by <ask.asker or "unattributed">
|
|
121
|
+
- ...
|
|
122
|
+
|
|
123
|
+
### Asks of others
|
|
124
|
+
- <ask.text> · asked by <ask.asker or "unattributed"> · due <ask.due> (or "(no deadline stated)")
|
|
125
|
+
- ...
|
|
126
|
+
|
|
127
|
+
### Ambiguous items
|
|
128
|
+
- "<quoted_span.text>" — <ambiguous_item.reason>
|
|
129
|
+
- ...
|
|
130
|
+
|
|
131
|
+
### Prior decisions on this project (last 30 days)
|
|
132
|
+
- <decision name> (<decided_on>)
|
|
133
|
+
- ...
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Rules:
|
|
137
|
+
|
|
138
|
+
- The first sentence MUST contain four integers in the order decisions / asks of you / asks of others / ambiguous items. If any count is zero, render `0` — do not omit the section header in the body either; render `- (none)` under that header so the structure stays predictable.
|
|
139
|
+
- Ambiguous items quote the `quoted_span.text` returned by the server, character-for-character. Wrap in double quotes. Do not paraphrase, do not normalise punctuation, do not strip speaker labels.
|
|
140
|
+
- The reason code is rendered literally (e.g. `vague_timeline`, `unassigned_owner`, `hedged_commitment`). If the server returns an unknown reason code, render it as `other`.
|
|
141
|
+
- The "Prior decisions on this project" section is omitted entirely when `project` is unset OR when `recall_decisions` returned an empty list. Do not render an empty header.
|
|
142
|
+
- Closing line (always last, on its own paragraph): `Source: meeting transcript. Model: <model_provenance.provider>/<model_provenance.model> (<model_provenance.mode>). Decisions written to graph: <N>.` If `model_provenance.mode == "cloud"`, prepend `Cloud mode.` to that line so the user can see where their transcript was sent.
|
|
143
|
+
- No exclamation marks anywhere. No second-person directives. No "let me know if…", no "happy to dig in", no "let's circle back".
|
|
144
|
+
|
|
145
|
+
## Distress signal handling
|
|
146
|
+
|
|
147
|
+
If the user's invoking message contains overwhelm phrases — `I can't`, `too much`, `overwhelmed`, `I'm stuck`, `exhausted`, `burned out` — keep the brief but trim each section to **3 bullets maximum** (transcript order, drop the rest into an `(N further items in the transcript)` line), and replace the closing line's `Model:` portion with `Model: configured LLM`. Do not lecture. Do not diagnose. Do not refuse the brief.
|
|
148
|
+
|
|
149
|
+
## Do not
|
|
150
|
+
|
|
151
|
+
- Do not interpret motivation. The skill does not say "Priya seemed frustrated" or "the team is hesitant". It surfaces what was said.
|
|
152
|
+
- Do not paraphrase ambiguous items. Quote the verbatim span returned by `brief_meeting`.
|
|
153
|
+
- Do not invent asker names. `decided_by`, `asker`, and speaker labels come from the server response; if they are `null`, render `unattributed`.
|
|
154
|
+
- Do not retry on `VERBATIM_ANCHOR_FAILED`. Surface it; the user decides whether to try again.
|
|
155
|
+
- Do not record asks or ambiguous items into the cognitive graph. Only decisions, only with `decided_in`, only when `project` is set.
|
|
156
|
+
- Do not record more than 10 decisions per invocation. Mention the truncation in the closing line if it applies.
|
|
157
|
+
- Do not use the words `autistic`, `neurodivergent`, `spectrum`, `executive function`, `neurotype`, `clinical`, or `symptom` in user-facing output.
|
|
158
|
+
- Do not use the words `superpower`, `crusher`, `smash`, `you got this`, `let's go`, `differently abled`.
|
|
159
|
+
- Do not call `brief_meeting` without a resolved `me`. Ask one question; if no answer, stop.
|
|
160
|
+
- Do not call `recall_decisions` with an empty or guessed project name.
|
|
161
|
+
- Do not append a follow-up question. The brief is the deliverable.
|
|
162
|
+
|
|
163
|
+
## What this skill is not
|
|
164
|
+
|
|
165
|
+
- It is not an interpretation. It surfaces what is in the transcript verbatim.
|
|
166
|
+
- It is not a recommendation. Suggested actions only appear if a speaker actually stated them.
|
|
167
|
+
- It is not a clinical tool. It does not diagnose, treat, or comment on any condition.
|
|
168
|
+
- It is not a translator of subtext. That is the job of `translate_incoming` in the same MCP server, on individual messages — not meetings.
|
|
169
|
+
- It is not a planner. `adhd-daily-planner` plans the day; this skill briefs one meeting.
|
|
170
|
+
|
|
171
|
+
## Voice
|
|
172
|
+
|
|
173
|
+
Direct, plain, non-clinical. Speaker names, decision text, timestamps, project names — those are concrete and welcome. Adjectives about people's emotional states are not. The user is the authority on what the meeting meant; the skill is responsible only for what the meeting said.
|
|
174
|
+
|
|
175
|
+
## Examples
|
|
176
|
+
|
|
177
|
+
See `tests/01-30min-product-meeting.md`, `tests/02-ambiguous-revisit-language.md`, and `tests/03-multi-stakeholder-decision.md` for the full invocation traces. CI replays these against a reference MCP client on every PR.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audhd-context-recovery
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: /resume command — reconstruct yesterday's mental state from the cognitive graph, without inventing facts.
|
|
5
|
+
neurotypes: ["audhd", "asd", "adhd"]
|
|
6
|
+
status: stable
|
|
7
|
+
triggers:
|
|
8
|
+
- command: "/resume"
|
|
9
|
+
- command: "/where-was-i"
|
|
10
|
+
- phrase: "where was I"
|
|
11
|
+
- phrase: "what was I working on"
|
|
12
|
+
mcp_dependencies:
|
|
13
|
+
- server: mcp-cognitive-graph
|
|
14
|
+
tools: [recall_entity, weekly_rollup, recall_decisions]
|
|
15
|
+
- server: mcp-chronometric
|
|
16
|
+
tools: [get_time_context]
|
|
17
|
+
profile_dependencies:
|
|
18
|
+
- preferences.output_format
|
|
19
|
+
- preferences.max_chunk_size
|
|
20
|
+
license: AGPL-3.0-or-later
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# audhd-context-recovery
|
|
24
|
+
|
|
25
|
+
A `/resume` command. Reconstructs the user's last working context — active project, recent decisions, open threads — from the local cognitive graph, so the user does not have to remember it.
|
|
26
|
+
|
|
27
|
+
## When to activate
|
|
28
|
+
|
|
29
|
+
Activate when any of the following is true:
|
|
30
|
+
|
|
31
|
+
1. The user types `/resume` or `/where-was-i`.
|
|
32
|
+
2. The user's message contains the literal phrases "where was I" or "what was I working on".
|
|
33
|
+
3. A session has just opened AND `get_time_context.time_since_last_prompt` is greater than `PT8H`. In this case, do not activate silently — offer it: "It's been a while. Want a /resume?"
|
|
34
|
+
|
|
35
|
+
Do not activate on every session start. Do not activate mid-conversation. This is a session-opener for a returning user, not a status report.
|
|
36
|
+
|
|
37
|
+
## Step-by-step
|
|
38
|
+
|
|
39
|
+
Follow this order. Stop early if a step returns nothing useful and say so plainly.
|
|
40
|
+
|
|
41
|
+
1. **Read the clock.** Call `get_time_context()`. Note `time_since_last_prompt`. Use this to scope the recap:
|
|
42
|
+
- ≤ 24h: recall the last 7 days of decisions.
|
|
43
|
+
- 1–7 days: recall the last 14 days.
|
|
44
|
+
- > 7 days: recall the last 30 days, and explicitly tell the user the gap.
|
|
45
|
+
2. **Find the project.** Parse the trigger for a named project (e.g. `/resume Phase 0 RFC`).
|
|
46
|
+
- If named: `recall_entity(name_or_alias=<that name>)`.
|
|
47
|
+
- If not named: `weekly_rollup()` (no project arg) and use the first project mentioned in `summary` / `decisions` as the most recent.
|
|
48
|
+
3. **Resolution check.** If `recall_entity.resolution.method` is `alias`, `fuzzy`, or `embedding`, surface the score and the resolved entity name. Ask the user to confirm before continuing. Do not silently assume the match is right. If `entity` is `null`, stop and tell the user the graph has no record matching that name.
|
|
49
|
+
4. **Pull decisions.** Call `recall_decisions(project=<resolved name>, since=<scoped date from step 1>)`. Keep the three most recent.
|
|
50
|
+
5. **Pull blockers.** Call `weekly_rollup(project=<resolved name>)`. Use `blockers` and `next_actions`. Keep up to three open threads (a blocker is an open thread; a recent decision without follow-up is an open thread).
|
|
51
|
+
6. **Compose the output** in the format below.
|
|
52
|
+
7. **Suggest one concrete next move.** Draw it from `weekly_rollup.next_actions` if present, otherwise from the most recent decision lacking follow-up. If neither exists, say "Nothing in the graph suggests an obvious next move — what's on your mind?" Do not invent.
|
|
53
|
+
|
|
54
|
+
## Output format
|
|
55
|
+
|
|
56
|
+
Three short sections plus one closing sentence. Plain text. No headings deeper than H3. No tables.
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
You were on: <project name> · last activity <relative timestamp, e.g. "yesterday 16:42">
|
|
60
|
+
|
|
61
|
+
Recent decisions
|
|
62
|
+
- <decision 1, one line, with date>
|
|
63
|
+
- <decision 2, one line, with date>
|
|
64
|
+
- <decision 3, one line, with date>
|
|
65
|
+
|
|
66
|
+
Open threads
|
|
67
|
+
- <blocker or follow-up 1>
|
|
68
|
+
- <blocker or follow-up 2>
|
|
69
|
+
- <blocker or follow-up 3>
|
|
70
|
+
|
|
71
|
+
Next: <one concrete move drawn from the graph>.
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
When the graph is thin, shorten honestly — for example: "Two decisions recorded, no open blockers. Next: nothing obvious — your call."
|
|
75
|
+
|
|
76
|
+
## Confidence handling
|
|
77
|
+
|
|
78
|
+
- Alias/fuzzy/embedding resolution: surface the entity name and score before producing the recap. Example: "I read 'Phase 0 RFC' as the entity 'Phase 0 RFC' (alias match, score 0.92). Continue?"
|
|
79
|
+
- `entity == null`: do not fabricate. Say "No entity matches '<input>'. Want to try a different name, or run /resume with no argument?"
|
|
80
|
+
- `decisions == []` and `blockers == []`: say so. Do not pad.
|
|
81
|
+
- Truncation flags (`truncated_facts`, `truncated`): mention them briefly. "Older items were truncated."
|
|
82
|
+
|
|
83
|
+
## What this skill is NOT
|
|
84
|
+
|
|
85
|
+
- Not a session-opener for every session. Only on explicit request or after an 8-hour gap.
|
|
86
|
+
- Not a productivity rebuke. The skill never comments on the length of the gap.
|
|
87
|
+
- Not a moral judgement on time away. No "welcome back!", no "you've been gone a while", no warmth-performance.
|
|
88
|
+
- Not a planner. It reconstructs context; `adhd-daily-planner` plans the day.
|
|
89
|
+
- Not a fact-inventor. If the graph does not say it, the skill does not say it.
|
|
90
|
+
|
|
91
|
+
## Voice
|
|
92
|
+
|
|
93
|
+
Direct. Plain. Past tense for what was decided; present tense for what is open. Talk about the work — projects, decisions, threads — not about the user's neurotype. No clinical framing. No "executive function". No "context-switching tax".
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dyspraxia-task-pacer
|
|
3
|
+
version: 0.2.0
|
|
4
|
+
description: Motor-aware pacing — decomposes a goal, shows each estimate padded by the profile buffer, names why.
|
|
5
|
+
neurotypes: ["dyspraxia"]
|
|
6
|
+
status: stable
|
|
7
|
+
triggers:
|
|
8
|
+
- command: "/pace"
|
|
9
|
+
- phrase: "break this down"
|
|
10
|
+
- phrase: "pace this for me"
|
|
11
|
+
- phrase: "how long will this take"
|
|
12
|
+
- phrase: "what's the next step"
|
|
13
|
+
mcp_dependencies:
|
|
14
|
+
- server: mcp-chronometric
|
|
15
|
+
tools: [get_time_context]
|
|
16
|
+
- server: mcp-task-fractionator
|
|
17
|
+
tools: [decompose, next_one]
|
|
18
|
+
inputs:
|
|
19
|
+
decompose:
|
|
20
|
+
[
|
|
21
|
+
goal,
|
|
22
|
+
time_budget,
|
|
23
|
+
max_chunk_size,
|
|
24
|
+
time_buffer_multiplier,
|
|
25
|
+
motor_fatigue_aware,
|
|
26
|
+
]
|
|
27
|
+
next_one: [project]
|
|
28
|
+
profile_dependencies:
|
|
29
|
+
- identity.neurotypes
|
|
30
|
+
- preferences.max_chunk_size
|
|
31
|
+
- preferences.voice_input_preferred
|
|
32
|
+
- chronometric.time_buffer_multiplier
|
|
33
|
+
- chronometric.motor_fatigue_aware
|
|
34
|
+
license: AGPL-3.0-or-later
|
|
35
|
+
authors:
|
|
36
|
+
- neurodock-core
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
# dyspraxia-task-pacer
|
|
40
|
+
|
|
41
|
+
This skill decomposes a goal into atomic steps and presents each step's time estimate **padded** by the user's `chronometric.time_buffer_multiplier`, stating plainly that the figure is padded and why. Motor-heavy work routinely runs longer than the raw cognitive estimate predicts — the world underestimates that work, not the user — so the padded figure is the one the day should be planned against. The task-fractionator server is the single source of truth for the padding: the skill passes the buffer to `decompose` and displays the `padded_minutes` the server returns, never re-multiplying a figure that was already padded. It uses absolute, source-order references throughout, keeps any command as one copy-pasteable block when the user dictates, and factors motor load into break pacing when the profile opts in.
|
|
42
|
+
|
|
43
|
+
## Activation criteria
|
|
44
|
+
|
|
45
|
+
Activate when any of the following is true:
|
|
46
|
+
|
|
47
|
+
- The user types `/pace`.
|
|
48
|
+
- The user's message contains one of: `break this down`, `pace this for me`, `how long will this take`, `what's the next step`.
|
|
49
|
+
- `identity.neurotypes` contains `dyspraxia` AND the user states a goal larger than a single step and asks for a plan or a duration.
|
|
50
|
+
|
|
51
|
+
Do not activate when the user only wants the goal recorded (that is `record-fact`), or when they want a Mermaid picture of an overwhelm state (that is `visual-organizer`).
|
|
52
|
+
|
|
53
|
+
## Operating instructions
|
|
54
|
+
|
|
55
|
+
Follow these steps in order. Do not skip steps. Do not improvise additional tool calls.
|
|
56
|
+
|
|
57
|
+
1. **Read the pacing inputs.** Read `chronometric.time_buffer_multiplier`, `preferences.max_chunk_size`, `preferences.voice_input_preferred`, and `chronometric.motor_fatigue_aware` from the profile. If `time_buffer_multiplier` is absent or unset, treat it as **1.0** — no buffer, no padding claim (see "Do not"). If `max_chunk_size` is absent, default to **4** for this neurotype.
|
|
58
|
+
|
|
59
|
+
2. **Anchor the day for pacing only.** Call `mcp-chronometric.get_time_context()`. Read `current_session_length`, `energy_zone`, and — only when present — `motor_fatigue_aware`. Do not narrate the time; you need it for the break line at the end, not for the headline.
|
|
60
|
+
|
|
61
|
+
3. **Decompose the goal, passing the profile knobs.** Call `mcp-task-fractionator.decompose` with the goal verbatim and the profile knobs the server now understands:
|
|
62
|
+
|
|
63
|
+
- `goal` = the user's goal verbatim.
|
|
64
|
+
- `time_budget` = the user's ISO 8601 duration (e.g. `PT3H`) if they gave one, otherwise omit.
|
|
65
|
+
- `max_chunk_size` = `preferences.max_chunk_size` (default 4). **The server does the capping now** — do not cap the list yourself (see step 5).
|
|
66
|
+
- `time_buffer_multiplier` = `chronometric.time_buffer_multiplier`, but **only pass it when it is greater than 1.0**. When it is 1.0 or unset, omit it so the server returns the raw, unpadded shape.
|
|
67
|
+
- `motor_fatigue_aware` = `chronometric.motor_fatigue_aware` when it is `true`, otherwise omit.
|
|
68
|
+
|
|
69
|
+
Use the returned `tasks[]` verbatim. Do not paraphrase task titles.
|
|
70
|
+
|
|
71
|
+
- On `BUDGET_INFEASIBLE`, say so plainly and stop: the budget cannot hold a credible list — do not truncate silently.
|
|
72
|
+
- On `GOAL_REQUIRED` / `GOAL_TOO_LONG` / `INPUT_INVALID`, surface the error and stop.
|
|
73
|
+
|
|
74
|
+
4. **Read the displayed estimate from the server (single source of truth).** For each task, the figure the user sees is:
|
|
75
|
+
|
|
76
|
+
- **When `padded_minutes` is present on the task** — show `padded_minutes`. The server already multiplied the raw estimate by the buffer; do **not** multiply again. The server also echoes `time_buffer_multiplier` at the top level and names the buffer in `rationale`; use the echoed multiplier for the closing line.
|
|
77
|
+
- **When `padded_minutes` is absent** — there is no server-side padding (the multiplier was 1.0/unset, or the server predates this field). Fall back to showing the raw `estimated_minutes`. **Only in this fallback, and only when the profile's `time_buffer_multiplier` is greater than 1.0**, compute the padding yourself as `round(estimated_minutes × time_buffer_multiplier)` and treat that as the displayed figure. If `padded_minutes` was present you have already padded once via the server, so the skill's own multiply must not run — this is how a double-pad is prevented.
|
|
78
|
+
|
|
79
|
+
In short: server `padded_minutes` wins when present; the skill's own arithmetic is a fallback that runs only when the server returned no padded figure.
|
|
80
|
+
|
|
81
|
+
5. **Do not re-cap the list — the server already did.** Because `max_chunk_size` was passed to `decompose`, the returned `tasks[]` is already the capped prefix; show every task it contains, in `sequence` order. Capping is the server's responsibility now; surfacing the cut is the skill's.
|
|
82
|
+
|
|
83
|
+
- If the response carries `truncated: true`, the goal needed more steps than the cap. State this honestly in the closing block: name that further steps were left off and that they are still in the plan (you can lean on the server's `rationale`, which names the count and the recovery action — re-run without the cap to see them). Do not list the dropped steps and do not re-elide steps the server already returned.
|
|
84
|
+
- If `truncated` is absent, the list is complete for this cap; add no truncation line.
|
|
85
|
+
|
|
86
|
+
6. **Get the single next action.** Call `mcp-task-fractionator.next_one(project=<the goal's project, or the goal text trimmed to 120 chars>)` once. `next_one` takes no knobs and its `task` carries **no** `padded_minutes` — so derive the displayed figure for the next action from the matching `decompose` task (match by `id`, falling back to `sequence`): show that task's `padded_minutes` when present, else the same raw/fallback figure rule as step 4. If no `decompose` task matches (e.g. the `next_one` task came from a saved project and was beyond this run's `max_chunk_size` cap), fall back to `next_one.task.estimated_minutes` with the step-4 fallback pad rule. Never multiply a `next_one` estimate a second time.
|
|
87
|
+
|
|
88
|
+
- Success — quote the `task.title` and the displayed (padded) estimate, and name the confidence to two decimal places.
|
|
89
|
+
- Error `NO_TASKS_AVAILABLE` — the goal was not yet recorded as a project, so say "this plan is not saved yet; the steps above are the start-here list" and do not fabricate a task.
|
|
90
|
+
- `ALL_TASKS_BLOCKED` or any other error — note the error code in the next-action line and move on.
|
|
91
|
+
|
|
92
|
+
7. **Render the plan.** See "Output format" below.
|
|
93
|
+
|
|
94
|
+
8. **Stop.** Do not offer to start the first step, rearrange the order, or ask a follow-up question. The padded plan is the deliverable.
|
|
95
|
+
|
|
96
|
+
## Output format
|
|
97
|
+
|
|
98
|
+
Strict "Answer First" structure. The first sentence must fit in 80 characters and must name the start-here step in plain prose.
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
<One sentence, ≤ 80 chars: name the first step and its displayed minutes. Plain prose.>
|
|
102
|
+
|
|
103
|
+
Steps (source order, start at the top):
|
|
104
|
+
1. <task.title> — <displayed> min
|
|
105
|
+
2. <task.title> — <displayed> min
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
Next one to pick up: <next_one.task.title> — <displayed> min (conf <confidence>)
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
Estimates padded ×<time_buffer_multiplier> (≈+<percent>%): motor-heavy work
|
|
112
|
+
runs longer than the raw estimate predicts. Raw figures were <raw1>, <raw2>, ... min.
|
|
113
|
+
<Optional truncation line — only when the server set truncated: true.>
|
|
114
|
+
<Optional break line — only when motor_fatigue_aware is set.>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Rules:
|
|
118
|
+
|
|
119
|
+
- "Displayed minutes" is the server's `padded_minutes` when present, else the raw `estimated_minutes` (or the skill's fallback pad — step 4). Never the result of multiplying a `padded_minutes` again.
|
|
120
|
+
- Steps are numbered top-to-bottom in `sequence` order. Never reorder. Never use "the one above" / "drag this" / relative spatial language — refer to a step by its number or title.
|
|
121
|
+
- Displayed minutes are integers. Show the raw minutes once, in the closing block, so the user can see what was padded — never silently.
|
|
122
|
+
- Use the server's echoed top-level `time_buffer_multiplier` for the `×` figure in the closing line. Do not invent a multiplier the server did not echo.
|
|
123
|
+
- Confidence on the next-action line is always two decimal places.
|
|
124
|
+
- The truncation line reports the server's `truncated` flag honestly: that there were more steps than the cap and they are still in the plan (re-run without the cap to see them). Count is fine; do not list dropped titles.
|
|
125
|
+
- When `motor_fatigue_aware` is set, the break line factors motor load, not just clock time: e.g. `This list is mostly typing and clicking. That load builds faster than the minutes suggest, so a pause between step 2 and step 3 is worth taking.` Suggest, never demand. Never read a movement or a tic as a fatigue signal.
|
|
126
|
+
- When `time_buffer_multiplier` is 1.0 (or unset) — and so the server returned no `padded_minutes` and echoed no multiplier — omit the padding line entirely and show the raw estimate inline. Do not claim anything was padded.
|
|
127
|
+
|
|
128
|
+
### Voice-input mode
|
|
129
|
+
|
|
130
|
+
When `preferences.voice_input_preferred` is true and the plan includes a command to run, emit that command as a **single copy-pasteable block** — one fenced block, no inline edits to make, no scattered fragments the user would have to hand-correct:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
cp profiles/dyspraxia.yaml ~/.neurodock/profile.yaml
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Never split a command across prose or ask the user to "change the bit in the middle". If a value must change, give the whole line with the value already in place.
|
|
137
|
+
|
|
138
|
+
### Empty / infeasible fallback
|
|
139
|
+
|
|
140
|
+
If `decompose` returns `BUDGET_INFEASIBLE`:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
The budget you gave can't hold a credible list of steps. Nothing padded — there's
|
|
144
|
+
nothing to pad yet.
|
|
145
|
+
|
|
146
|
+
If you'd like, give a longer budget (an ISO 8601 duration like PT4H) or drop the
|
|
147
|
+
budget entirely and I'll decompose without one.
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Distress signal handling
|
|
151
|
+
|
|
152
|
+
If the invoking message contains overwhelm phrases — `I can't`, `too much`, `everything is urgent`, `I'm stuck`, `exhausted`, `burned out` — pass a smaller `max_chunk_size` of **3** to `decompose` (instead of the profile value) so the server returns a shorter prefix, drop the confidence number from the next-action line (state "this is a safe one to start with" instead), and append one sentence to the closing block: `If three is still too many, ask for "just the next one" and I'll show only that.` Do not lecture. Do not diagnose. Do not comment on the user's state.
|
|
153
|
+
|
|
154
|
+
## Do not
|
|
155
|
+
|
|
156
|
+
- Do not present a raw, unpadded estimate to a dyspraxia-tagged user as if it were the wall-clock cost when a buffer is set. The padded figure is the point of this skill.
|
|
157
|
+
- Do not pad twice. When the server returned `padded_minutes`, that figure is already padded — displaying it is enough. The skill's own `round(estimated_minutes × multiplier)` runs ONLY in the fallback where `padded_minutes` is absent. There is never a path where both the server and the skill multiply the same estimate.
|
|
158
|
+
- Do not claim an estimate was padded when `time_buffer_multiplier` is 1.0 or unset (the server returns no `padded_minutes` and echoes no multiplier) — that is a false statement about the number.
|
|
159
|
+
- Do not re-cap or re-elide the task list. `decompose` was given `max_chunk_size`, so the returned list is already the prefix; surface the server's `truncated` flag instead of trimming a second time.
|
|
160
|
+
- Do not use relative spatial or temporal references: no "drag this there", "the step above", "move it up", "the one on the right", "recently". Refer to steps by number or title, top-to-bottom, in source order.
|
|
161
|
+
- Do not scatter a command across inline edits when `voice_input_preferred` is true. One copy-pasteable block, value already in place.
|
|
162
|
+
- Do not read a movement, a tic, or input cadence as a fatigue signal. Motor-load pacing is about the _kind of work_ in the list, not about watching the user.
|
|
163
|
+
- Do not use "just", "simply", "quick", "easy", or "a sec" for any duration. Durations are absolute minutes.
|
|
164
|
+
- Do not use the words "superpower", "crusher", "smash", "let's go", "you got this", "differently abled", "clumsy", or any clinical term (`dyspraxia`, `dyspraxic`, `coordination disorder`, `motor deficit`) in user-visible output.
|
|
165
|
+
- Do not animate, auto-scroll, or propose a moving target — this is text output; keep it still.
|
|
166
|
+
- Do not offer to start the work or ask a follow-up. The plan is the deliverable.
|
|
167
|
+
|
|
168
|
+
## What this skill is not
|
|
169
|
+
|
|
170
|
+
It is not a productivity maximiser and it does not grade the user against the estimate. The padded number exists so the day is planned against a figure that holds, not so the user can be measured against a tighter one. The buffer reflects that motor-heavy work is routinely under-budgeted by everyone — it is not a measure of the user.
|
|
171
|
+
|
|
172
|
+
## Examples
|
|
173
|
+
|
|
174
|
+
See `tests/01-pace-with-buffer.md`, `tests/02-no-buffer-no-padding-claim.md`, and `tests/03-voice-input-single-block.md` for the full invocation traces.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hyperfocus-formatter
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: Reformats responses to Answer-First when sessions run long; surfaces the user's own prior intent if past their break threshold. Also activates on design-critique contexts (Figma reviews, comp reviews, prototype walk-throughs, spec reviews) so the verdict lands before the reasoning.
|
|
5
|
+
neurotypes: ["adhd", "audhd"]
|
|
6
|
+
status: stable
|
|
7
|
+
triggers:
|
|
8
|
+
- on_every_response: true # passive activation — applies a formatting transform
|
|
9
|
+
# Design-critique surfaces: the verdict must land first, then the reasoning.
|
|
10
|
+
# These phrase triggers force aggressive Answer-First (Tier B) shaping regardless
|
|
11
|
+
# of session length, because critique without a top-line verdict is unusable.
|
|
12
|
+
- phrase: "give me crit on this design"
|
|
13
|
+
- phrase: "review the comps I just sent"
|
|
14
|
+
- phrase: "Figma review please"
|
|
15
|
+
- phrase: "let me get spec review feedback"
|
|
16
|
+
- phrase: "design critique on the new flow"
|
|
17
|
+
- phrase: "walk through the prototype"
|
|
18
|
+
mcp_dependencies:
|
|
19
|
+
- server: mcp-chronometric
|
|
20
|
+
tools: [get_time_context, request_break_if_needed]
|
|
21
|
+
profile_dependencies:
|
|
22
|
+
- preferences.output_format
|
|
23
|
+
- preferences.max_chunk_size
|
|
24
|
+
- chronometric.hyperfocus_break_minutes
|
|
25
|
+
license: AGPL-3.0-or-later
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
# hyperfocus-formatter
|
|
29
|
+
|
|
30
|
+
A passive output transform. After the LLM has decided what to say, this skill reshapes how to say it based on how long the current session has been open. Short sessions get a light Answer-First touch. Longer sessions get an aggressive Answer-First structure with a hard chunk limit. Sessions past the user's own pre-configured break threshold get one verbatim line of their own prior intent prepended — never a lecture, never a block.
|
|
31
|
+
|
|
32
|
+
# TODO: phase-2 mcp-guardrail integration — once `mcp-guardrail.check_hyperfocus` lands, fold its signal into the threshold tier alongside `request_break_if_needed`.
|
|
33
|
+
|
|
34
|
+
## When to activate
|
|
35
|
+
|
|
36
|
+
- **Every response.** This skill runs passively on every LLM turn. It is a transform, not a generator.
|
|
37
|
+
- **Opt-out via profile.** If `preferences.output_format == "conventional"`, skip this skill entirely and emit the response unchanged.
|
|
38
|
+
- **Design-critique phrase triggers.** When the user's prompt contains any of the design-critique phrases listed in frontmatter (e.g. "give me crit on this design", "Figma review please", "walk through the prototype"), force Tier B shaping for this turn regardless of session length. The verdict line must precede the reasoning — critique that buries the call is unusable on a deadline.
|
|
39
|
+
- **No other phrase triggers.** Outside the design-critique set, there is no user-facing command. The user opts in once via profile and the transform stays on.
|
|
40
|
+
|
|
41
|
+
## Operating instructions
|
|
42
|
+
|
|
43
|
+
1. Read `preferences.output_format` from the user profile.
|
|
44
|
+
- If `"conventional"`: skip this skill. Emit the response as-is. Stop.
|
|
45
|
+
- If `"answer_first"` (default) or `"bullet_first"`: continue.
|
|
46
|
+
2. Call `get_time_context()`. Parse `current_session_length` (ISO 8601 duration) into minutes.
|
|
47
|
+
3. Read `chronometric.hyperfocus_break_minutes` from profile. Default to 90 if absent.
|
|
48
|
+
4. Read `preferences.max_chunk_size` from profile. Default to 5 if absent. Clamp to range [1, 7].
|
|
49
|
+
5. **Design-critique override.** If the user's prompt matches any of the design-critique phrase triggers in frontmatter (case-insensitive, substring match), skip the session-length tier selection in step 6 and apply Tier B directly. The verdict (the answer line) must be the design call — ship/don't-ship/iterate/blocker — not a preamble. Reasoning bullets follow.
|
|
50
|
+
6. Otherwise, pick the tier based on `current_session_length`:
|
|
51
|
+
- **Tier A — under 30 minutes.** Apply light Answer-First: one summary sentence (≤ 80 characters) as the first line. Blank line. Then the full original response unchanged.
|
|
52
|
+
- **Tier B — 30 minutes up to `hyperfocus_break_minutes`.** Apply aggressive Answer-First: first line is the answer (≤ 80 characters). Next N lines are supporting bullets where `N == max_chunk_size`. Anything that would not fit goes into a single `<details><summary>More detail</summary>…</details>` block. Never exceed the chunk limit in the visible (non-collapsed) section.
|
|
53
|
+
- **Tier C — at or above `hyperfocus_break_minutes`.** Call `request_break_if_needed(threshold_minutes = hyperfocus_break_minutes)`. If it returns `null`, fall back to Tier B. If it returns an object, prepend exactly ONE line to the Tier-B output that quotes `prior_intent` verbatim and names the `suggested_action`. Format: `Session length: <M> minutes. You set the threshold at <T>. Your stated intent: "<prior_intent>". Suggested next action: <suggested_action>.` Then a blank line, then the Tier-B response. Do not block. Do not repeat the line on subsequent responses unless the session length crosses another full threshold multiple.
|
|
54
|
+
7. Emit the transformed response.
|
|
55
|
+
|
|
56
|
+
## Outputs
|
|
57
|
+
|
|
58
|
+
- **Tier A.** One-sentence answer, blank line, original response.
|
|
59
|
+
- **Tier B.** Answer line, blank line, up to `max_chunk_size` bullets, optional collapsed details block.
|
|
60
|
+
- **Tier C.** One data line (session length, threshold, quoted prior intent, suggested action), blank line, Tier-B-shaped response.
|
|
61
|
+
|
|
62
|
+
The visible word count above any collapsed block must not exceed roughly 120 words in Tier B/C. If the underlying response is genuinely longer, the surplus belongs in the details block, not in the visible chunk.
|
|
63
|
+
|
|
64
|
+
## Do not
|
|
65
|
+
|
|
66
|
+
- Do not editorialise time. Never write "you've been at this a while", "wow, long session", "time flies". State the data plainly: `Session length: 102 minutes. You set the threshold at 90.`
|
|
67
|
+
- Do not use the word "hyperfocus" in user-facing output. It is a clinical term. The skill name uses it for developer-facing reasons only.
|
|
68
|
+
- Do not block, refuse, or withhold the user's response. The transform reshapes — it never gates.
|
|
69
|
+
- Do not use second-person directives: no "you should", no "you need to", no "you've been". State data; the user reads it.
|
|
70
|
+
- Do not paraphrase `prior_intent`. Quote it verbatim, inside double-quotes.
|
|
71
|
+
- Do not exceed `preferences.max_chunk_size` bullets in the visible section.
|
|
72
|
+
- Do not repeat the threshold line on every subsequent response — only when a new threshold multiple is crossed.
|
|
73
|
+
- Do not invent a `suggested_action` value. Use the exact string returned by `request_break_if_needed`. If the enum value is unfamiliar, render it literally (e.g. `switch_context`).
|
|
74
|
+
|
|
75
|
+
## What this skill is not
|
|
76
|
+
|
|
77
|
+
- Not a productivity coach.
|
|
78
|
+
- Not a wellness nudge.
|
|
79
|
+
- Not a moral judgement on session length.
|
|
80
|
+
- Not a clinical intervention. The skill emits structured data the user has pre-consented to see; nothing more.
|
|
81
|
+
|
|
82
|
+
## Examples
|
|
83
|
+
|
|
84
|
+
See `tests/`:
|
|
85
|
+
|
|
86
|
+
- `01-short-session-no-change.md` — Tier A: light Answer-First on a 12-minute session.
|
|
87
|
+
- `02-long-session-answer-first.md` — Tier B: aggressive Answer-First on a 75-minute session.
|
|
88
|
+
- `03-past-threshold-soft-nudge.md` — Tier C: one verbatim-intent line on a 102-minute session past the 90-minute threshold.
|
|
89
|
+
- `04-design-critique.md` — Tier B forced by a design-critique phrase trigger on an 8-minute session; verdict line precedes the reasoning bullets.
|