@primitive.ai/prim 0.1.0-alpha.52 → 0.1.0-alpha.54
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 +11 -4
- package/SKILL.md +16 -10
- package/dist/index.js +15 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,8 +31,8 @@ npx @primitive.ai/prim
|
|
|
31
31
|
In commands such as `npx --yes @primitive.ai/prim@latest ...`, the first `--yes`
|
|
32
32
|
belongs to **npm**: it skips npm's package-install confirmation. It does not approve a
|
|
33
33
|
Primitive action. Prim's own global `--yes` comes after the package name, for example
|
|
34
|
-
`npx --yes @primitive.ai/prim@latest --yes decisions create
|
|
35
|
-
that Prim invocation.
|
|
34
|
+
`npx --yes @primitive.ai/prim@latest --yes decisions create ... --attribution user`,
|
|
35
|
+
and applies only to that Prim invocation.
|
|
36
36
|
|
|
37
37
|
## Quick Start
|
|
38
38
|
|
|
@@ -215,7 +215,7 @@ prim decisions show <id> # Drill into one decision
|
|
|
215
215
|
prim decisions cascade <id> # Blast radius of a decision
|
|
216
216
|
prim decisions check --files <…> # Active decisions referencing files (warn-only)
|
|
217
217
|
prim decisions confirm <id> # Answer a rationale-confirmation prompt
|
|
218
|
-
prim decisions create --intent <…>
|
|
218
|
+
prim decisions create --intent <…> --attribution <user|agent> # Record with explicit origin
|
|
219
219
|
prim decisions link <child> --on <parent> # Relate: <child> depends on <parent>
|
|
220
220
|
prim decisions unlink <child> --on <parent> # Remove that dependency
|
|
221
221
|
```
|
|
@@ -226,12 +226,19 @@ JSON; human-readable status goes to STDERR.
|
|
|
226
226
|
When passive capture is inactive in the current repo, an approved one-time create is:
|
|
227
227
|
|
|
228
228
|
```bash
|
|
229
|
-
npx --yes @primitive.ai/prim@latest --yes decisions create --intent "…"
|
|
229
|
+
npx --yes @primitive.ai/prim@latest --yes decisions create --intent "…" --attribution user
|
|
230
230
|
```
|
|
231
231
|
|
|
232
232
|
Here npm's first `--yes` only permits package resolution; Prim's second `--yes`
|
|
233
233
|
confirms this create. It does not enable the repo or authorize a later create.
|
|
234
234
|
|
|
235
|
+
Every create requires `--attribution user|agent`. Use `user` only when the person
|
|
236
|
+
directly stated, selected, or confirmed the exact recorded choice. Use `agent` when
|
|
237
|
+
the agent introduced that exact choice while pursuing a broader request. A broad task
|
|
238
|
+
prompt or permission to implement does not make the resulting agent choice a user
|
|
239
|
+
Decision. If the origin is ambiguous, confirm the exact choice with the person before
|
|
240
|
+
creating it; do not guess.
|
|
241
|
+
|
|
235
242
|
`link` / `unlink` curate the dependency edges the automatic linker would otherwise
|
|
236
243
|
own — `<child>` depends on `<parent>`. Both are idempotent and refuse any link that
|
|
237
244
|
would create a cycle (exit 2); an unresolved id exits 4.
|
package/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: prim
|
|
3
|
-
description: Use the prim CLI for Primitive’s decision graph. MUST INVOKE before finishing any coding, planning, specification, or review task where the user or agent chose between plausible approaches or established or changed a lasting goal, priority, constraint, invariant, default, commitment, tradeoff, exception, or shared instruction—even when Primitive was not mentioned. Also invoke for Primitive setup, reading decisions, conflict gates, reconcile, rationale confirmations, linking, and team presence. SKIP routine implementation that merely follows an existing decision
|
|
3
|
+
description: Use the prim CLI for Primitive’s decision graph. MUST INVOKE before finishing any coding, planning, specification, or review task where the user or agent chose between plausible approaches or established or changed a lasting goal, priority, constraint, invariant, default, commitment, tradeoff, exception, or shared instruction—even when Primitive was not mentioned. Also invoke for Primitive setup, reading decisions, conflict gates, reconcile, rationale confirmations, linking, and team presence. SKIP — do not invoke even to check — when the task shows no fork that should guide future work, for example temporary tactics (a change that is explicitly temporary or to-be-reverted); routine implementation that merely follows an existing decision or a convention already visible in the code or repo instructions; or the word “decision” merely naming code, data, or UI. Such signals need no graph lookup to rule out.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Working with the prim CLI
|
|
@@ -80,7 +80,7 @@ Confirmations are author-targeted and rare by design; answering keeps the graph'
|
|
|
80
80
|
|
|
81
81
|
Capture is automatic for low-level choices made while coding in an active repo. Use the deliberate CLI path for higher-order decisions that emerge in conversation: goals, priorities, principles, invariants, constraints, defaults, commitments, durable tradeoffs, and exceptions.
|
|
82
82
|
|
|
83
|
-
A decision worth deliberately recording is a genuine **fork in the road**: the user or agent encountered multiple plausible paths, selected one, and that selection should inform future work. Record the chosen behavior, direction, constraint, or tradeoff—not routine implementation needed to finish the task or follow an existing convention. A teammate working elsewhere should benefit from knowing it.
|
|
83
|
+
A decision worth deliberately recording is a genuine **fork in the road**: the user or agent encountered multiple plausible paths, selected one, and that selection should inform future work. Record the chosen behavior, direction, constraint, or tradeoff—not routine implementation needed to finish the task or follow an existing convention. Small design choices made in-flight while implementing—such as edge-case handling, parameter defaults, retry or timeout values, log levels, naming, or the shape of an internal data structure—are implementation details even when you chose between alternatives: never deliberately record them or spend a rationale question on them; passive capture already covers coding activity. A teammate working elsewhere should benefit from knowing it.
|
|
84
84
|
|
|
85
85
|
### Ground the rationale in real sources
|
|
86
86
|
|
|
@@ -91,8 +91,10 @@ Record only rationale supported by those sources. Do not mistake the implementat
|
|
|
91
91
|
For proactively identified decisions in an active repo, let confidence in the rationale determine the interaction:
|
|
92
92
|
|
|
93
93
|
- **Clear and well-supported** — record the decision and rationale silently at the natural task boundary.
|
|
94
|
-
- **Plausible but uncertain** — at the task boundary, state the proposed rationale and ask for lightweight confirmation: “I understand the reason for choosing X to be Y. Is that right?” Record
|
|
95
|
-
- **No supported rationale** — at the task boundary, ask one focused question: “What made you choose X over the other path?” Record
|
|
94
|
+
- **Plausible but uncertain** — at the task boundary, state the proposed rationale and ask for lightweight confirmation: “I understand the reason for choosing X to be Y. Is that right?” Record in the same turn with the rationale omitted; add it once confirmed or corrected.
|
|
95
|
+
- **No supported rationale** — at the task boundary, ask one focused question: “What made you choose X over the other path?” Record in the same turn with the rationale omitted; add it when the answer arrives.
|
|
96
|
+
|
|
97
|
+
In both cases the question is a courtesy, not a gate: never make the record wait on an answer, and never fabricate a rationale to fill the gap. An unanswered question with no record is the only wrong outcome.
|
|
96
98
|
|
|
97
99
|
These questions share the interruption budget below; never ask separate questions for the decision and its rationale. If both are uncertain, combine them into one concise prompt. An explicit request to “add this decision to Primitive” still records immediately with the information supplied—do not delay it to demand rationale.
|
|
98
100
|
|
|
@@ -109,8 +111,10 @@ an explicit local `prim.active=false` is always inactive. Every
|
|
|
109
111
|
rationale, then wait for approval before creating it. A previous approval never
|
|
110
112
|
carries forward to another Decision.
|
|
111
113
|
- After approval, pass Prim's global `--yes` for that invocation:
|
|
112
|
-
`npx --yes @primitive.ai/prim --yes decisions create
|
|
113
|
-
|
|
114
|
+
`npx --yes @primitive.ai/prim --yes decisions create ... --attribution user`.
|
|
115
|
+
The person's approval of the exact proposed choice is user ratification. The
|
|
116
|
+
first `--yes` is npm's package-install flag; the second is Prim's one-time
|
|
117
|
+
confirmation.
|
|
114
118
|
- Do not run `prim enable` merely to bypass this boundary or infer permission to
|
|
115
119
|
activate the repo. Activation requires a separate user request (a requested
|
|
116
120
|
`prim setup` counts because setup explicitly activates its current repo). A
|
|
@@ -124,7 +128,7 @@ When the user asks to record a decision—for example, “add this decision to P
|
|
|
124
128
|
|
|
125
129
|
### Clear decisions: record without interrupting
|
|
126
130
|
|
|
127
|
-
When the user clearly makes a durable fork-in-the-road decision without explicitly asking to record it, record it at the next natural task boundary without asking a redundant confirmation question **when passive capture is active**. In an inactive repo, present it and obtain the per-create approval above. Preserve the user's meaning and stated rationale; do not strengthen, broaden, or embellish it. Prefer the governing position over the implementation activity that revealed it.
|
|
131
|
+
When the user clearly makes a durable fork-in-the-road decision without explicitly asking to record it, record it at the next natural task boundary without asking a redundant confirmation question **when passive capture is active**. An explicit ratification of a direction—“agreed,” “ship it that way,” or any equivalent affirmation—is such a decision even when the ratified option was your own proposal: the ratification is the approval, so record it and do not ask whether to record. That rule is general: in an active repository, never ask permission to record — the only question the budget permits is the single rationale question, and only when no rationale was stated. In an inactive repo, present it and obtain the per-create approval above. Preserve the user's meaning and stated rationale; do not strengthen, broaden, or embellish it. Prefer the governing position over the implementation activity that revealed it.
|
|
128
132
|
|
|
129
133
|
Examples that qualify:
|
|
130
134
|
|
|
@@ -166,16 +170,18 @@ npx --yes @primitive.ai/prim decisions recent --limit 20
|
|
|
166
170
|
If an equivalent decision is already present, do not create or suggest it again. After this duplicate check—or after the user confirms an onboarding proposal—author the decision directly. If the repo is inactive, that confirmation authorizes Prim's `--yes` only for the approved create:
|
|
167
171
|
|
|
168
172
|
```
|
|
169
|
-
npx --yes @primitive.ai/prim decisions create --intent "Adopt prosemirror-collab over Yjs" --area data --rationale "Server-authoritative ordering" --alternatives "Yjs,Automerge"
|
|
173
|
+
npx --yes @primitive.ai/prim decisions create --intent "Adopt prosemirror-collab over Yjs" --attribution user --area data --rationale "Server-authoritative ordering" --alternatives "Yjs,Automerge"
|
|
170
174
|
```
|
|
171
175
|
|
|
172
176
|
Inactive-repo form after approval:
|
|
173
177
|
|
|
174
178
|
```
|
|
175
|
-
npx --yes @primitive.ai/prim --yes decisions create --intent "Adopt prosemirror-collab over Yjs" --area data --rationale "Server-authoritative ordering" --alternatives "Yjs,Automerge"
|
|
179
|
+
npx --yes @primitive.ai/prim --yes decisions create --intent "Adopt prosemirror-collab over Yjs" --attribution user --area data --rationale "Server-authoritative ordering" --alternatives "Yjs,Automerge"
|
|
176
180
|
```
|
|
177
181
|
|
|
178
|
-
|
|
182
|
+
Both `--intent` and `--attribution` are required. Set `--attribution user` only when the person directly stated, selected, or confirmed the exact recorded choice. Set `--attribution agent` when you introduced that exact choice while pursuing a broader request. A broad task prompt, implementation permission, or assignment of responsibility does not turn your implementation choice into a user Decision. If the origin is ambiguous, ask the person to confirm the exact choice before creating it; after confirmation, use `user`. Never guess attribution.
|
|
183
|
+
|
|
184
|
+
Optional: `--kind` (change|exploration|task_execution|unclear, default change), `--rationale`, `--area`, `--decided`, `--alternatives` (comma-separated), `--confidence` (high|medium|low, default high), `--reversibility` (high|low, default high), and `--files` (comma-separated repo-relative paths the decision governs — these are the files Conflict Gates would check on later edits, same path form as `decisions check`; Conflict Gates are not currently enabled). Omit `--files` for broad directions that should not immediately participate in file-based Conflict Gates. STDOUT is the created identity `{ decisionId, shortId, createdAt }`; STDERR prints `[prim] created dec_<short>.` — pass that `dec_<short>` straight into `decisions show` / `cascade` / `confirm`.
|
|
179
185
|
|
|
180
186
|
### Inferred decisions: finish first, then optionally ask once
|
|
181
187
|
|
package/dist/index.js
CHANGED
|
@@ -2309,6 +2309,9 @@ function registerDaemonCommands(program2) {
|
|
|
2309
2309
|
});
|
|
2310
2310
|
}
|
|
2311
2311
|
|
|
2312
|
+
// src/commands/decisions.ts
|
|
2313
|
+
import { Option } from "commander";
|
|
2314
|
+
|
|
2312
2315
|
// src/decisions/cascade-renderer.ts
|
|
2313
2316
|
var DEPENDENTS_INLINE_LIMIT = 5;
|
|
2314
2317
|
var KNOWLEDGE_INLINE_LIMIT = 4;
|
|
@@ -2764,6 +2767,7 @@ var defaultDeps4 = { getClient };
|
|
|
2764
2767
|
function toRequestBody(request) {
|
|
2765
2768
|
const candidate = {
|
|
2766
2769
|
intent: request.intent,
|
|
2770
|
+
attribution: request.attribution,
|
|
2767
2771
|
kind: request.kind,
|
|
2768
2772
|
rationale: request.rationale,
|
|
2769
2773
|
area: request.area,
|
|
@@ -3103,7 +3107,12 @@ function registerDecisionsCommands(program2) {
|
|
|
3103
3107
|
throw err;
|
|
3104
3108
|
}
|
|
3105
3109
|
});
|
|
3106
|
-
decisions.command("create").description("
|
|
3110
|
+
decisions.command("create").description("Record a decision directly with its explicit user or agent origin").requiredOption("--intent <text>", "What was decided (required)").addOption(
|
|
3111
|
+
new Option(
|
|
3112
|
+
"--attribution <origin>",
|
|
3113
|
+
"Who originated the exact choice: user | agent (required)"
|
|
3114
|
+
).choices(["user", "agent"]).makeOptionMandatory()
|
|
3115
|
+
).option("--kind <kind>", "change | exploration | task_execution | unclear (default change)").option("--rationale <text>", "Why the decision was made").option(
|
|
3107
3116
|
"--area <area>",
|
|
3108
3117
|
"Functional area (auth, data, infra, ui, api, billing, mobile, docs, testing)"
|
|
3109
3118
|
).option("--decided <items>", "Comma-separated option(s) chosen").option("--alternatives <items>", "Comma-separated options considered but rejected").option("--confidence <level>", "high | medium | low (default high)").option("--reversibility <level>", "high | low (default high)").option(
|
|
@@ -3124,6 +3133,7 @@ function registerDecisionsCommands(program2) {
|
|
|
3124
3133
|
}
|
|
3125
3134
|
const request = {
|
|
3126
3135
|
intent: opts.intent,
|
|
3136
|
+
attribution: opts.attribution,
|
|
3127
3137
|
kind: opts.kind,
|
|
3128
3138
|
rationale: opts.rationale,
|
|
3129
3139
|
area: opts.area,
|
|
@@ -3874,7 +3884,7 @@ import { execFileSync } from "child_process";
|
|
|
3874
3884
|
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
3875
3885
|
import { homedir as homedir6 } from "os";
|
|
3876
3886
|
import { dirname as dirname4, join as join6, resolve as resolve2 } from "path";
|
|
3877
|
-
import { Option } from "commander";
|
|
3887
|
+
import { Option as Option2 } from "commander";
|
|
3878
3888
|
var PRE_COMMIT = { hookName: "pre-commit", binName: "prim-pre-commit" };
|
|
3879
3889
|
var POST_COMMIT = { hookName: "post-commit", binName: "prim-post-commit" };
|
|
3880
3890
|
var HOOKS = [PRE_COMMIT, POST_COMMIT];
|
|
@@ -4167,12 +4177,12 @@ function registerHooksCommands(program2) {
|
|
|
4167
4177
|
hooks.command("install").description(
|
|
4168
4178
|
"Install the prim git hooks \u2014 pre-commit + post-commit (auto-detects Husky; use --target to override)"
|
|
4169
4179
|
).addOption(
|
|
4170
|
-
new
|
|
4180
|
+
new Option2("--target <where>", "install destination; bypasses Husky detection").choices([
|
|
4171
4181
|
"husky",
|
|
4172
4182
|
"git-hooks"
|
|
4173
4183
|
])
|
|
4174
4184
|
).addOption(
|
|
4175
|
-
new
|
|
4185
|
+
new Option2(
|
|
4176
4186
|
"--scope <scope>",
|
|
4177
4187
|
"project (default, this repo) or user (a global core.hooksPath capturing every repo)"
|
|
4178
4188
|
).choices(["project", "user"])
|
|
@@ -4212,7 +4222,7 @@ function registerHooksCommands(program2) {
|
|
|
4212
4222
|
hooks.command("uninstall").description(
|
|
4213
4223
|
"Remove the prim git hooks (.git/hooks, or the global core.hooksPath with --scope user)"
|
|
4214
4224
|
).addOption(
|
|
4215
|
-
new
|
|
4225
|
+
new Option2(
|
|
4216
4226
|
"--scope <scope>",
|
|
4217
4227
|
"project (default, this repo) or user (global core.hooksPath)"
|
|
4218
4228
|
).choices(["project", "user"])
|
package/package.json
CHANGED