lyman 0.1.0 → 0.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.
- checksums.yaml +4 -4
- data/README.md +9 -3
- data/docs/design/deployment.md +6 -1
- data/lib/lyman/cli/commands/add.rb +6 -1
- data/lib/lyman/cli/commands/new.rb +1 -1
- data/lib/lyman/cli/registry.rb +20 -0
- data/lib/lyman/cli/version.rb +1 -1
- data/lib/lyman/cli.rb +2 -1
- data/templates/SKILL.md +62 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c688da4f3dbae3ea1eae1ddadbbcb9c8024ca15d6b396d6a2b8aa85dd77bb91c
|
|
4
|
+
data.tar.gz: 31ead51a810ff07e2ef56943f36cc379ef8df8cbb7dcdfc611ad92c2d098c61e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f5c814ed46a0ff60e7058850901a13a4b5367a87afe935efcdc86c881619580a656e5387e9cedd47c9e7ea47caf958ffb2ddb73b6a4697563f6dac21995a4a05
|
|
7
|
+
data.tar.gz: a6b3450171f5db5c04eb8ce3bb5e3fb742abf692d45f30c1dcb1077afda75570e73b2e0a054fbeadcbca92d1876a5b17ed51cf8f9b07c6c444e1b86d9c6fddfe
|
data/README.md
CHANGED
|
@@ -152,9 +152,15 @@ Early and moving. What exists today: the vision, circuit-pattern, and
|
|
|
152
152
|
deployment design docs, the core `Conversation` item, chat-completion and
|
|
153
153
|
tool-execution workers, a working tool-using chat harness against live local
|
|
154
154
|
models, and the generator CLI (`new` / `add` / `update` / `eject` / `diff` /
|
|
155
|
-
`doctor` / `list`) with a Minitest suite behind it.
|
|
156
|
-
rubygems.org —
|
|
157
|
-
|
|
155
|
+
`doctor` / `list`) with a Minitest suite behind it. Published to
|
|
156
|
+
[rubygems.org](https://rubygems.org/gems/lyman) — install it with:
|
|
157
|
+
|
|
158
|
+
```sh
|
|
159
|
+
gem install lyman
|
|
160
|
+
lyman new my-agent
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
On deck: tool-call fan-out and a one-shot (non-REPL) harness.
|
|
158
164
|
|
|
159
165
|
## License
|
|
160
166
|
|
data/docs/design/deployment.md
CHANGED
|
@@ -150,7 +150,12 @@ Three channels, ordered by reach:
|
|
|
150
150
|
`AGENTS.md`) as a first-class artifact carrying the load-bearing facts: the
|
|
151
151
|
nil-source footgun, the runaway-turn guard, item-as-control discipline,
|
|
152
152
|
wire-vs-conversation separation. Highest-value channel: works with any
|
|
153
|
-
coding agent, zero install steps, travels with the code.
|
|
153
|
+
coding agent, zero install steps, travels with the code. For projects that
|
|
154
|
+
already have a `CLAUDE.md` lyman shouldn't clobber, the same guidance
|
|
155
|
+
ships as an opt-in Claude Code skill (`lyman add claude_skill` plants
|
|
156
|
+
`.claude/skills/lyman/SKILL.md`); `lyman add claude_md` points there when
|
|
157
|
+
it refuses to overwrite an existing file. Opt-in artifacts (`optional:` in
|
|
158
|
+
the registry) are skipped by `new` and reached with `add`.
|
|
154
159
|
2. **A Claude plugin marketplace** in the `joelhelbling/lyman` repo, for
|
|
155
160
|
richer *procedures* — e.g. a skill that knows how to wire a new tool worker
|
|
156
161
|
correctly, or how to read a stalled pipeline. Skills earn their keep when
|
|
@@ -31,8 +31,13 @@ module Lyman
|
|
|
31
31
|
end
|
|
32
32
|
else
|
|
33
33
|
if File.exist?(dest) && !force
|
|
34
|
-
|
|
34
|
+
message = "#{dest} already exists and isn't tracked by lyman. " \
|
|
35
35
|
"Move it aside, or run `lyman add #{name} --force` to overwrite it."
|
|
36
|
+
if (alt = spec[:alternative])
|
|
37
|
+
message += " Or plant `lyman add #{alt}` instead, " \
|
|
38
|
+
"which leaves #{spec[:dest]} untouched."
|
|
39
|
+
end
|
|
40
|
+
raise Thor::Error, message
|
|
36
41
|
end
|
|
37
42
|
end
|
|
38
43
|
|
|
@@ -19,7 +19,7 @@ module Lyman
|
|
|
19
19
|
FileUtils.mkdir_p(project_root)
|
|
20
20
|
|
|
21
21
|
manifest = Manifest.load(project_root)
|
|
22
|
-
Registry
|
|
22
|
+
Registry.default.each do |artifact_name, spec|
|
|
23
23
|
plant(manifest, artifact_name, spec, project_root)
|
|
24
24
|
end
|
|
25
25
|
manifest.save
|
data/lib/lyman/cli/registry.rb
CHANGED
|
@@ -42,8 +42,21 @@ module Lyman
|
|
|
42
42
|
source: "templates/CLAUDE.md",
|
|
43
43
|
dest: "CLAUDE.md",
|
|
44
44
|
role: :owned,
|
|
45
|
+
alternative: "claude_skill",
|
|
45
46
|
description: "Guidance for coding agents working in this project"
|
|
46
47
|
},
|
|
48
|
+
# The same guidance as claude_md, packaged as a Claude Code skill —
|
|
49
|
+
# for projects that already have a CLAUDE.md lyman shouldn't clobber.
|
|
50
|
+
# `optional:` keeps `new` from planting it (a fresh scaffold gets
|
|
51
|
+
# claude_md instead); `alternative:` on claude_md points here when
|
|
52
|
+
# `add` refuses to overwrite an existing CLAUDE.md.
|
|
53
|
+
"claude_skill" => {
|
|
54
|
+
source: "templates/SKILL.md",
|
|
55
|
+
dest: ".claude/skills/lyman/SKILL.md",
|
|
56
|
+
role: :owned,
|
|
57
|
+
optional: true,
|
|
58
|
+
description: "Claude Code skill variant of the CLAUDE.md guidance — for projects with their own CLAUDE.md"
|
|
59
|
+
},
|
|
47
60
|
"gemfile" => {
|
|
48
61
|
source: "templates/Gemfile",
|
|
49
62
|
dest: "Gemfile",
|
|
@@ -90,6 +103,13 @@ module Lyman
|
|
|
90
103
|
ARTIFACTS.select { |_, spec| spec[:role] == :managed }
|
|
91
104
|
end
|
|
92
105
|
|
|
106
|
+
# What `new` plants: everything except opt-in artifacts (those exist
|
|
107
|
+
# for situations a fresh scaffold can't be in, like a pre-existing
|
|
108
|
+
# CLAUDE.md — reach them with `lyman add`).
|
|
109
|
+
def self.default
|
|
110
|
+
ARTIFACTS.reject { |_, spec| spec[:optional] }
|
|
111
|
+
end
|
|
112
|
+
|
|
93
113
|
def self.source_path(spec, source_root: GEM_ROOT)
|
|
94
114
|
File.join(source_root, spec[:source])
|
|
95
115
|
end
|
data/lib/lyman/cli/version.rb
CHANGED
data/lib/lyman/cli.rb
CHANGED
|
@@ -80,7 +80,8 @@ module Lyman
|
|
|
80
80
|
entry ? entry["status"] : "not planted"
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
role = "#{spec[:role]}#{", opt-in" if spec[:optional]}"
|
|
84
|
+
line = "#{name} (#{role}) #{spec[:dest]}#{" — #{status}" if status} — #{spec[:description]}"
|
|
84
85
|
say line
|
|
85
86
|
end
|
|
86
87
|
end
|
data/templates/SKILL.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lyman
|
|
3
|
+
description: Guidance for working in a lyman-scaffolded agentic harness — the pipeline-of-workers model, the managed/owned boundary, and lyman's sharp edges. Use when reading or changing the harness (harness/chat.rb), anything under lib/lyman/, or when running lyman CLI commands (add, update, eject, diff, doctor).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Working in a lyman project
|
|
7
|
+
|
|
8
|
+
This project was scaffolded by [lyman](https://github.com/joelhelbling/lyman):
|
|
9
|
+
an agentic harness built on the [shifty](https://github.com/joelhelbling/shifty)
|
|
10
|
+
gem's pipeline-of-workers model. `harness/chat.rb` wires a model⇄tool loop
|
|
11
|
+
against any OpenAI-compatible chat completions endpoint (Ollama by default).
|
|
12
|
+
|
|
13
|
+
## Running it
|
|
14
|
+
|
|
15
|
+
- `bundle install` — install dependencies (just `shifty` and `ostruct`; this
|
|
16
|
+
project has no runtime dependency on the `lyman` gem itself).
|
|
17
|
+
- `ruby harness/chat.rb` — run the interactive chat harness. Defaults to
|
|
18
|
+
Ollama at `http://localhost:11434/v1`; override with `LYMAN_MODEL` and
|
|
19
|
+
`LYMAN_BASE_URL` env vars.
|
|
20
|
+
|
|
21
|
+
## The managed/owned boundary
|
|
22
|
+
|
|
23
|
+
Everything under the `Lyman::` namespace (`lib/lyman.rb`, `lib/lyman/`) is
|
|
24
|
+
**managed** by the lyman CLI: it was planted here, and `lyman update` can
|
|
25
|
+
refresh it from newer lyman releases. Treat it as a library to extend, not a
|
|
26
|
+
file to hand-edit — if you need to change one, run `lyman eject <name>` first,
|
|
27
|
+
which takes ownership explicitly rather than leaving it silently forked.
|
|
28
|
+
`.lyman/manifest.yml` is the record of what's managed, what's owned, and what
|
|
29
|
+
you've ejected; commit it.
|
|
30
|
+
|
|
31
|
+
`harness/chat.rb` and everything outside `Lyman::` is **owned** — yours from
|
|
32
|
+
day one, never touched by `lyman update`. Put your own workers in your own
|
|
33
|
+
namespace or directory, not inside `lib/lyman/`.
|
|
34
|
+
|
|
35
|
+
## Four load-bearing facts
|
|
36
|
+
|
|
37
|
+
1. **The nil-source footgun.** In shifty, a source returning `nil` ends the
|
|
38
|
+
stream permanently. If you're driving a pipeline off a queue, enqueue
|
|
39
|
+
before you shift — never pull a source worker while its queue is empty.
|
|
40
|
+
|
|
41
|
+
2. **The runaway-turn guard.** The model⇄tool circuit is bounded by
|
|
42
|
+
`Conversation#runaway?` / `max_rounds`. Keep that guard intact when
|
|
43
|
+
rewiring the circuit; without it, a model that keeps calling tools never
|
|
44
|
+
lets a turn end.
|
|
45
|
+
|
|
46
|
+
3. **Item-as-control discipline.** An item may tell a worker *whether* to
|
|
47
|
+
act, never *which of several things* to do. A worker that switches
|
|
48
|
+
between jobs based on item state is the anti-pattern to avoid
|
|
49
|
+
(multi-way dispatch) — split it into stages, or use a splitter, instead.
|
|
50
|
+
|
|
51
|
+
4. **Wire vs. conversation.** Reasoning/thinking content stays on messages in
|
|
52
|
+
the `Conversation` for observability, but `Workers.wire_messages` strips
|
|
53
|
+
it before anything goes out over the wire. Preserve that separation if
|
|
54
|
+
you touch message handling.
|
|
55
|
+
|
|
56
|
+
## Other conventions
|
|
57
|
+
|
|
58
|
+
- `lyman doctor` smoke-tests the pipeline end to end against a stub
|
|
59
|
+
transport — run it after `lyman update` or whenever something feels off.
|
|
60
|
+
- `lyman list` shows what's managed, owned, or ejected in this project.
|
|
61
|
+
- Messages use string keys throughout, matching the OpenAI-compatible wire
|
|
62
|
+
format — no symbol-key message hashes.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lyman
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joel Helbling
|
|
@@ -83,6 +83,7 @@ files:
|
|
|
83
83
|
- lib/lyman/workers/tool_execution.rb
|
|
84
84
|
- templates/CLAUDE.md
|
|
85
85
|
- templates/Gemfile
|
|
86
|
+
- templates/SKILL.md
|
|
86
87
|
- templates/gitignore
|
|
87
88
|
- templates/lib_lyman.rb
|
|
88
89
|
homepage: https://github.com/joelhelbling/lyman
|