@zalom/plastic 1.0.0-alpha.18 → 1.0.0-alpha.19

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
@@ -4,9 +4,9 @@
4
4
  > Install: `npx @zalom/plastic@alpha --claude`
5
5
 
6
6
  Intent-driven idea development system for AI coding agents. Named after
7
- **neuroplasticity** adaptive, malleable, dynamic, resilient.
7
+ **neuroplasticity**: adaptive, malleable, dynamic, resilient.
8
8
 
9
- Plastic thinks in **intents**, not tasks. An intent is a desire something
9
+ Plastic thinks in **intents**, not tasks. An intent is a desire, something
10
10
  you want to accomplish, explore, or understand. Intents are atomic thoughts
11
11
  that get developed through two nested processes.
12
12
 
@@ -20,18 +20,53 @@ This loop runs continuously across sessions.
20
20
  from motivation through specification, planning, to delivery. Intents produce
21
21
  artifacts: `spec.md`, `plan.md`, `checklist.md`, `outcome.md`.
22
22
 
23
+ ## How Plastic Works
24
+
25
+ Plastic is a **thinking system**, a blueprint for taking a desire from intent to
26
+ delivery. It splits the work in two:
27
+
28
+ - **The blueprint (deterministic).** The conventions, templates, directory structure,
29
+ lifecycle, and linking rules. This is *how to fill in the work*, and it comes out
30
+ identically no matter who or what is working.
31
+ - **The brain (non-deterministic).** The human or LLM that does the actual thinking.
32
+ Plastic never replaces it. It only **steers and validates** it.
33
+
34
+ Determinism lives in the **form** of the work (section sets, ordering, schemas, naming,
35
+ IDs, file layout), never in the brain's reasoning. The framework stays constant while the
36
+ thinking varies. Run Plastic on Claude Code, Codex, Hermes, OpenClaw, or by hand on paper
37
+ in Obsidian or Word, and the only thing that changes is the *quality of thought*. The
38
+ proof is the paper test: if a person with no tooling and no AI can reproduce a
39
+ correctly-shaped intent, the determinism is in the form, not the agent.
40
+
41
+ **Deterministic by design, free by intent.** The rigid part is rigid on purpose. It is
42
+ what makes work portable, reviewable, and resumable across any agent. The free part is
43
+ free on purpose. It is where the brain's creativity lives. Plastic draws the line between
44
+ the two and holds it.
45
+
46
+ **Harnesses are how it holds the line.** Shared harnesses (conventions, templates, and
47
+ directory structure) constrain humans and agents alike. Agent-extra harnesses (evals that
48
+ check a skill's output, plus hooks and instructions that steer reasoning) give an agent
49
+ the instincts a careful person already has: stop and save state, leave a note when the
50
+ context runs out, never plan before specifying.
51
+
52
+ This is **intent-driven delivery**, a new shape for the software lifecycle in the age of
53
+ agentic engineering. The unit of work is an *intent*, not a ticket, and every intent
54
+ carries its own spec, plan, checklist, and outcome as it moves through Why, What, How, and
55
+ Execute. What you get is agent-agnostic, auditable, and additive: a knowledge graph of
56
+ *why* things were built, not just what.
57
+
23
58
  ## Install
24
59
 
25
60
  Plastic requires Ruby (pre-installed on macOS/Linux) and Node.js 18+.
26
61
 
27
62
  ```bash
28
- # Alpha (current active development)
63
+ # Alpha (current, active development)
29
64
  npx @zalom/plastic@alpha --claude
30
65
 
31
- # Beta (when available API-stable, bug hunting)
66
+ # Beta (when available, API-stable, bug hunting)
32
67
  npx @zalom/plastic@beta --claude
33
68
 
34
- # Stable (when available general use)
69
+ # Stable (when available, general use)
35
70
  npx @zalom/plastic --claude
36
71
  ```
37
72
 
@@ -42,7 +77,7 @@ Bun users can substitute `bunx` for `npx` (e.g. `bunx @zalom/plastic@alpha --cla
42
77
  Bun is never required.
43
78
 
44
79
  Skills install as flat, hyphen-namespaced personal skills (`plastic-doctor`,
45
- `plastic-auto`, ) invoke them with a hyphen. Plastic is **not** a Claude Code
80
+ `plastic-auto`, and so on). Invoke them with a hyphen. Plastic is **not** a Claude Code
46
81
  plugin; re-running the installer auto-removes any legacy plugin registration.
47
82
 
48
83
  ### Updating
@@ -68,6 +103,13 @@ After installation, run `/clear` to load Plastic conventions, then:
68
103
 
69
104
  Or say "auto" to let the agent handle the full lifecycle autonomously.
70
105
 
106
+ ## Documentation
107
+
108
+ - [`docs/architecture.md`](docs/architecture.md): system structure, the two
109
+ processes, the store layout, and the component map.
110
+ - [`docs/internals.md`](docs/internals.md): how Plastic stays deterministic, the
111
+ determinism breakdown, and the harness system.
112
+
71
113
  ## Conventions
72
114
 
73
115
  All conventions live in `AGENTS.md`, distributed to `~/.plastic/AGENTS.md`
package/bin/plastic.js ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Thin shim — npx entry point that dispatches a subcommand to the matching Ruby verb script.
4
+ // All logic lives in scripts/<verb>.rb. JS is only the distribution + dispatch mechanism.
5
+ //
6
+ // npx @zalom/plastic install [flags]
7
+ // npx @zalom/plastic update [flags]
8
+ // npx @zalom/plastic uninstall [flags]
9
+ // npx @zalom/plastic versions [flags]
10
+ //
11
+ // Back-compat: a bare `--uninstall` (no subcommand) routes to uninstall with a deprecation
12
+ // warning; no subcommand at all defaults to install (legacy behaviour, one release).
13
+
14
+ import { execFileSync } from 'node:child_process'
15
+ import { resolve } from 'node:path'
16
+ import { existsSync } from 'node:fs'
17
+
18
+ const VERBS = ['install', 'update', 'uninstall', 'versions']
19
+ const packageRoot = new URL('..', import.meta.url).pathname
20
+ const argv = process.argv.slice(2)
21
+
22
+ let verb
23
+ let rest
24
+
25
+ if (VERBS.includes(argv[0])) {
26
+ verb = argv[0]
27
+ rest = argv.slice(1)
28
+ } else if (argv.includes('--uninstall')) {
29
+ // Deprecated: `--uninstall` as a flag instead of the `uninstall` subcommand.
30
+ console.error('! plastic: `--uninstall` is deprecated — use `npx @zalom/plastic uninstall`. (works for now)')
31
+ verb = 'uninstall'
32
+ rest = argv.filter((a) => a !== '--uninstall')
33
+ } else {
34
+ // No subcommand: legacy default to install (one release of grace).
35
+ verb = 'install'
36
+ rest = argv
37
+ }
38
+
39
+ const script = resolve(packageRoot, 'scripts', `${verb}.rb`)
40
+
41
+ if (!existsSync(script)) {
42
+ console.error(`Error: scripts/${verb}.rb not found in package.`)
43
+ process.exit(1)
44
+ }
45
+
46
+ try {
47
+ execFileSync('ruby', [script, ...rest], {
48
+ stdio: 'inherit',
49
+ env: { ...process.env, PLASTIC_PACKAGE_ROOT: packageRoot },
50
+ })
51
+ } catch (err) {
52
+ if (err.status) process.exit(err.status)
53
+ console.error('Error: Ruby is required to run Plastic.')
54
+ console.error(' macOS: Ruby is pre-installed')
55
+ console.error(' Linux: sudo apt install ruby / dnf install ruby')
56
+ process.exit(1)
57
+ }
package/bin/test ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # frozen_string_literal: true
4
+
5
+ # Runs the FULL Minitest suite in a single process.
6
+ #
7
+ # `release.verify` used to be `ruby -Itest test/*_test.rb`, but Ruby runs only
8
+ # the first glob-expanded file as the program — the rest land in ARGV and are
9
+ # never required. The release gate exercised one test file, reported green, and
10
+ # let releases ship over real failures (intent 30). Pointing verify at this
11
+ # script keeps the runner in version control and guarantees every test file is
12
+ # loaded.
13
+
14
+ root = File.expand_path("..", __dir__)
15
+
16
+ files = Dir.glob(File.join(root, "test", "**", "*_test.rb")).sort
17
+ abort "No test files found under #{File.join(root, "test")}" if files.empty?
18
+
19
+ # `bin/test --list` prints the discovered files without running them, so the
20
+ # discovery logic can be tested cheaply (no full-suite execution).
21
+ if ARGV.delete("--list")
22
+ puts files.map { |f| f.sub("#{root}/", "") }
23
+ exit 0
24
+ end
25
+
26
+ $LOAD_PATH.unshift File.join(root, "test")
27
+ require "minitest/autorun"
28
+ files.each { |f| require f }
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
3
+ exec ruby "$SCRIPT_DIR/../scripts/hook-bash-gate"
package/hooks/hooks.json CHANGED
@@ -39,6 +39,16 @@
39
39
  "statusMessage": "Checking lifecycle gate..."
40
40
  }
41
41
  ]
42
+ },
43
+ {
44
+ "matcher": "Bash",
45
+ "hooks": [
46
+ {
47
+ "type": "command",
48
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook\" bash-gate",
49
+ "statusMessage": "Checking lifecycle gate..."
50
+ }
51
+ ]
42
52
  }
43
53
  ],
44
54
  "PostToolUse": [
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@zalom/plastic",
3
- "version": "1.0.0-alpha.18",
3
+ "version": "1.0.0-alpha.19",
4
4
  "description": "Intent-driven idea development system for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
7
- "plastic": "bin/install.js"
7
+ "plastic": "bin/plastic.js"
8
8
  },
9
9
  "engines": {
10
10
  "node": ">=18.0.0"