spacekid 0.0.0-stage → 0.1.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.
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const { main } = require('../src/cli');
5
+
6
+ process.exitCode = main(process.argv.slice(2));
package/package.json CHANGED
@@ -1,6 +1,29 @@
1
1
  {
2
2
  "name": "spacekid",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "A minimalist spec kit for agentic development.",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "spacekid": "bin/spacekid.js"
8
+ },
9
+ "main": "src/index.js",
10
+ "types": "types/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./types/index.d.ts",
14
+ "default": "./src/index.js"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
18
+ "files": [
19
+ "bin",
20
+ "src",
21
+ "types"
22
+ ],
23
+ "engines": {
24
+ "node": ">=20.0.0"
25
+ },
26
+ "scripts": {
27
+ "test": "node --test"
28
+ }
29
+ }
package/src/cli.js ADDED
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const { parseArgs } = require('node:util');
5
+
6
+ const { scaffold } = require('./scaffold');
7
+
8
+ const STATUS_LABEL = {
9
+ created: 'created',
10
+ appended: 'appended to',
11
+ skipped: 'skipped (already exists)',
12
+ };
13
+
14
+ const USAGE = `usage: spacekid init [--path <dir>] [--name <name>]
15
+
16
+ init scaffold the SpaceKid AGENTS.md cycle in a project
17
+ `;
18
+
19
+ function init(args) {
20
+ const { values } = parseArgs({
21
+ args,
22
+ options: {
23
+ path: { type: 'string', default: '.' },
24
+ name: { type: 'string' },
25
+ },
26
+ allowPositionals: false,
27
+ });
28
+
29
+ const projectRoot = path.resolve(values.path);
30
+ for (const result of scaffold(projectRoot, values.name)) {
31
+ console.log(`${STATUS_LABEL[result.status]}: ${path.relative(projectRoot, result.path)}`);
32
+ }
33
+ return 0;
34
+ }
35
+
36
+ function main(argv) {
37
+ const [command, ...rest] = argv;
38
+ if (command !== 'init') {
39
+ process.stderr.write(USAGE);
40
+ return 1;
41
+ }
42
+ try {
43
+ return init(rest);
44
+ } catch (err) {
45
+ process.stderr.write(`spacekid: ${err.message}\n${USAGE}`);
46
+ return 1;
47
+ }
48
+ }
49
+
50
+ module.exports = { main };
package/src/index.js ADDED
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = require('./scaffold');
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+
6
+ const APP_NAME_PLACEHOLDER = '{{APP_NAME}}';
7
+ const TEMPLATES_DIR = path.join(__dirname, 'templates');
8
+
9
+ function loadTemplate(filename) {
10
+ return fs.readFileSync(path.join(TEMPLATES_DIR, filename), 'utf8');
11
+ }
12
+
13
+ function detectAppName(projectRoot) {
14
+ const manifest = path.join(projectRoot, 'package.json');
15
+ if (fs.existsSync(manifest)) {
16
+ try {
17
+ const { name } = JSON.parse(fs.readFileSync(manifest, 'utf8'));
18
+ if (typeof name === 'string' && name.length > 0) {
19
+ return name;
20
+ }
21
+ } catch {
22
+ // Unreadable or malformed package.json: fall back to the directory name.
23
+ }
24
+ }
25
+ return path.basename(path.resolve(projectRoot));
26
+ }
27
+
28
+ function renderRootAgents(appName) {
29
+ return loadTemplate('root-agents.md').split(APP_NAME_PLACEHOLDER).join(appName);
30
+ }
31
+
32
+ function writeOrSkip(filePath, content) {
33
+ if (fs.existsSync(filePath)) {
34
+ return { path: filePath, status: 'skipped' };
35
+ }
36
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
37
+ fs.writeFileSync(filePath, content, 'utf8');
38
+ return { path: filePath, status: 'created' };
39
+ }
40
+
41
+ function writeOrAppend(filePath, content) {
42
+ if (fs.existsSync(filePath)) {
43
+ fs.appendFileSync(filePath, '\n' + content, 'utf8');
44
+ return { path: filePath, status: 'appended' };
45
+ }
46
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
47
+ fs.writeFileSync(filePath, content, 'utf8');
48
+ return { path: filePath, status: 'created' };
49
+ }
50
+
51
+ function scaffold(projectRoot, appName) {
52
+ const root = path.resolve(projectRoot);
53
+ const resolvedName = appName || detectAppName(root);
54
+
55
+ return [
56
+ writeOrSkip(path.join(root, 'AGENTS.md'), renderRootAgents(resolvedName)),
57
+ writeOrAppend(path.join(root, 'specs', 'AGENTS.md'), loadTemplate('specs-agents.md')),
58
+ writeOrAppend(path.join(root, 'plans', 'AGENTS.md'), loadTemplate('plans-agents.md')),
59
+ ];
60
+ }
61
+
62
+ module.exports = {
63
+ detectAppName,
64
+ renderRootAgents,
65
+ writeOrSkip,
66
+ writeOrAppend,
67
+ scaffold,
68
+ };
@@ -0,0 +1,62 @@
1
+ # AGENTS.md — Writing Implementation Plans
2
+
3
+ A plan translates a spec into a **technical design**: how it will be built,
4
+ with the highest quality and best software engineering practices.
5
+
6
+ Follow the same writing discipline as `specs/AGENTS.md` — concise, clear,
7
+ no fluff — applied here to engineering rather than business content.
8
+
9
+ ## Guiding principles
10
+
11
+ - **KISS.** The simplest design that correctly satisfies the spec wins.
12
+ Well-executed simplicity beats clever complexity every time.
13
+ - **SOLID.** Apply these principles where they add real value — not as
14
+ ceremony.
15
+ - **Scalability & maintainability.** Design for the load and change patterns
16
+ the spec actually implies, not speculative future needs. Don't build for
17
+ hypothetical requirements.
18
+
19
+ ## Rules
20
+
21
+ - **One plan per spec**, named identically: `plans/<name>.md` implements
22
+ `specs/<name>.md`.
23
+ - **This file may reference its spec** — it should open by linking to
24
+ `specs/<name>.md`. This is the only direction references flow: specs never
25
+ reference plans.
26
+ - **English only.**
27
+
28
+ ## Structure
29
+
30
+ ```markdown
31
+ # <Feature Name> — Implementation Plan
32
+
33
+ Implements: `specs/<name>.md`
34
+ Status: Draft | Approved | In Progress | Done
35
+
36
+ ## Approach
37
+ The chosen technical approach and why it's the simplest one that satisfies
38
+ the spec.
39
+
40
+ ## Steps
41
+ Ordered, concrete implementation steps.
42
+
43
+ ## Key Decisions
44
+ Notable design/architecture choices and their trade-offs (only if non-obvious).
45
+
46
+ ## Implementation Notes
47
+ Filled in after the work is done: what changed vs. the original plan, and
48
+ why (edge cases found, constraints discovered, simplifications made).
49
+ ```
50
+
51
+ ## After implementation — mandatory
52
+
53
+ As soon as the implementation is finished:
54
+
55
+ 1. Set `Status: Done`.
56
+ 2. Fill in **Implementation Notes** with any deviation from the original plan
57
+ and the reason for it.
58
+ 3. Go back to `specs/<name>.md` and update its status per `specs/AGENTS.md`.
59
+ 4. If this work affected the behavior of any other already-implemented
60
+ spec/plan pair, update those too.
61
+
62
+ Never consider a task finished while this update step is pending.
@@ -0,0 +1,49 @@
1
+ # Agent Guide — {{APP_NAME}}
2
+
3
+ ## Project Overview
4
+
5
+ <!--
6
+ AGENT TODO: This section is a placeholder. Replace it as soon as you have
7
+ enough context about this specific project — its purpose, its intended
8
+ users, and any key constraints or decisions that shape it. Do this the
9
+ first time you work on a real feature here, not before you actually know
10
+ the answers. Once this section reflects the real project, delete this
11
+ comment block; a placeholder left in place after that point is a bug in
12
+ this file, not a feature.
13
+ -->
14
+
15
+ _Not yet described. Fill in what this project does, who it's for, and any
16
+ constraints that matter before writing the first spec._
17
+
18
+ ## Purpose
19
+
20
+ This file orients any agent working in this repository. It maps where the rules live and defines the mandatory cycle that connects business intent, engineering planning, and implementation.
21
+
22
+ ## Project Map
23
+
24
+ - `AGENTS.md` (this file) — the map, the cycle, and this project's overview.
25
+ - `specs/AGENTS.md` — how to write a spec. Read this before writing or editing anything in `specs/`.
26
+ - `specs/*.md` — one spec per feature. Business-only, self-contained.
27
+ - `plans/AGENTS.md` — how to write an implementation plan. Read this before writing or editing anything in `plans/`.
28
+ - `plans/*.md` — one implementation plan per feature, paired with its spec by matching slug (e.g. `specs/foo-spec.md` ↔ `plans/foo-plan.md`).
29
+ - This project's own architecture or coding-convention guide, if one has been added — read it before writing or editing implementation code.
30
+
31
+ ## The Cycle
32
+
33
+ Every non-trivial feature must flow through these steps, in order:
34
+
35
+ 1. **Spec.** Write or update a spec in `specs/`, following `specs/AGENTS.md`. It captures the business problem, what must be delivered, and acceptance criteria — nothing about how.
36
+ 2. **Plan.** Write or update an implementation plan in `plans/`, following `plans/AGENTS.md`. It references the spec and lays out the engineering approach.
37
+ 3. **Implementation.** Build the feature following the plan and this project's own conventions.
38
+ 4. **Close the loop.** As soon as implementation finishes:
39
+ - Update the plan's Status and its Adaptations Log with anything that changed from the original plan during the build.
40
+ - Update the spec's Status to reflect that it is now implemented.
41
+ 5. **Stay current.** If later work touches an area already covered by an existing spec or plan — even when that wasn't the original goal of the task — revisit and update those files too, so they never go stale.
42
+
43
+ ## Rules Agents Must Never Break
44
+
45
+ - Never implement a non-trivial feature without a spec in `specs/` and a plan in `plans/` already in place.
46
+ - Never finish an implementation task without updating the Status of both the plan and its spec.
47
+ - Never let a spec or plan go stale after a related change lands elsewhere in the codebase — step 5 is not optional.
48
+ - Never write a spec that contains implementation details, or a plan that skips referencing its spec.
49
+ - Never leave the Project Overview placeholder above unfilled once the project's purpose is actually known.
@@ -0,0 +1,55 @@
1
+ # AGENTS.md — Writing Specs
2
+
3
+ A spec captures the **business intent** of a feature: why it exists, what it
4
+ must do, and how we know it's done. Nothing more.
5
+
6
+ ## Rules
7
+
8
+ - **Self-contained.** A reader must understand the full spec without opening
9
+ any other file. Do not reference other specs, plans, code files, or paths.
10
+ - **No implementation detail.** No code, no technology choices, no
11
+ architecture, no data models. That belongs exclusively in the matching
12
+ `plans/<name>.md`.
13
+ - **Concise and clear.** Say only what's needed to preserve the core idea.
14
+ Prefer short sentences and bullet lists over long prose. Cut anything that
15
+ doesn't change what gets built or how it's accepted.
16
+ - **Business-only scope.** A spec centralizes business points: context,
17
+ problem, what must be delivered, and acceptance criteria. It does not
18
+ belong to engineering.
19
+ - **English only.**
20
+
21
+ ## Structure
22
+
23
+ ```markdown
24
+ # <Feature Name>
25
+
26
+ Status: Draft | Approved | Implemented
27
+
28
+ ## Context
29
+ Why this is needed. The problem or opportunity, in business terms.
30
+
31
+ ## Requirements
32
+ What must exist or happen once this is delivered. Plain, unambiguous
33
+ statements — no solution design.
34
+
35
+ ## Acceptance Criteria
36
+ A checklist of verifiable conditions that define "done".
37
+
38
+ ## Out of Scope
39
+ What this spec explicitly does not cover (optional, only if it prevents
40
+ ambiguity).
41
+ ```
42
+
43
+ ## What happens next
44
+
45
+ The implementation plan for this spec is written in `plans/<name>.md`
46
+ (same `<name>`), following `plans/AGENTS.md`. The plan file is the only place
47
+ allowed to reference this spec — this spec must never reference the plan or
48
+ any code.
49
+
50
+ ## Status updates
51
+
52
+ Once the feature is implemented, the `Status` field here must be updated to
53
+ `Implemented`. If real-world constraints forced any acceptance criteria to
54
+ change during implementation, update this file to reflect what was actually
55
+ delivered.
@@ -0,0 +1,10 @@
1
+ export interface FileResult {
2
+ path: string;
3
+ status: 'created' | 'appended' | 'skipped';
4
+ }
5
+
6
+ export function detectAppName(projectRoot: string): string;
7
+ export function renderRootAgents(appName: string): string;
8
+ export function writeOrSkip(filePath: string, content: string): FileResult;
9
+ export function writeOrAppend(filePath: string, content: string): FileResult;
10
+ export function scaffold(projectRoot: string, appName?: string): FileResult[];
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.