create-academic-research 0.1.6 → 0.1.7

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
@@ -53,6 +53,9 @@ By default, the wizard:
53
53
  - writes `docs/agent/capability-profile.md`;
54
54
  - writes `docs/agent/mcp-setup.md`;
55
55
  - writes `docs/agent/generated/mcp.json` unless an explicit agent target is set;
56
+ - includes `scripts/README.md` for repeatable command entrypoints;
57
+ - includes reusable `wiki/templates/` pages for sources, claims, experiments,
58
+ decisions, reviewer concerns, and research questions;
56
59
  - appends the onboarding event to `wiki/log.md`;
57
60
  - does not install external MCP tools unless explicitly requested.
58
61
 
@@ -84,6 +87,7 @@ Inside a generated project:
84
87
 
85
88
  ```bash
86
89
  npx academic-research doctor
90
+ npx academic-research setup
87
91
  npx academic-research rename --title "New Title" --slug new-title --package new_title
88
92
  npx academic-research agents list
89
93
  npx academic-research skills presets
@@ -99,15 +103,20 @@ npx academic-research mcp enabled
99
103
  npx academic-research mcp available
100
104
  npx academic-research mcp commands arxiv
101
105
  npx academic-research mcp env openalex semantic-scholar zotero
102
- npx academic-research mcp enable arxiv openalex
106
+ npx academic-research mcp enable arxiv dblp
103
107
  npx academic-research mcp disable arxiv
104
108
  npx academic-research mcp install arxiv
105
109
  npx academic-research mcp uninstall arxiv
110
+ npx academic-research mcp smoke
106
111
  npx academic-research mcp doctor
107
112
  ```
108
113
 
109
114
  ## Command Model
110
115
 
116
+ `academic-research setup` is a non-destructive onboarding status command. It
117
+ prints the active preset, agent, skill counts, enabled MCP records, and next
118
+ commands without changing files.
119
+
111
120
  Skills are project-local by default.
112
121
 
113
122
  | Command | Meaning |
@@ -132,6 +141,7 @@ MCP commands are split by side-effect:
132
141
  | `mcp disable` | Remove an MCP server from project records and generated snippets. |
133
142
  | `mcp install` | Run finite external tool install commands for selected MCP servers. It must not launch stdio MCP servers. |
134
143
  | `mcp uninstall` | Run the external uninstall command when one exists. |
144
+ | `mcp smoke` | Print non-launching readiness diagnostics for enabled or selected MCP servers. |
135
145
  | `mcp doctor` | Validate enabled MCP records, generated snippets, required env vars, and documented manual prerequisites. |
136
146
 
137
147
  ## Companion Skills
@@ -185,6 +195,9 @@ live tools by themselves. Your MCP client must load the generated snippet, and
185
195
  the referenced commands must be available on your machine or runnable through
186
196
  `uvx`/`npx`. `mcp install` only runs finite setup commands such as the arXiv
187
197
  tool install; it deliberately does not launch stdio MCP servers.
198
+ Use `mcp smoke` for a non-launching readiness pass before wiring a client: it
199
+ checks required env vars, manual/local-service status, and whether runtime
200
+ commands are visible on `PATH`.
188
201
 
189
202
  ## Validate This Package
190
203
 
@@ -202,8 +215,8 @@ Releases are tag-driven. Update `package.json` and `package-lock.json`, commit
202
215
  the change, create `vX.Y.Z`, and push the tag:
203
216
 
204
217
  ```bash
205
- git tag -a v0.1.6 -m "v0.1.6"
206
- git push origin main v0.1.6
218
+ git tag -a v0.1.7 -m "v0.1.7"
219
+ git push origin main v0.1.7
207
220
  ```
208
221
 
209
222
  Once the GitHub repository is public, the release workflow validates the tag
package/dist/src/cli.js CHANGED
@@ -1,5 +1,5 @@
1
- import { readFileSync } from "node:fs";
2
- import { basename, dirname, join, resolve } from "node:path";
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { basename, delimiter, dirname, join, resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { assertKnownMcpServers, disableMcpServers, doctorMcpServers, enableMcpServers, DEFAULT_AGENT, installMcpTools, installSkills, listInstalledSkills, mcpToolCommandTexts, readCapabilities, removeSkills, uninstallMcpTools, updateSkills } from "./capabilities.js";
5
5
  import { createProject, doctorProject, renameProject } from "./project.js";
@@ -100,6 +100,8 @@ async function lifecycleMain(argv) {
100
100
  }
101
101
  if (command === "doctor")
102
102
  return doctorCommand(argv.slice(1));
103
+ if (command === "setup")
104
+ return setupCommand(argv.slice(1));
103
105
  if (command === "rename")
104
106
  return renameCommand(argv.slice(1));
105
107
  if (command === "agents")
@@ -125,6 +127,41 @@ async function doctorCommand(argv) {
125
127
  console.log(`OK: ${root}`);
126
128
  return result.ok ? 0 : 1;
127
129
  }
130
+ async function setupCommand(argv) {
131
+ const parsed = parseFlags(argv, ROOT_FLAGS);
132
+ if (flagBool(parsed.flags, "help")) {
133
+ printSetupHelp();
134
+ return 0;
135
+ }
136
+ assertNoArguments(parsed.positionals, "setup");
137
+ const root = resolve(flagString(parsed.flags, "root") ?? ".");
138
+ const project = await doctorProject(root);
139
+ const state = await readCapabilities(root);
140
+ const skills = await listInstalledSkills(root);
141
+ const skillIds = new Set(skills.map((skill) => skill.name));
142
+ console.log("Project Setup");
143
+ console.log(`root\t${root}`);
144
+ console.log(`doctor\t${project.ok ? "ok" : "error"}`);
145
+ console.log(`agent\t${state.agent}`);
146
+ console.log(`preset\t${state.preset}`);
147
+ console.log(`scope\t${state.scope}`);
148
+ console.log(`installed_skill_ids\t${skillIds.size}`);
149
+ console.log(`installed_skill_copies\t${skills.length}`);
150
+ console.log(`mcp_enabled\t${state.mcp_servers.length > 0 ? state.mcp_servers.join(",") : "none"}`);
151
+ if (!project.ok) {
152
+ for (const error of project.errors)
153
+ console.error(`ERROR: ${error}`);
154
+ }
155
+ console.log("");
156
+ console.log("Next Commands");
157
+ console.log(`academic-research skills install --preset ${state.preset}`);
158
+ console.log("academic-research skills status");
159
+ console.log("academic-research mcp list");
160
+ console.log("academic-research mcp env");
161
+ console.log("academic-research mcp smoke");
162
+ console.log("academic-research doctor");
163
+ return project.ok ? 0 : 1;
164
+ }
128
165
  async function renameCommand(argv) {
129
166
  const parsed = parseFlags(argv, RENAME_FLAGS);
130
167
  if (flagBool(parsed.flags, "help")) {
@@ -317,6 +354,24 @@ async function mcpCommand(argv) {
317
354
  console.log(`Ran ${result.count ?? 0} MCP uninstall command(s).`);
318
355
  return 0;
319
356
  }
357
+ if (subcommand === "smoke") {
358
+ assertOnlyOptions(parsed.flags, "mcp smoke", ["root"]);
359
+ const root = resolve(flagString(parsed.flags, "root") ?? ".");
360
+ const state = await readCapabilities(root);
361
+ const explicitSelection = parsed.positionals.length > 0;
362
+ const selected = explicitSelection ? parsed.positionals : state.mcp_servers;
363
+ assertKnownMcpServers(selected);
364
+ const failed = printMcpSmokeDiagnostics(selected);
365
+ if (!explicitSelection) {
366
+ const result = await doctorMcpServers(root);
367
+ for (const error of result.errors)
368
+ console.error(`ERROR: ${error}`);
369
+ for (const warning of result.warnings)
370
+ console.warn(`WARN: ${warning}`);
371
+ return result.ok && !failed ? 0 : 1;
372
+ }
373
+ return failed ? 1 : 0;
374
+ }
320
375
  if (subcommand === "doctor") {
321
376
  assertOnlyOptions(parsed.flags, "mcp doctor", ["root"]);
322
377
  const root = resolve(flagString(parsed.flags, "root") ?? ".");
@@ -476,7 +531,7 @@ function printMissingTargetHelp() {
476
531
  }
477
532
  function printLifecycleHelp() {
478
533
  console.log([
479
- "Usage: academic-research <doctor|rename|agents|skills|mcp>",
534
+ "Usage: academic-research <doctor|setup|rename|agents|skills|mcp>",
480
535
  "",
481
536
  "Manage a generated academic research repository after creation.",
482
537
  "",
@@ -485,6 +540,17 @@ function printLifecycleHelp() {
485
540
  " -v, --version Show package version."
486
541
  ].join("\n"));
487
542
  }
543
+ function printSetupHelp() {
544
+ console.log([
545
+ "Usage: academic-research setup [options]",
546
+ "",
547
+ "Print project onboarding status and next commands without changing files.",
548
+ "",
549
+ "Options:",
550
+ " --root <path> Project root. Default: current directory.",
551
+ " -h, --help Show this help."
552
+ ].join("\n"));
553
+ }
488
554
  function printAgentsHelp() {
489
555
  console.log([
490
556
  "Usage: academic-research agents <list>",
@@ -515,9 +581,9 @@ function printSkillsHelp() {
515
581
  }
516
582
  function printMcpHelp() {
517
583
  console.log([
518
- "Usage: academic-research mcp <list|enabled|available|commands|env|enable|disable|install|uninstall|doctor> [servers...]",
584
+ "Usage: academic-research mcp <list|enabled|available|commands|env|enable|disable|install|uninstall|smoke|doctor> [servers...]",
519
585
  "",
520
- "Manage MCP records and finite external MCP tool installs.",
586
+ "Manage MCP records, readiness checks, and finite external MCP tool installs.",
521
587
  "",
522
588
  "Options:",
523
589
  " --root <path> Project root for project-state commands.",
@@ -525,6 +591,32 @@ function printMcpHelp() {
525
591
  " -h, --help Show this help."
526
592
  ].join("\n"));
527
593
  }
594
+ function printMcpSmokeDiagnostics(servers) {
595
+ let failed = false;
596
+ console.log("id\tstatus\truntime\tcheck");
597
+ for (const name of servers) {
598
+ const server = AGENT_STACK.mcp_servers[name];
599
+ const missingRequired = server.required_env.filter((envName) => !process.env[envName]);
600
+ if (missingRequired.length > 0)
601
+ failed = true;
602
+ const runtime = server.command ? [server.command, ...server.args].join(" ") : "manual setup";
603
+ let status = "manual";
604
+ if (missingRequired.length > 0) {
605
+ status = `missing-required-env:${missingRequired.join(",")}`;
606
+ }
607
+ else if (server.command && commandExists(server.command)) {
608
+ status = "runtime-found";
609
+ }
610
+ else if (server.command) {
611
+ status = "runtime-missing";
612
+ }
613
+ else if (server.local_service) {
614
+ status = "manual-local-service";
615
+ }
616
+ console.log(`${name}\t${status}\t${runtime}\t${server.smoke_test}`);
617
+ }
618
+ return failed;
619
+ }
528
620
  function printMcpEnvironment(servers) {
529
621
  for (const name of servers) {
530
622
  const server = AGENT_STACK.mcp_servers[name];
@@ -553,6 +645,25 @@ function printMcpEnvironment(servers) {
553
645
  console.log(`${name}\tnone\t-`);
554
646
  }
555
647
  }
648
+ function commandExists(command) {
649
+ if (!command)
650
+ return false;
651
+ if (command.includes("/") || command.includes("\\"))
652
+ return existsSync(command);
653
+ const pathValue = process.env.PATH ?? "";
654
+ const extensions = process.platform === "win32"
655
+ ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";")
656
+ : [""];
657
+ for (const directory of pathValue.split(delimiter).filter(Boolean)) {
658
+ for (const extension of extensions) {
659
+ const hasExtension = extension && command.toLowerCase().endsWith(extension.toLowerCase());
660
+ const candidate = join(directory, hasExtension ? command : `${command}${extension}`);
661
+ if (existsSync(candidate))
662
+ return true;
663
+ }
664
+ }
665
+ return false;
666
+ }
556
667
  function readPackageVersion() {
557
668
  try {
558
669
  const packageJson = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
@@ -138,10 +138,17 @@ export async function doctorProject(root) {
138
138
  "docs/agent/capability-profile.md",
139
139
  "docs/agent/mcp-setup.md",
140
140
  "docs/agent/generated",
141
+ "scripts/README.md",
141
142
  "sources/source-ledger.csv",
142
143
  "sota/literature-matrix.csv",
143
144
  "wiki/index.md",
144
- "wiki/log.md"
145
+ "wiki/log.md",
146
+ "wiki/templates/source-page.md",
147
+ "wiki/templates/claim-page.md",
148
+ "wiki/templates/experiment-page.md",
149
+ "wiki/templates/decision-record.md",
150
+ "wiki/templates/reviewer-concern.md",
151
+ "wiki/templates/research-question.md"
145
152
  ];
146
153
  for (const relative of required) {
147
154
  if (!(await exists(join(target, relative))))
@@ -207,7 +214,7 @@ async function writeGeneratedPackageJson(root, { slug }) {
207
214
  const path = join(root, "package.json");
208
215
  const data = await readJson(path);
209
216
  const existingSpec = data.devDependencies?.["create-academic-research"];
210
- const packageSpec = process.env.CREATE_ACADEMIC_RESEARCH_PACKAGE_SPEC ?? existingSpec ?? "0.1.6";
217
+ const packageSpec = process.env.CREATE_ACADEMIC_RESEARCH_PACKAGE_SPEC ?? existingSpec ?? "0.1.7";
211
218
  data.name = slug;
212
219
  data.devDependencies = {
213
220
  ...(data.devDependencies ?? {}),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-academic-research",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Create and manage agent-ready academic research repositories.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -6,7 +6,8 @@ scholarly record.
6
6
  ## Core Rules
7
7
 
8
8
  - Preserve source originals under `sources/`, `data/raw/`, and `data/external/`.
9
- - Keep reusable logic in `src/`; keep notebooks for exploration and narrative output.
9
+ - Keep reusable logic in `src/`; keep `scripts/` as thin repeatable entrypoints.
10
+ - Keep notebooks for exploration and narrative output.
10
11
  - Tie claims to sources, datasets, experiment records, or decision records.
11
12
  - Update durable records when project knowledge changes.
12
13
  - Keep large data, generated caches, credentials, and private review material out of git.
@@ -35,6 +36,8 @@ scholarly record.
35
36
  - `wiki/synthesis.md` changes only when the project-level interpretation changes.
36
37
  - `wiki/open_questions.md` tracks unresolved questions.
37
38
  - `wiki/contradictions.md` tracks conflicts across sources, data, or runs.
39
+ - `wiki/templates/` contains reusable source, claim, experiment, decision,
40
+ reviewer-concern, and research-question page structures.
38
41
 
39
42
  ## Evidence
40
43
 
@@ -45,3 +48,4 @@ scholarly record.
45
48
  - Citation issues go in `sources/bib/citation-audit.csv`.
46
49
  - SOTA records go in `sota/`.
47
50
  - Curated experiment records go in `experiments/`.
51
+ - Repeatable command entrypoints go in `scripts/`.
@@ -41,6 +41,7 @@ npx academic-research doctor
41
41
  - `docs/agent/`: active agent workflows, capability profile, and MCP setup.
42
42
  - `docs/methodology/`: research design, evaluation plan, and validity threats.
43
43
  - `experiments/`: curated experiment registry and run records.
44
+ - `scripts/`: thin repeatable entrypoints that call reusable code in `src/`.
44
45
  - `notebooks/`: optional exploratory and narrative notebooks.
45
46
  - `outputs/`: final figures, tables, models, and paper-supporting derived assets.
46
47
  - `reports/`: proposal, paper, slides, reviews, and rebuttal material.
@@ -58,11 +59,13 @@ npx academic-research skills install --preset default
58
59
  npx academic-research skills install --preset enhanced
59
60
  npx academic-research skills list
60
61
  npx academic-research skills status
62
+ npx academic-research setup
61
63
  npx academic-research mcp list
62
64
  npx academic-research mcp env openalex semantic-scholar zotero
63
65
  npx academic-research mcp enable arxiv dblp
64
66
  npx academic-research mcp commands arxiv
65
67
  npx academic-research mcp install arxiv
68
+ npx academic-research mcp smoke
66
69
  npx academic-research mcp doctor
67
70
  ```
68
71
 
@@ -74,6 +77,12 @@ enable optional servers. `mcp install` runs only finite tool installation
74
77
  commands; runtime-only `uvx`/`npx` MCP servers may have no install step and are
75
78
  started later by the MCP client.
76
79
 
80
+ `setup` prints the current project capability state, installed skill counts,
81
+ enabled MCP records, and the next onboarding commands without changing files.
82
+ `mcp smoke` performs a non-launching MCP readiness check: it reports required
83
+ env vars, local/manual setup, and whether client runtime commands such as `uvx`
84
+ or `npx` are available.
85
+
77
86
  `default` installs the companion academic research skill package and keeps the
78
87
  MCP records focused on low-friction arXiv discovery. `literature` and `full`
79
88
  add DBLP for computer science bibliography. Credentialed, local-service, or
@@ -4,15 +4,17 @@
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "doctor": "academic-research doctor",
7
+ "setup": "academic-research setup",
7
8
  "skills:install": "academic-research skills install --preset default",
8
9
  "skills:list": "academic-research skills list",
9
10
  "skills:presets": "academic-research skills presets",
10
11
  "mcp:list": "academic-research mcp list",
11
12
  "mcp:commands": "academic-research mcp commands",
12
13
  "mcp:env": "academic-research mcp env",
14
+ "mcp:smoke": "academic-research mcp smoke",
13
15
  "mcp:doctor": "academic-research mcp doctor"
14
16
  },
15
17
  "devDependencies": {
16
- "create-academic-research": "0.1.6"
18
+ "create-academic-research": "0.1.7"
17
19
  }
18
20
  }
@@ -0,0 +1,10 @@
1
+ # Scripts
2
+
3
+ Use this folder for thin, repeatable command entrypoints.
4
+
5
+ Scripts should orchestrate project code, not contain core scientific logic. Put
6
+ reusable methods, models, data transforms, and analysis functions in `src/`.
7
+
8
+ Each script should make its inputs, outputs, config path, and expected side
9
+ effects clear enough to reproduce later from `docs/reproducibility/` or an
10
+ experiment record.
@@ -8,6 +8,7 @@ def test_core_research_structure_exists() -> None:
8
8
  "configs/default.yaml",
9
9
  "configs/capabilities.yaml",
10
10
  "docs/agent/capability-profile.md",
11
+ "scripts/README.md",
11
12
  "notebooks/README.md",
12
13
  "outputs/figures",
13
14
  "outputs/tables",
@@ -21,5 +22,11 @@ def test_core_research_structure_exists() -> None:
21
22
  "sota/literature-matrix.csv",
22
23
  "wiki/index.md",
23
24
  "wiki/log.md",
25
+ "wiki/templates/source-page.md",
26
+ "wiki/templates/claim-page.md",
27
+ "wiki/templates/experiment-page.md",
28
+ "wiki/templates/decision-record.md",
29
+ "wiki/templates/reviewer-concern.md",
30
+ "wiki/templates/research-question.md",
24
31
  ):
25
32
  assert (root / relative).exists()
@@ -7,3 +7,12 @@ This is the content index for the LLM-maintained project wiki.
7
7
  - [[synthesis]]
8
8
  - [[open_questions]]
9
9
  - [[contradictions]]
10
+
11
+ ## Templates
12
+
13
+ - [[templates/source-page]]
14
+ - [[templates/claim-page]]
15
+ - [[templates/experiment-page]]
16
+ - [[templates/decision-record]]
17
+ - [[templates/reviewer-concern]]
18
+ - [[templates/research-question]]
@@ -0,0 +1,24 @@
1
+ # Claim: <claim_id>
2
+
3
+ ## Claim
4
+
5
+ <fill: atomic claim>
6
+
7
+ ## Status
8
+
9
+ - Verdict:
10
+ - Confidence:
11
+ - Last checked:
12
+
13
+ ## Evidence
14
+
15
+ | source_or_run_id | path | support_span | verdict | notes |
16
+ |---|---|---|---|---|
17
+
18
+ ## Safe Wording
19
+
20
+ <fill: wording that current evidence supports>
21
+
22
+ ## Risk
23
+
24
+ <fill: what would weaken, falsify, or narrow this claim>
@@ -0,0 +1,26 @@
1
+ # Decision: <decision_id>
2
+
3
+ ## Context
4
+
5
+ <fill: situation and constraints>
6
+
7
+ ## Decision
8
+
9
+ <fill: chosen option>
10
+
11
+ ## Alternatives Considered
12
+
13
+ | option | reason rejected |
14
+ |---|---|
15
+
16
+ ## Evidence
17
+
18
+ - Sources:
19
+ - Experiments:
20
+ - Reviews:
21
+
22
+ ## Consequences
23
+
24
+ - Expected benefit:
25
+ - Risk:
26
+ - Review date:
@@ -0,0 +1,30 @@
1
+ # Experiment: <run_id>
2
+
3
+ ## Question
4
+
5
+ <fill: research question or hypothesis>
6
+
7
+ ## Run
8
+
9
+ - Date:
10
+ - Git commit:
11
+ - Command:
12
+ - Config:
13
+ - Seed:
14
+ - Dataset:
15
+ - Metric:
16
+ - Output path:
17
+
18
+ ## Result
19
+
20
+ <fill: measured outcome>
21
+
22
+ ## Interpretation
23
+
24
+ <fill: claim status, limitations, and next action>
25
+
26
+ ## Links
27
+
28
+ - Registry row: `experiments/registry.csv`
29
+ - Related claims:
30
+ - Related sources:
@@ -0,0 +1,27 @@
1
+ # Research Question: <rq_id>
2
+
3
+ ## Question
4
+
5
+ <fill: answerable research question>
6
+
7
+ ## Scope
8
+
9
+ - Population/domain:
10
+ - Evidence type:
11
+ - Exclusions:
12
+
13
+ ## Contribution Link
14
+
15
+ - Candidate claim:
16
+ - Closest prior work:
17
+ - Delta:
18
+ - Failure condition:
19
+
20
+ ## Evidence Plan
21
+
22
+ | evidence_needed | path_or_source | status | risk |
23
+ |---|---|---|---|
24
+
25
+ ## Current Status
26
+
27
+ <fill: hypothesis, active, answered, rejected, or out of scope>
@@ -0,0 +1,25 @@
1
+ # Reviewer Concern: <concern_id>
2
+
3
+ ## Concern
4
+
5
+ <fill: reviewer or internal-review concern>
6
+
7
+ ## Classification
8
+
9
+ - Source:
10
+ - Severity:
11
+ - Paper location:
12
+ - Claim or issue:
13
+ - Action: concede | clarify | add-evidence | reframe | defend | defer
14
+
15
+ ## Evidence
16
+
17
+ <fill: source, experiment, or manuscript evidence>
18
+
19
+ ## Response Plan
20
+
21
+ <fill: exact response and manuscript change>
22
+
23
+ ## Status
24
+
25
+ <fill: open, addressed, deferred, rejected with rationale>
@@ -0,0 +1,31 @@
1
+ # Source: <source_id>
2
+
3
+ ## Bibliographic Record
4
+
5
+ - Title:
6
+ - Authors:
7
+ - Year:
8
+ - Venue:
9
+ - Identifiers:
10
+ - Native path:
11
+ - Derived path:
12
+ - Metadata path:
13
+
14
+ ## Summary
15
+
16
+ <fill: concise source summary>
17
+
18
+ ## Evidence Record
19
+
20
+ - Supports:
21
+ - Contradicts:
22
+ - Method / data / metric:
23
+ - Limitations:
24
+ - Project relevance:
25
+ - Claim strength:
26
+ - Allowed wording:
27
+ - Forbidden stronger wording:
28
+
29
+ ## Follow-Up
30
+
31
+ - <fill: unresolved checks>
File without changes