make-runner-mcp 2.1.1 → 2.2.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 +35 -18
- package/package.json +1 -1
- package/server.js +24 -20
- package/skills/fix-makefile-compat/SKILL.md +346 -0
- package/skills/fix-makefile-links/SKILL.md +0 -169
package/README.md
CHANGED
|
@@ -113,24 +113,41 @@ you expect actually show up.
|
|
|
113
113
|
|
|
114
114
|
### Fixing it automatically, not just diagnosing it
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
There's a broader compatibility procedure than just linking — a Makefile
|
|
117
|
+
written for a human at a real terminal often has two other habits that
|
|
118
|
+
break under make-runner-mcp too:
|
|
119
|
+
|
|
120
|
+
- **Hardcoded interactive docker flags** — `docker exec -it`/`-itu ...`
|
|
121
|
+
(or `docker compose exec` without `-T`) requires a real TTY. It works
|
|
122
|
+
for a human, and fails or hangs when make-runner-mcp runs it (it always
|
|
123
|
+
spawns `make` with piped, non-tty stdio).
|
|
124
|
+
- **`$(MAKECMDGOALS)`-style argument passing** — a `composer`-style target
|
|
125
|
+
that forwards `make composer install foo` via
|
|
126
|
+
`$(filter-out $@,$(MAKECMDGOALS))` can't take arguments through
|
|
127
|
+
make-runner-mcp at all: bare positional arguments are always rejected
|
|
128
|
+
(see [Passing arguments through to a target](#passing-arguments-through-to-a-target)
|
|
129
|
+
above) — only `ARGS=value` style works.
|
|
130
|
+
|
|
131
|
+
All three (linking, TTY flags, `$(MAKECMDGOALS)`) are covered by one
|
|
132
|
+
procedure, written once at
|
|
133
|
+
[`skills/fix-makefile-compat/SKILL.md`](./skills/fix-makefile-compat/SKILL.md)
|
|
134
|
+
— it finds every instance of each, shows you the full proposed changeset,
|
|
135
|
+
and waits for your approval before writing anything. Reachable two ways:
|
|
120
136
|
|
|
121
137
|
- **Already connected to this server** (the normal case — no extra setup):
|
|
122
|
-
it's exposed as an MCP **prompt** named `fix-makefile-
|
|
138
|
+
it's exposed as an MCP **prompt** named `fix-makefile-compat`. Any
|
|
123
139
|
MCP client that supports prompts (Claude Code's `/mcp` prompt picker,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
140
|
+
Gemini CLI's automatic MCP-prompt-as-slash-command support, etc.) can
|
|
141
|
+
pull it straight from the running server — the prompt text comes back
|
|
142
|
+
with this project's own `PROJECT_DIR`, Makefile path, and a ready-to-run
|
|
143
|
+
`--diagnose` command already filled in, since the server serving it
|
|
144
|
+
already knows all three. Nothing to install.
|
|
128
145
|
- **Not using make-runner-mcp as an MCP server here** (e.g. evaluating it,
|
|
129
146
|
or just want the procedure without wiring up a client): install the same
|
|
130
147
|
file as a standalone Claude Code skill —
|
|
131
|
-
`cp -r skills/fix-makefile-
|
|
148
|
+
`cp -r skills/fix-makefile-compat ~/.claude/skills/` (every project) or
|
|
132
149
|
into a single project's own `.claude/skills/` — then run
|
|
133
|
-
`/fix-makefile-
|
|
150
|
+
`/fix-makefile-compat`. Slightly more manual (it has to search for a
|
|
134
151
|
make-runner-mcp checkout itself to run `--diagnose`, rather than already
|
|
135
152
|
knowing where one is), but requires nothing beyond Claude Code.
|
|
136
153
|
|
|
@@ -142,7 +159,7 @@ The server is the same everywhere — only the config file and its shape
|
|
|
142
159
|
differ per client. Things that change between projects/teams:
|
|
143
160
|
|
|
144
161
|
- `PROJECT_DIR` — the target project's root.
|
|
145
|
-
- `#v2.
|
|
162
|
+
- `#v2.2.0` — bump this to whatever tag you've actually released. Always
|
|
146
163
|
pin to a release tag, never `#main`: for a tool that executes commands,
|
|
147
164
|
an unpinned branch reference means a bad push could silently change what
|
|
148
165
|
runs on everyone's machine.
|
|
@@ -157,7 +174,7 @@ differ per client. Things that change between projects/teams:
|
|
|
157
174
|
"mcpServers": {
|
|
158
175
|
"makeRunner": {
|
|
159
176
|
"command": "npx",
|
|
160
|
-
"args": ["-y", "github:davindermahal/make-runner-mcp#v2.
|
|
177
|
+
"args": ["-y", "github:davindermahal/make-runner-mcp#v2.2.0"],
|
|
161
178
|
"env": { "PROJECT_DIR": "/path/to/project", "MCP_TRANSPORT": "stdio" }
|
|
162
179
|
}
|
|
163
180
|
}
|
|
@@ -171,13 +188,13 @@ Project-level `.mcp.json` at the repo root (checked in, shared with the team):
|
|
|
171
188
|
"mcpServers": {
|
|
172
189
|
"makeRunner": {
|
|
173
190
|
"command": "npx",
|
|
174
|
-
"args": ["-y", "github:davindermahal/make-runner-mcp#v2.
|
|
191
|
+
"args": ["-y", "github:davindermahal/make-runner-mcp#v2.2.0"],
|
|
175
192
|
"env": { "PROJECT_DIR": "/path/to/project", "MCP_TRANSPORT": "stdio" }
|
|
176
193
|
}
|
|
177
194
|
}
|
|
178
195
|
}
|
|
179
196
|
```
|
|
180
|
-
Or via the CLI: `claude mcp add makeRunner -e PROJECT_DIR=/path/to/project -e MCP_TRANSPORT=stdio -- npx -y github:davindermahal/make-runner-mcp#v2.
|
|
197
|
+
Or via the CLI: `claude mcp add makeRunner -e PROJECT_DIR=/path/to/project -e MCP_TRANSPORT=stdio -- npx -y github:davindermahal/make-runner-mcp#v2.2.0`
|
|
181
198
|
|
|
182
199
|
### Claude Desktop
|
|
183
200
|
`claude_desktop_config.json` (Settings → Developer → Edit Config):
|
|
@@ -186,7 +203,7 @@ Or via the CLI: `claude mcp add makeRunner -e PROJECT_DIR=/path/to/project -e MC
|
|
|
186
203
|
"mcpServers": {
|
|
187
204
|
"makeRunner": {
|
|
188
205
|
"command": "npx",
|
|
189
|
-
"args": ["-y", "github:davindermahal/make-runner-mcp#v2.
|
|
206
|
+
"args": ["-y", "github:davindermahal/make-runner-mcp#v2.2.0"],
|
|
190
207
|
"env": { "PROJECT_DIR": "/path/to/project", "MCP_TRANSPORT": "stdio" }
|
|
191
208
|
}
|
|
192
209
|
}
|
|
@@ -200,7 +217,7 @@ Or via the CLI: `claude mcp add makeRunner -e PROJECT_DIR=/path/to/project -e MC
|
|
|
200
217
|
"mcpServers": {
|
|
201
218
|
"makeRunner": {
|
|
202
219
|
"command": "npx",
|
|
203
|
-
"args": ["-y", "github:davindermahal/make-runner-mcp#v2.
|
|
220
|
+
"args": ["-y", "github:davindermahal/make-runner-mcp#v2.2.0"],
|
|
204
221
|
"env": { "PROJECT_DIR": "/path/to/project", "MCP_TRANSPORT": "stdio" }
|
|
205
222
|
}
|
|
206
223
|
}
|
|
@@ -232,7 +249,7 @@ on this machine):
|
|
|
232
249
|
PROJECT_DIR=/path/to/project \
|
|
233
250
|
MCP_HTTP_TOKEN=$(openssl rand -hex 24) \
|
|
234
251
|
MCP_HTTP_PORT=8791 \
|
|
235
|
-
npx -y github:davindermahal/make-runner-mcp#v2.
|
|
252
|
+
npx -y github:davindermahal/make-runner-mcp#v2.2.0
|
|
236
253
|
```
|
|
237
254
|
|
|
238
255
|
Generate a real random token (`openssl rand -hex 24` or equivalent) and
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -88,15 +88,15 @@ const CONFIG_PATH =
|
|
|
88
88
|
process.env.MCP_MAKE_CONFIG || path.join(PROJECT_DIR, ".mcp-make-config.json");
|
|
89
89
|
|
|
90
90
|
// This server's own location, not the target project's — used to serve the
|
|
91
|
-
// "fix-makefile-
|
|
91
|
+
// "fix-makefile-compat" MCP prompt (below) straight from the same checkout
|
|
92
92
|
// this server is running from, and to point that prompt's own verification
|
|
93
93
|
// step back at this exact server.js rather than asking whoever receives
|
|
94
94
|
// the prompt to go find one.
|
|
95
95
|
const SCRIPT_PATH = fileURLToPath(import.meta.url);
|
|
96
|
-
const
|
|
96
|
+
const FIX_MAKEFILE_COMPAT_SKILL_PATH = path.join(
|
|
97
97
|
path.dirname(SCRIPT_PATH),
|
|
98
98
|
"skills",
|
|
99
|
-
"fix-makefile-
|
|
99
|
+
"fix-makefile-compat",
|
|
100
100
|
"SKILL.md"
|
|
101
101
|
);
|
|
102
102
|
|
|
@@ -621,7 +621,7 @@ function runDiagnostics() {
|
|
|
621
621
|
console.log(lines.join("\n"));
|
|
622
622
|
}
|
|
623
623
|
|
|
624
|
-
// Serves skills/fix-makefile-
|
|
624
|
+
// Serves skills/fix-makefile-compat/SKILL.md (the same file distributed for
|
|
625
625
|
// manual/Claude-Code-skill installs — see README) as an MCP prompt, so
|
|
626
626
|
// simply connecting to this server is enough to get it: no separate file
|
|
627
627
|
// to copy into ~/.claude/skills first. One file stays the source of truth
|
|
@@ -630,18 +630,19 @@ function runDiagnostics() {
|
|
|
630
630
|
// PROJECT_DIR/Makefile/script path) so whoever receives the prompt doesn't
|
|
631
631
|
// need to search for a make-runner-mcp checkout the way a cold read of the
|
|
632
632
|
// skill file on its own would require.
|
|
633
|
-
function
|
|
633
|
+
function buildFixMakefileCompatPrompt() {
|
|
634
634
|
let raw;
|
|
635
635
|
try {
|
|
636
|
-
raw = readFileSync(
|
|
636
|
+
raw = readFileSync(FIX_MAKEFILE_COMPAT_SKILL_PATH, "utf8");
|
|
637
637
|
} catch (err) {
|
|
638
|
-
console.error(`Failed to read ${
|
|
638
|
+
console.error(`Failed to read ${FIX_MAKEFILE_COMPAT_SKILL_PATH}: ${err.message}`);
|
|
639
639
|
return (
|
|
640
|
-
`Could not load the fix-makefile-
|
|
641
|
-
`checkout (expected at ${
|
|
640
|
+
`Could not load the fix-makefile-compat procedure from this server's own ` +
|
|
641
|
+
`checkout (expected at ${FIX_MAKEFILE_COMPAT_SKILL_PATH}). Run ` +
|
|
642
642
|
`\`PROJECT_DIR=${PROJECT_DIR} node ${SCRIPT_PATH} --diagnose\` and fix any ` +
|
|
643
643
|
`gaps it reports using MAKEFILE-GUIDE.md's guidance on include/forwarding/` +
|
|
644
|
-
`also-read links
|
|
644
|
+
`also-read links, hardcoded interactive docker flags, and $(MAKECMDGOALS)` +
|
|
645
|
+
`-style argument passing.`
|
|
645
646
|
);
|
|
646
647
|
}
|
|
647
648
|
// Strip the leading YAML frontmatter block — it's Claude Code skill
|
|
@@ -651,10 +652,10 @@ function buildFixMakefileLinksPrompt() {
|
|
|
651
652
|
const context =
|
|
652
653
|
`You are receiving this as an MCP prompt served directly by the ` +
|
|
653
654
|
`make-runner-mcp server already configured for this project — you ` +
|
|
654
|
-
`already have everything Step
|
|
655
|
+
`already have everything Step 8's live verification asks you to go find:\n\n` +
|
|
655
656
|
`Project root (PROJECT_DIR): ${PROJECT_DIR}\n` +
|
|
656
657
|
`Root Makefile: ${MAKEFILE}\n` +
|
|
657
|
-
`This server's own script, for Step
|
|
658
|
+
`This server's own script, for Step 8's live verification: ${SCRIPT_PATH}\n` +
|
|
658
659
|
` e.g. PROJECT_DIR="${PROJECT_DIR}" node "${SCRIPT_PATH}" --diagnose\n\n` +
|
|
659
660
|
`---\n\n`;
|
|
660
661
|
return context + body;
|
|
@@ -880,33 +881,36 @@ function createServer() {
|
|
|
880
881
|
}
|
|
881
882
|
});
|
|
882
883
|
|
|
883
|
-
// A single prompt, "fix-makefile-
|
|
884
|
+
// A single prompt, "fix-makefile-compat": see buildFixMakefileCompatPrompt()
|
|
884
885
|
// above for what it actually serves and why. This is what makes it
|
|
885
886
|
// reachable to any MCP client without a separate skill-file install —
|
|
886
887
|
// connecting to this server is enough.
|
|
887
888
|
server.setRequestHandler(ListPromptsRequestSchema, async () => ({
|
|
888
889
|
prompts: [
|
|
889
890
|
{
|
|
890
|
-
name: "fix-makefile-
|
|
891
|
+
name: "fix-makefile-compat",
|
|
891
892
|
description:
|
|
892
|
-
"Find
|
|
893
|
-
"
|
|
894
|
-
"
|
|
893
|
+
"Find everything in this project's Makefile(s) that keeps make-runner-mcp from " +
|
|
894
|
+
"discovering or correctly running a target — an unlinked secondary Makefile, " +
|
|
895
|
+
"hardcoded interactive docker flags (-it/-itu) that only work for a human at a " +
|
|
896
|
+
"real terminal, and $(MAKECMDGOALS)-style argument passing this server's " +
|
|
897
|
+
"security model rejects outright — and fix each one, with your approval before " +
|
|
898
|
+
"writing anything.",
|
|
895
899
|
},
|
|
896
900
|
],
|
|
897
901
|
}));
|
|
898
902
|
|
|
899
903
|
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
900
904
|
const { name } = request.params;
|
|
901
|
-
if (name !== "fix-makefile-
|
|
905
|
+
if (name !== "fix-makefile-compat") {
|
|
902
906
|
throw new Error(`Unknown prompt: ${name}`);
|
|
903
907
|
}
|
|
904
908
|
return {
|
|
905
|
-
description: "Diagnose and fix why
|
|
909
|
+
description: "Diagnose and fix why a Makefile target isn't discoverable by, or compatible with, make-runner-mcp.",
|
|
906
910
|
messages: [
|
|
907
911
|
{
|
|
908
912
|
role: "user",
|
|
909
|
-
content: { type: "text", text:
|
|
913
|
+
content: { type: "text", text: buildFixMakefileCompatPrompt() },
|
|
910
914
|
},
|
|
911
915
|
],
|
|
912
916
|
};
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Find everything in this project's Makefile(s) that keeps make-runner-mcp from discovering or correctly running a target — a secondary Makefile that isn't linked in, hardcoded interactive docker flags (`-it`/`-itu`) that only work for a human at a real terminal, and bare-word `$(MAKECMDGOALS)`-style argument passing that make-runner-mcp's security model rejects outright — and fix each one, showing you every change and waiting for your approval before writing anything. Only run when explicitly invoked as /fix-makefile-compat.
|
|
3
|
+
argument-hint: [optional: path to a local make-runner-mcp checkout, for live --diagnose verification]
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
allowed-tools: Read Glob Grep Bash Edit AskUserQuestion
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Make this project's Makefile(s) work for both a human and make-runner-mcp
|
|
9
|
+
|
|
10
|
+
Input: $ARGUMENTS (optional path to a make-runner-mcp checkout — see Step 6)
|
|
11
|
+
|
|
12
|
+
Goal: a human typing `make <target>` at their own terminal keeps getting
|
|
13
|
+
exactly the experience they already have — colored output, an interactive
|
|
14
|
+
shell, a live progress bar, whatever the Makefile already does for them —
|
|
15
|
+
while the *same* target also works when make-runner-mcp invokes it, which
|
|
16
|
+
happens through a real `make` process that has no terminal at all and
|
|
17
|
+
whose security model flatly refuses to run anything but the one named
|
|
18
|
+
target with only flag/`VAR=value` arguments. This skill finds every place
|
|
19
|
+
that assumption breaks and fixes it, three categories at a time, with your
|
|
20
|
+
approval before any file changes.
|
|
21
|
+
|
|
22
|
+
This does **not** cover everything `MAKEFILE-GUIDE.md` checks — denylist
|
|
23
|
+
false positives, reliance on reserved make variables, and description
|
|
24
|
+
backfilling are separate, higher-judgment concerns. Mention any you notice
|
|
25
|
+
along the way in your final report, but don't act on them here.
|
|
26
|
+
|
|
27
|
+
## Step 0: Preconditions
|
|
28
|
+
|
|
29
|
+
- Confirm a root `Makefile` exists at the project root (where this was
|
|
30
|
+
invoked, or a directory named in $ARGUMENTS/the conversation). If not,
|
|
31
|
+
stop and say so — make-runner-mcp requires `<project root>/Makefile` to
|
|
32
|
+
exist; there's nothing to fix yet.
|
|
33
|
+
- `git status --porcelain` (if this is a git repo). If dirty, proceed
|
|
34
|
+
anyway, but say so in your final report — your edits will land alongside
|
|
35
|
+
whatever's already uncommitted.
|
|
36
|
+
|
|
37
|
+
## Step 1: Inventory every Makefile in the project
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
find . -name Makefile \
|
|
41
|
+
-not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/vendor/*' \
|
|
42
|
+
-not -path '*/.venv/*' -not -path '*/venv/*'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Read every file this finds. Set aside the root one; everything else is a
|
|
46
|
+
**candidate secondary Makefile**. Every check below (Steps 2–5) applies to
|
|
47
|
+
the root Makefile and to every file reached from it (Step 2), not just the
|
|
48
|
+
root file in isolation — a target defined in a real-`include`d file is
|
|
49
|
+
just as much make-runner-mcp's problem as one in the root file itself.
|
|
50
|
+
|
|
51
|
+
## Step 2: Resolve what the root Makefile already reaches (for the linking check)
|
|
52
|
+
|
|
53
|
+
Read the root Makefile (and recurse into anything it reaches, same as
|
|
54
|
+
below) and classify every line into one of three link mechanisms — this
|
|
55
|
+
mirrors exactly what make-runner-mcp's own parser does, so a file found
|
|
56
|
+
here is one make-runner-mcp already discovers today:
|
|
57
|
+
|
|
58
|
+
1. **Real include**: a line matching `^\s*(-|s)?include\s+(.+)$`. Each
|
|
59
|
+
whitespace-separated path on the line, resolved relative to the
|
|
60
|
+
*including* file's own directory. A path containing `$(` can't be
|
|
61
|
+
resolved by make-runner-mcp either — note it as **unresolvable
|
|
62
|
+
include** in your final report rather than treating it as reachable.
|
|
63
|
+
2. **Catch-all forwarding**: a rule whose target is bare `%:` (not
|
|
64
|
+
`%.o:` or `docker-%:` — those are ordinary pattern rules, not this
|
|
65
|
+
idiom), whose recipe (the tab-indented lines immediately after it)
|
|
66
|
+
contains `$(MAKE) ... -C <dir>`. Reaches `<dir>/Makefile`. A `-C`
|
|
67
|
+
value containing `$(` similarly can't be resolved — note it the same
|
|
68
|
+
way as an unresolvable include.
|
|
69
|
+
3. **The marker this skill itself manages**: a comment line matching
|
|
70
|
+
`^\s*#{1,2}\s*make-runner:\s*also-read\s+(.+)$`. Each
|
|
71
|
+
whitespace-separated path, resolved the same way as `include`.
|
|
72
|
+
|
|
73
|
+
For every file reached via (1) or (3), recurse into it too — apply the
|
|
74
|
+
same three checks to its contents, since an included/linked file can
|
|
75
|
+
itself `include` or mark further files. (Forwarding targets, (2), are a
|
|
76
|
+
Makefile invoked by a live `$(MAKE)` at build time in a fresh directory
|
|
77
|
+
context, not textually processed further here — don't recurse into them
|
|
78
|
+
for more forwarding/include chains; treat the forwarded file itself as
|
|
79
|
+
reached and stop there, matching what make-runner-mcp's own parser does.)
|
|
80
|
+
|
|
81
|
+
Build the **reached set**: the realpath of every file resolved this way,
|
|
82
|
+
starting from the root Makefile itself. Any candidate secondary Makefile
|
|
83
|
+
from Step 1 whose realpath is **not** in this set is **orphaned** —
|
|
84
|
+
make-runner-mcp cannot see its targets at all right now.
|
|
85
|
+
|
|
86
|
+
## Step 3: Fix orphaned Makefiles (linking)
|
|
87
|
+
|
|
88
|
+
For each orphaned Makefile, the default and safest fix is to add this line
|
|
89
|
+
to the root Makefile (near any existing `include`/`also-read` lines if
|
|
90
|
+
present, otherwise near the top, after any leading variable assignments):
|
|
91
|
+
|
|
92
|
+
```makefile
|
|
93
|
+
## make-runner: also-read <path, relative to the root Makefile's directory>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
This is a plain comment — it changes nothing about what a human running
|
|
97
|
+
`make` by hand experiences, and it works regardless of *why* the file was
|
|
98
|
+
orphaned. Prefer it over adding a real `include` here: a real `include`
|
|
99
|
+
would need you to verify the whole orphaned file is safe to textually pull
|
|
100
|
+
into the root Makefile's namespace (no colliding variable/target names, no
|
|
101
|
+
assumption about running from a different `cwd`), which is exactly the
|
|
102
|
+
kind of judgment call this skill should not make silently.
|
|
103
|
+
|
|
104
|
+
**Exception — flag instead of fixing:** before proposing the marker for a
|
|
105
|
+
given orphaned file, grep its recipes for `$(UPPERCASE_VAR)`-style tokens
|
|
106
|
+
and check whether each one is assigned *only* in the root Makefile and not
|
|
107
|
+
in the orphaned file itself (excluding standard built-ins like `$(MAKE)`,
|
|
108
|
+
`$(CC)`, `$(SHELL)`). If you find one, the `also-read` marker would run
|
|
109
|
+
this file without that variable defined — likely breaking or silently
|
|
110
|
+
changing its recipe. For that file only: don't propose an edit, add it to
|
|
111
|
+
**NEEDS HUMAN DECISION** in your final report with the variable name and
|
|
112
|
+
where it's defined. This is a heuristic, not exhaustive — say so.
|
|
113
|
+
|
|
114
|
+
## Step 4: Find hardcoded interactive docker flags
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
grep -nE '\bdocker (exec|run)\b|\bdocker compose (exec|run)\b|\bdocker-compose (exec|run)\b' Makefile
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
(Run across every file from Step 1, not just the root.) For every line
|
|
121
|
+
this returns, look for a **short-option token containing `t`** (a single
|
|
122
|
+
`-` followed by one or more letters, e.g. `-it`, `-ti`, `-itu`, `-t`,
|
|
123
|
+
`-dit`) or the long form `--tty` (check separately: `grep -n -- '--tty'
|
|
124
|
+
Makefile`). That's Docker's "allocate a pseudo-TTY" flag. A recipe using
|
|
125
|
+
it only works when `make` itself has a real terminal on its own stdin — a
|
|
126
|
+
human running `make <target>` directly. It fails outright ("the input
|
|
127
|
+
device is not a TTY") or, if `-i`/`--interactive` survives without `-t`,
|
|
128
|
+
can hang waiting on stdin that's never closed — whenever `make` is
|
|
129
|
+
invoked non-interactively: through make-runner-mcp (which always spawns
|
|
130
|
+
`make` with piped, non-tty stdio), through most CI systems, and through
|
|
131
|
+
several coding-agent shell tools.
|
|
132
|
+
|
|
133
|
+
**Before proposing a fix, check whether the file already has a variable
|
|
134
|
+
for this** — grep for an existing `$(shell [ -t 0 ]` / `test -t 0` /
|
|
135
|
+
`tty -s`-style expression already assigned to a variable. If one exists,
|
|
136
|
+
reuse its exact name in the substitutions below instead of introducing a
|
|
137
|
+
second one.
|
|
138
|
+
|
|
139
|
+
If none exists, propose adding this once per file that needs it (near the
|
|
140
|
+
top, after other variable declarations, before the first target — name it
|
|
141
|
+
`DOCKER_IT` unless that collides with an existing variable in the file, in
|
|
142
|
+
which case pick another short, clear name and use it consistently):
|
|
143
|
+
|
|
144
|
+
```makefile
|
|
145
|
+
# `-t` requires a real TTY to allocate a pseudo-terminal against; without one, docker either
|
|
146
|
+
# errors ("the input device is not a TTY") or hangs. Empty here (no `-it`) whenever stdin isn't a
|
|
147
|
+
# real terminal -- e.g. make-runner-mcp, which always spawns `make` this way, or a non-interactive
|
|
148
|
+
# CI/agent shell. A human running `make <target>` directly still gets identical behavior to before.
|
|
149
|
+
DOCKER_IT := $(shell [ -t 0 ] && echo -it)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Then, for every matched line, replace the interactive-flag token with
|
|
153
|
+
`$(DOCKER_IT)`, unbundling any *other* flags in that same token so they
|
|
154
|
+
stay literal and always applied:
|
|
155
|
+
|
|
156
|
+
```makefile
|
|
157
|
+
# BEFORE
|
|
158
|
+
some-target:
|
|
159
|
+
docker exec -itu $(shell id -u):$(shell id -g) $(CONTAINER) some-command
|
|
160
|
+
|
|
161
|
+
# AFTER
|
|
162
|
+
some-target:
|
|
163
|
+
docker exec $(DOCKER_IT) -u $(shell id -u):$(shell id -g) $(CONTAINER) some-command
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
A bare `-it`/`-ti`/`--interactive --tty` (no other bundled letters)
|
|
167
|
+
becomes exactly `$(DOCKER_IT)` with nothing else added. Drop **both** `i`
|
|
168
|
+
and `t` into the variable together, not just `t` — an `-i`-only mode with
|
|
169
|
+
no real tty can still hang on an open, never-closed stdin pipe (exactly
|
|
170
|
+
how make-runner-mcp spawns `make`), so there's no safe reason to keep `-i`
|
|
171
|
+
alone when there's no `-t` to go with it. A target whose entire purpose is
|
|
172
|
+
opening an interactive shell (e.g. a `bash`/`sh` target with no other
|
|
173
|
+
arguments) will still get the same variable — running it through
|
|
174
|
+
make-runner-mcp will simply do nothing useful and time out, which is
|
|
175
|
+
correct: an interactive shell isn't meaningful through an agent either
|
|
176
|
+
way, and this isn't something to solve further here.
|
|
177
|
+
|
|
178
|
+
If this project already has parallel "-ci" or "-noninteractive"-suffixed
|
|
179
|
+
duplicate targets working around this exact problem (check target names
|
|
180
|
+
and comments for it), **do not delete or rename them** — they may be
|
|
181
|
+
referenced elsewhere (CI config, docs, muscle memory). Leave them exactly
|
|
182
|
+
as they are; they become redundant but harmless once the primary targets
|
|
183
|
+
are fixed.
|
|
184
|
+
|
|
185
|
+
## Step 5: Find and convert `$(MAKECMDGOALS)`-style argument passing
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
grep -n "MAKECMDGOALS" Makefile
|
|
189
|
+
grep -n 'filter-out \$@' Makefile
|
|
190
|
+
grep -n "wordlist" Makefile
|
|
191
|
+
grep -n "^%:" Makefile
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
(Run across every file from Step 1.) Any hit means at least one target
|
|
195
|
+
relies on bare-word passthrough — make-runner-mcp always rejects a bare
|
|
196
|
+
positional argument outright (it would be treated as an *additional build
|
|
197
|
+
goal*, which could smuggle a second, unvetted target onto the same
|
|
198
|
+
invocation), so a target using this pattern simply can't take arguments
|
|
199
|
+
through the MCP tool at all right now, even though it works fine for a
|
|
200
|
+
human typing `make composer require some/package` directly.
|
|
201
|
+
|
|
202
|
+
For each hit, find which real target's recipe consumes it (read a few
|
|
203
|
+
lines above/below the match) and add it to a list: **targets to
|
|
204
|
+
convert**.
|
|
205
|
+
|
|
206
|
+
A `^%:` hit whose recipe contains `$(MAKE)` with a `-C` flag (forwarding
|
|
207
|
+
any undefined goal to another directory's Makefile) is a *different*,
|
|
208
|
+
already-supported idiom — make-runner-mcp discovers and exposes those
|
|
209
|
+
forwarded targets automatically. Do not add it to **targets to convert**.
|
|
210
|
+
Only a `%:` rule that swallows bare-word `$(MAKECMDGOALS)` arguments
|
|
211
|
+
(typically paired with an `@:` no-op recipe, no `$(MAKE) -C ...` call) is
|
|
212
|
+
the pattern this step converts.
|
|
213
|
+
|
|
214
|
+
For each target on the list:
|
|
215
|
+
|
|
216
|
+
1. Replace every use of `$(MAKECMDGOALS)`, `$(filter-out $@,$(MAKECMDGOALS))`,
|
|
217
|
+
or similar with a single variable named `ARGS`.
|
|
218
|
+
2. Rewrite (or write, if missing) its `##` comment: `## <what it does>.
|
|
219
|
+
Pass args via ARGS, e.g. ARGS="<realistic example>"`.
|
|
220
|
+
|
|
221
|
+
```makefile
|
|
222
|
+
# BEFORE
|
|
223
|
+
composer: ## Run composer
|
|
224
|
+
docker compose exec app composer $(filter-out $@,$(MAKECMDGOALS))
|
|
225
|
+
|
|
226
|
+
# AFTER
|
|
227
|
+
composer: ## Run composer inside the app container. Pass args via ARGS, e.g. ARGS="install symfony/console --no-dev"
|
|
228
|
+
docker compose exec app composer $(ARGS)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Do not rename the target. Do not change what command it runs beyond this
|
|
232
|
+
substitution. If a target also had a hardcoded interactive flag (Step 4),
|
|
233
|
+
apply both fixes to the same recipe line in one edit.
|
|
234
|
+
|
|
235
|
+
After converting every target on the list, check whether the bare `%:`
|
|
236
|
+
catch-all rule (and its `@:` no-op recipe, and any `.PHONY` entry naming
|
|
237
|
+
it) is now dead code — nothing else still using `$(MAKECMDGOALS)`. If so,
|
|
238
|
+
propose removing it too, as part of the same changeset.
|
|
239
|
+
|
|
240
|
+
**Skip if the example value doesn't fit the safe character set:** check
|
|
241
|
+
each `ARGS="..."` example against `^[A-Za-z0-9 _.,+/@:^~=-]*$` (letters,
|
|
242
|
+
digits, spaces, and `` _ . , + / @ : ^ ~ = - ``). If your chosen example
|
|
243
|
+
doesn't match, pick a different, representative one — if nothing
|
|
244
|
+
realistic fits, leave that target unconverted and add it to **NEEDS HUMAN
|
|
245
|
+
DECISION** instead, per `MAKEFILE-GUIDE.md` §8's guidance not to invent a
|
|
246
|
+
workaround (no encoding tricks).
|
|
247
|
+
|
|
248
|
+
## Step 6: Show the full changeset and get approval before writing anything
|
|
249
|
+
|
|
250
|
+
Assemble every proposed change from Steps 3–5 into one list — file,
|
|
251
|
+
category (linking / TTY / ARGS), and a short before/after snippet for
|
|
252
|
+
each. Show this to the user as a single summary and ask for explicit
|
|
253
|
+
approval before editing any file — e.g. via `AskUserQuestion`, or by
|
|
254
|
+
plainly asking "Apply these N changes?" and waiting for a clear yes. If
|
|
255
|
+
the user approves some categories but not others, apply only what was
|
|
256
|
+
approved. Don't treat your own tool permissions (if file edits happen to
|
|
257
|
+
be pre-approved in this session) as a substitute for this — ask anyway.
|
|
258
|
+
|
|
259
|
+
If there is nothing to fix in any category, say so plainly ("Already
|
|
260
|
+
compatible — nothing to change") and stop; don't invent work.
|
|
261
|
+
|
|
262
|
+
## Step 7: Apply the approved changes
|
|
263
|
+
|
|
264
|
+
Write exactly what was approved, nothing more.
|
|
265
|
+
|
|
266
|
+
## Step 8: Verify
|
|
267
|
+
|
|
268
|
+
- **Linking**: re-run Step 2's classification against the now-edited root
|
|
269
|
+
Makefile and confirm every previously-orphaned file (other than ones
|
|
270
|
+
left for human decision) now appears in the reached set.
|
|
271
|
+
- **TTY flags**: run `make -n <target> ...` for at least one fixed target,
|
|
272
|
+
from your own shell. Your own shell is itself non-interactive (this is
|
|
273
|
+
exactly the condition make-runner-mcp always runs under), so the printed
|
|
274
|
+
command should show *no* `-it`/`-t`/`--tty` — confirm that directly in
|
|
275
|
+
the output.
|
|
276
|
+
- **ARGS conversion**: for every target converted in Step 5, run
|
|
277
|
+
`make -n <target> ARGS="<the example value from its comment>"` and
|
|
278
|
+
confirm the printed command substitutes `ARGS` in the right place and
|
|
279
|
+
the target isn't silently doing nothing.
|
|
280
|
+
- **Live check, if available**: if $ARGUMENTS names a local
|
|
281
|
+
make-runner-mcp checkout (a directory containing `server.js`), or
|
|
282
|
+
`command -v make-runner-mcp` resolves to something, run:
|
|
283
|
+
```bash
|
|
284
|
+
PROJECT_DIR="$(pwd)" node <path-to-that-checkout>/server.js --diagnose
|
|
285
|
+
```
|
|
286
|
+
Confirm newly-linked targets appear in `EXPOSED TARGETS`, and its
|
|
287
|
+
`UNRESOLVED ... PATHS` / `FILES REJECTED` sections are empty for files
|
|
288
|
+
you just fixed. If unavailable, say so and note the checks above stand
|
|
289
|
+
in for it.
|
|
290
|
+
|
|
291
|
+
Do **not** invoke any real `make <target>` recipe with side effects
|
|
292
|
+
(anything that isn't `-n`/dry-run) to test — that executes real commands,
|
|
293
|
+
which is outside what this skill is for.
|
|
294
|
+
|
|
295
|
+
## Step 9: Report
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
MAKEFILES FOUND:
|
|
299
|
+
- <path>: <root | already linked via include/forwarding/also-read | orphaned>
|
|
300
|
+
|
|
301
|
+
LINKING FIXED (also-read marker added):
|
|
302
|
+
- <path>
|
|
303
|
+
|
|
304
|
+
TTY FLAGS FIXED:
|
|
305
|
+
- <target>: <e.g. "docker exec -itu ... -> docker exec $(DOCKER_IT) -u ...">
|
|
306
|
+
|
|
307
|
+
ARGS CONVERTED (MAKECMDGOALS -> ARGS):
|
|
308
|
+
- <target>: <one line: what changed>
|
|
309
|
+
|
|
310
|
+
DEAD CODE REMOVED:
|
|
311
|
+
- <catch-all rule removed, or "none">
|
|
312
|
+
|
|
313
|
+
NEEDS HUMAN DECISION:
|
|
314
|
+
- <target/file>: <exact reason>
|
|
315
|
+
|
|
316
|
+
VERIFIED:
|
|
317
|
+
- <target>: <"dry-run only" | "dry-run + live --diagnose" | "not tested -- reason">
|
|
318
|
+
|
|
319
|
+
NOT TOUCHED (and why):
|
|
320
|
+
- <target>: <e.g. "already uses ARGS and no interactive flags, no change needed">
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Also mention, once, that the `also-read` marker and any of these fixes
|
|
324
|
+
only take effect with a make-runner-mcp version that includes them — if
|
|
325
|
+
this project's MCP client config pins an older release tag, the fix won't
|
|
326
|
+
apply until that tag is bumped.
|
|
327
|
+
|
|
328
|
+
## Guardrails — do not do these, under any circumstance
|
|
329
|
+
|
|
330
|
+
- **Don't rename or restructure a target to dodge the hard-coded
|
|
331
|
+
denylist** (`deploy`, `destroy`, `prod`, `publish`, `release`, `rm-*`).
|
|
332
|
+
That's a separate, higher-judgment concern outside this skill's scope —
|
|
333
|
+
mention it in your report if you notice it, don't act on it.
|
|
334
|
+
- **Don't try to route around the `VAR=value` character restriction** in
|
|
335
|
+
Step 5 — no encoding tricks, no alternate delimiters. If a target's real
|
|
336
|
+
arguments don't fit, leave it as `NEEDS HUMAN DECISION`.
|
|
337
|
+
- **Don't edit `.mcp-make-config.json`** as a substitute for fixing a
|
|
338
|
+
target — it only narrows what's exposed, it doesn't change how a target
|
|
339
|
+
runs or receives arguments.
|
|
340
|
+
- **Don't edit make-runner-mcp's own `server.js`** from inside a target
|
|
341
|
+
project's repo. If something here genuinely needs a change to
|
|
342
|
+
make-runner-mcp itself, report it, don't make it from here.
|
|
343
|
+
- **Don't mark something as tested if you didn't actually run a command
|
|
344
|
+
and see its output.** If you couldn't test (missing tooling, no
|
|
345
|
+
container running, etc.), say so plainly in Step 9 rather than guessing
|
|
346
|
+
that it probably works.
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Find every Makefile in the current project, check which ones make-runner-mcp can actually discover (via a real `include`/`-include` directive, the `%:` catch-all forwarding idiom, or a `## make-runner: also-read <path>` marker), and add the missing link automatically for any that are orphaned — instead of just reporting the gap. Only run when explicitly invoked as /fix-makefile-links.
|
|
3
|
-
argument-hint: [optional: path to a local make-runner-mcp checkout, to run --diagnose for live verification]
|
|
4
|
-
disable-model-invocation: true
|
|
5
|
-
allowed-tools: Read Glob Grep Bash Edit AskUserQuestion
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Fix make-runner-mcp Makefile linking
|
|
9
|
-
|
|
10
|
-
Input: $ARGUMENTS (optional path to a make-runner-mcp checkout — see Step 5)
|
|
11
|
-
|
|
12
|
-
Goal: make sure every Makefile in this project that defines real targets is
|
|
13
|
-
actually reachable from `<project root>/Makefile` — the only file
|
|
14
|
-
make-runner-mcp reads — and fix it automatically where it isn't, rather
|
|
15
|
-
than just telling the user their Makefile isn't being picked up.
|
|
16
|
-
|
|
17
|
-
This handles **linking/discovery only**. It does not touch recipe bodies,
|
|
18
|
-
convert `$(MAKECMDGOALS)`-style argument passing, or fix denylist false
|
|
19
|
-
positives — those are separate, higher-judgment concerns covered by
|
|
20
|
-
make-runner-mcp's own `MAKEFILE-GUIDE.md`; mention it in your final report
|
|
21
|
-
if you notice any of those along the way, but don't act on them here.
|
|
22
|
-
|
|
23
|
-
## Step 0: Preconditions
|
|
24
|
-
|
|
25
|
-
- Confirm a root `Makefile` exists at the project root (where this was
|
|
26
|
-
invoked, or a directory the user named in $ARGUMENTS/the conversation).
|
|
27
|
-
If not, stop and say so — make-runner-mcp requires
|
|
28
|
-
`<project root>/Makefile` to exist; there's nothing to link yet.
|
|
29
|
-
- `git status --porcelain` (if this is a git repo). If dirty, proceed
|
|
30
|
-
anyway — the only edit this skill makes is appending comment lines to
|
|
31
|
-
the root Makefile — but mention in the final report that the edit will
|
|
32
|
-
land alongside whatever else is already uncommitted.
|
|
33
|
-
|
|
34
|
-
## Step 1: Inventory every Makefile in the project
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
find . -name Makefile \
|
|
38
|
-
-not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/vendor/*' \
|
|
39
|
-
-not -path '*/.venv/*' -not -path '*/venv/*'
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Read every file this finds. Set aside the root one; everything else is a
|
|
43
|
-
**candidate secondary Makefile**.
|
|
44
|
-
|
|
45
|
-
If this returns only the root Makefile, stop here and report: "Only one
|
|
46
|
-
Makefile in this project — nothing to link." Don't invent work.
|
|
47
|
-
|
|
48
|
-
## Step 2: Resolve what the root Makefile already reaches
|
|
49
|
-
|
|
50
|
-
Read the root Makefile (and recurse into anything it reaches, same as
|
|
51
|
-
below) and classify every line into one of three link mechanisms —
|
|
52
|
-
this mirrors exactly what make-runner-mcp's own parser does, so a file
|
|
53
|
-
found here is one make-runner-mcp already discovers today:
|
|
54
|
-
|
|
55
|
-
1. **Real include**: a line matching `^\s*(-|s)?include\s+(.+)$`. Each
|
|
56
|
-
whitespace-separated path on the line, resolved relative to the
|
|
57
|
-
*including* file's own directory. A path containing `$(` can't be
|
|
58
|
-
resolved by make-runner-mcp either — note it as **unresolvable
|
|
59
|
-
include** (see Step 4) rather than treating it as reachable.
|
|
60
|
-
2. **Catch-all forwarding**: a rule whose target is bare `%:` (not
|
|
61
|
-
`%.o:` or `docker-%:` — those are ordinary pattern rules, not this
|
|
62
|
-
idiom), whose recipe (the tab-indented lines immediately after it)
|
|
63
|
-
contains `$(MAKE) ... -C <dir>`. Reaches `<dir>/Makefile`. A `-C`
|
|
64
|
-
value containing `$(` similarly can't be resolved — note it the same
|
|
65
|
-
way as an unresolvable include.
|
|
66
|
-
3. **The marker this skill itself manages**: a comment line matching
|
|
67
|
-
`^\s*#{1,2}\s*make-runner:\s*also-read\s+(.+)$`. Each
|
|
68
|
-
whitespace-separated path, resolved the same way as `include`.
|
|
69
|
-
|
|
70
|
-
For every file reached via (1) or (3), recurse into it too — apply the
|
|
71
|
-
same three checks to its contents, since an included/linked file can
|
|
72
|
-
itself `include` or mark further files. (Forwarding targets, (2), are a
|
|
73
|
-
Makefile invoked by a live `$(MAKE)` at build time in a fresh directory
|
|
74
|
-
context, not textually processed further here — don't recurse into them
|
|
75
|
-
for more forwarding/include chains; treat the forwarded file itself as
|
|
76
|
-
reached and stop there, matching what make-runner-mcp's own parser does.)
|
|
77
|
-
|
|
78
|
-
Build the **reached set**: the realpath of every file resolved this way,
|
|
79
|
-
starting from the root Makefile itself.
|
|
80
|
-
|
|
81
|
-
## Step 3: Compute the gap
|
|
82
|
-
|
|
83
|
-
Any candidate secondary Makefile from Step 1 whose realpath is **not** in
|
|
84
|
-
the reached set from Step 2 is **orphaned** — make-runner-mcp cannot see
|
|
85
|
-
its targets right now, regardless of why (never referenced at all, or
|
|
86
|
-
referenced only via an unresolvable `$(VAR)` path).
|
|
87
|
-
|
|
88
|
-
If the gap is empty: report "All Makefiles are already correctly linked —
|
|
89
|
-
nothing to fix" and stop.
|
|
90
|
-
|
|
91
|
-
## Step 4: Fix each orphaned file
|
|
92
|
-
|
|
93
|
-
For each orphaned Makefile, the default and safest fix is to append this
|
|
94
|
-
line to the root Makefile (near any existing `include`/`also-read` lines
|
|
95
|
-
if present, otherwise near the top, after any leading variable
|
|
96
|
-
assignments):
|
|
97
|
-
|
|
98
|
-
```makefile
|
|
99
|
-
## make-runner: also-read <path, relative to the root Makefile's directory>
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
This is a plain comment — it changes nothing about what a human running
|
|
103
|
-
`make` by hand experiences, and it works regardless of *why* the file was
|
|
104
|
-
orphaned. Prefer it over adding a real `include` here: a real `include`
|
|
105
|
-
would need you to verify the whole orphaned file is safe to textually pull
|
|
106
|
-
into the root Makefile's namespace (no colliding variable/target names,
|
|
107
|
-
no assumption about running from a different `cwd`), which is exactly the
|
|
108
|
-
kind of judgment call this skill should not make silently.
|
|
109
|
-
|
|
110
|
-
**Exception — flag instead of auto-fixing:** before applying the marker to
|
|
111
|
-
a given orphaned file, grep its recipes for `$(UPPERCASE_VAR)`-style
|
|
112
|
-
tokens and check whether each one is assigned *only* in the root Makefile
|
|
113
|
-
and not in the orphaned file itself (excluding standard built-ins like
|
|
114
|
-
`$(MAKE)`, `$(CC)`, `$(SHELL)`). If you find one, the `also-read` marker
|
|
115
|
-
would run this file without that variable defined — likely breaking or
|
|
116
|
-
silently changing its recipe. For that file only: don't edit anything,
|
|
117
|
-
add it to a **NEEDS HUMAN DECISION** list in your final report with the
|
|
118
|
-
variable name and where it's defined, and suggest either (a) defining that
|
|
119
|
-
variable directly in the orphaned file too, or (b) using a real `include`
|
|
120
|
-
once a human has verified there's no namespace collision. This is a
|
|
121
|
-
heuristic, not exhaustive — say so.
|
|
122
|
-
|
|
123
|
-
Apply the marker fix for every other orphaned file in one edit to the root
|
|
124
|
-
Makefile (one line per file), then move on.
|
|
125
|
-
|
|
126
|
-
## Step 5: Verify
|
|
127
|
-
|
|
128
|
-
Re-run Step 2's classification by hand against the now-edited root
|
|
129
|
-
Makefile and confirm every previously-orphaned file (other than ones left
|
|
130
|
-
for human decision) now appears in the reached set.
|
|
131
|
-
|
|
132
|
-
If $ARGUMENTS names a local make-runner-mcp checkout (a directory
|
|
133
|
-
containing `server.js`), or `command -v make-runner-mcp` resolves to
|
|
134
|
-
something, run the real thing for a live check instead of trusting your
|
|
135
|
-
own by-hand classification alone:
|
|
136
|
-
|
|
137
|
-
```bash
|
|
138
|
-
PROJECT_DIR="$(pwd)" node <path-to-that-checkout>/server.js --diagnose
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Check its `EXPOSED TARGETS` section lists targets from the newly-linked
|
|
142
|
-
file(s), and its `UNRESOLVED ... PATHS` / `FILES REJECTED` sections are
|
|
143
|
-
empty for the files you just fixed. If no checkout is available, say so in
|
|
144
|
-
the report and note that the by-hand verification above stands in for it.
|
|
145
|
-
|
|
146
|
-
Do **not** invoke any actual `make <target>` to test — that executes real
|
|
147
|
-
recipes, which is outside what this skill is for.
|
|
148
|
-
|
|
149
|
-
## Step 6: Report
|
|
150
|
-
|
|
151
|
-
State plainly, in this shape:
|
|
152
|
-
|
|
153
|
-
```
|
|
154
|
-
MAKEFILES FOUND:
|
|
155
|
-
- <path>: <root | already linked via include/forwarding/also-read | orphaned>
|
|
156
|
-
|
|
157
|
-
FIXED (also-read marker added to root Makefile):
|
|
158
|
-
- <path>
|
|
159
|
-
|
|
160
|
-
NEEDS HUMAN DECISION:
|
|
161
|
-
- <path>: <reason — e.g. "recipe uses $(FOO), only defined in root Makefile">
|
|
162
|
-
|
|
163
|
-
VERIFIED: <"live --diagnose output matches" | "by-hand classification only — no make-runner-mcp checkout available to confirm">
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
Also mention, once, that the `also-read` marker only works with a
|
|
167
|
-
make-runner-mcp version that supports it — if this project's MCP client
|
|
168
|
-
config pins an older release tag, the fix won't take effect until that
|
|
169
|
-
tag is bumped.
|