@sabaiway/agent-workflow-memory 1.0.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.
- package/CHANGELOG.md +40 -0
- package/LICENSE +21 -0
- package/README.md +61 -0
- package/SKILL.md +201 -0
- package/bin/install.mjs +185 -0
- package/bin/install.test.mjs +76 -0
- package/capability.json +27 -0
- package/migrations/1.1.0-communication-language.md +51 -0
- package/migrations/1.2.0-agent-attribution.md +57 -0
- package/migrations/README.md +46 -0
- package/migrations/legacy-stamp-takeover.md +72 -0
- package/package.json +53 -0
- package/references/contracts.md +62 -0
- package/references/scripts/_expect-shim.mjs +41 -0
- package/references/scripts/archive-changelog.mjs +438 -0
- package/references/scripts/archive-changelog.test.mjs +212 -0
- package/references/scripts/archive-issues.mjs +179 -0
- package/references/scripts/archive-issues.test.mjs +95 -0
- package/references/scripts/check-docs-size.mjs +353 -0
- package/references/scripts/check-docs-size.test.mjs +180 -0
- package/references/scripts/install-git-hooks.mjs +83 -0
- package/references/templates/AGENTS.md +96 -0
- package/references/templates/active_plan.md +31 -0
- package/references/templates/agent_rules.md +85 -0
- package/references/templates/architecture.md +49 -0
- package/references/templates/changelog.md +24 -0
- package/references/templates/current_state.md +36 -0
- package/references/templates/decisions.md +44 -0
- package/references/templates/env_commands.md +41 -0
- package/references/templates/handover.md +37 -0
- package/references/templates/known_issues.md +33 -0
- package/references/templates/pages/PAGE_TEMPLATE.md +53 -0
- package/references/templates/pages/index.md +23 -0
- package/references/templates/pages/shared-patterns.md +30 -0
- package/references/templates/tech_reference.md +34 -0
- package/references/templates/technical_specification.md +37 -0
- package/scripts/package-content.test.mjs +78 -0
- package/scripts/stamp-takeover.mjs +181 -0
- package/scripts/stamp-takeover.test.mjs +166 -0
- package/scripts/standalone-bootstrap.test.mjs +111 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Migration 1.1.0-communication-language
|
|
2
|
+
|
|
3
|
+
**From:** versions < 1.1.0 **To:** 1.1.0
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
1.1.0 adds a **conversational language** setting: the language the agent *talks to the
|
|
8
|
+
user* in (questions, explanations, summaries, status). It is recorded in a *Communication
|
|
9
|
+
language* block in the project's `AGENTS.md` so every agent that reads the entry point
|
|
10
|
+
honours it instead of drifting between languages. Pre-1.1.0 deployments have no such block.
|
|
11
|
+
|
|
12
|
+
Scope is **dialogue only** — code, identifiers, paths, commands, log output, and
|
|
13
|
+
abbreviations stay in their source language, and the `docs/ai/` files + `AGENTS.md` are not
|
|
14
|
+
translated either. This migration changes *one* doc block, nothing else.
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Open the project's entry point `AGENTS.md` (the real file; `CLAUDE.md` is a symlink to it).
|
|
19
|
+
2. **Idempotency check** — if it already contains a `## 🗣️ Communication language` heading,
|
|
20
|
+
this migration is done; skip to Verification.
|
|
21
|
+
3. **Ask the user** which language the agent should converse in (questions, explanations,
|
|
22
|
+
summaries, status). Offer the language they're already writing in as the default.
|
|
23
|
+
4. Insert this block immediately **after the opening blockquote** (before `## 🧭 Memory Map`),
|
|
24
|
+
replacing `<their language>` with the answer from step 3:
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 🗣️ Communication language
|
|
30
|
+
|
|
31
|
+
> **Talk to the user in <their language>** — every question, explanation, summary, and status update.
|
|
32
|
+
> Keep code, identifiers, file paths, shell commands, log output, and abbreviations in their **source language** — translating them breaks copy-paste, search, and tooling.
|
|
33
|
+
> This sets the **dialogue** language only — it does not translate the files in `docs/ai/` or this entry point, which stay in their source language (for cross-agent / cross-team portability).
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
5. Keep `AGENTS.md` within its ≤100-line budget (the block is ~6 lines; it fits). Do **not**
|
|
37
|
+
touch any other section, and do **not** translate existing file contents.
|
|
38
|
+
|
|
39
|
+
## Verification
|
|
40
|
+
|
|
41
|
+
- `AGENTS.md` has exactly one `## 🗣️ Communication language` block, with a real language in
|
|
42
|
+
place of `<their language>` (no leftover `{{COMM_LANGUAGE}}` placeholder).
|
|
43
|
+
- The docs cap-validator is still green (`node scripts/check-docs-size.mjs` for Node projects)
|
|
44
|
+
— the entry point did not bust its line budget.
|
|
45
|
+
- From now on the agent's replies are in the chosen language; paths/commands/identifiers
|
|
46
|
+
remain in their source language.
|
|
47
|
+
|
|
48
|
+
## Rollback
|
|
49
|
+
|
|
50
|
+
Delete the inserted `## 🗣️ Communication language` block (and its trailing `---`) from
|
|
51
|
+
`AGENTS.md`. No other files were changed.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Migration 1.2.0-agent-attribution
|
|
2
|
+
|
|
3
|
+
**From:** versions < 1.2.0 **To:** 1.2.0
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
1.2.0 makes **agent attribution opt-in**. The agent may attribute work to itself / AI —
|
|
8
|
+
`Co-Authored-By` trailers, "Generated with …" footers, AI/agent/model mentions in code,
|
|
9
|
+
comments, commit messages, PR titles/bodies, branch names, or docs — **only if the user
|
|
10
|
+
allows it**. Default is `off`. The choice is recorded in an *Attribution* block in the
|
|
11
|
+
project's `AGENTS.md`; pre-1.2.0 deployments have no such block.
|
|
12
|
+
|
|
13
|
+
A single `Co-Authored-By` trailer is enough to list an AI as a repo contributor, and GitHub
|
|
14
|
+
keeps it permanently via PR refs — so the safe default is "no mention anywhere".
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Open the project's entry point `AGENTS.md` (the real file; `CLAUDE.md` is a symlink to it).
|
|
19
|
+
2. **Idempotency check** — if it already contains a `## ✍️ Attribution` heading, skip to Verification.
|
|
20
|
+
3. **Ask the user**: may the agent attribute work to itself / AI anywhere (commits, PRs, code,
|
|
21
|
+
comments, docs)? **Default to `off`** unless they opt in.
|
|
22
|
+
4. Insert this block immediately **after the *Communication language* block** (or, if that is
|
|
23
|
+
absent, after the opening blockquote — before `## 🧭 Memory Map`), replacing `<off|on>` with
|
|
24
|
+
the answer from step 3:
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## ✍️ Attribution
|
|
30
|
+
|
|
31
|
+
> **Agent attribution: <off|on>** (chosen at setup).
|
|
32
|
+
> **off** → never attribute work to the agent, AI, or the model: no `Co-Authored-By` trailers, no "Generated with …" footers, no AI/agent/model mentions in code, comments, commit messages, PR titles/bodies, branch names, or docs. Author everything as the human.
|
|
33
|
+
> **on** → the agent may add its standard `Co-Authored-By` trailer / footer per your tooling defaults.
|
|
34
|
+
> Claude Code also honours `includeCoAuthoredBy` in `.claude/settings.json`; this block binds every agent for everything written by hand.
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
5. **If the answer is `off` and the project uses Claude Code**, also set the harness flag so the
|
|
38
|
+
automatic trailer stops (a doc directive cannot stop a harness-added trailer):
|
|
39
|
+
- Ensure `.claude/settings.json` exists in the project root; create it as `{}` if absent.
|
|
40
|
+
- Set `"includeCoAuthoredBy": false` (merge into the existing JSON; do not clobber other keys).
|
|
41
|
+
- For other tools, disable their equivalent co-author / footer setting if present.
|
|
42
|
+
6. Keep `AGENTS.md` within its ≤100-line budget (the block is ~7 lines; it fits). Do **not**
|
|
43
|
+
retroactively rewrite existing git history here — that is a separate, deliberate operation.
|
|
44
|
+
|
|
45
|
+
## Verification
|
|
46
|
+
|
|
47
|
+
- `AGENTS.md` has exactly one `## ✍️ Attribution` block, with `off` or `on` (no leftover
|
|
48
|
+
`{{AGENT_ATTRIBUTION}}` placeholder).
|
|
49
|
+
- If `off` + Claude Code: `.claude/settings.json` contains `"includeCoAuthoredBy": false`, and
|
|
50
|
+
the file is valid JSON (`node -e "JSON.parse(require('fs').readFileSync('.claude/settings.json'))"`).
|
|
51
|
+
- The docs cap-validator is still green (`node scripts/check-docs-size.mjs` for Node projects).
|
|
52
|
+
|
|
53
|
+
## Rollback
|
|
54
|
+
|
|
55
|
+
Delete the inserted `## ✍️ Attribution` block (and its trailing `---`) from `AGENTS.md`, and
|
|
56
|
+
remove the `includeCoAuthoredBy` key from `.claude/settings.json` if you added it. No other
|
|
57
|
+
files were changed.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Migrations
|
|
2
|
+
|
|
3
|
+
Each upgrade step is one file: `migrations/<version>-<slug>.md`, where `<version>` is the
|
|
4
|
+
skill release that introduced the change (matches a `CHANGELOG.md` heading) and `<slug>`
|
|
5
|
+
is a short kebab-case name. Empty until the first change that needs migrating — most
|
|
6
|
+
releases add files/templates, which `upgrade` reconciles without a migration.
|
|
7
|
+
|
|
8
|
+
## How `upgrade` applies them
|
|
9
|
+
|
|
10
|
+
1. Read the project's stamped version from `docs/ai/.memory-version` (the deployment-lineage
|
|
11
|
+
stamp owned by this substrate). On a deployment that has only the legacy `docs/ai/.workflow-version`
|
|
12
|
+
(a kit fallback bootstrap), `legacy-stamp-takeover.md` runs first and copies that value into
|
|
13
|
+
`.memory-version` verbatim — see that migration.
|
|
14
|
+
2. Select every migration whose `<version>` is **strictly newer** than the stamp.
|
|
15
|
+
3. Apply them in **ascending semver order**.
|
|
16
|
+
4. Re-stamp `docs/ai/.memory-version` to the deployment-lineage head (`1.3.0` today — the shared
|
|
17
|
+
lineage sequence, **not** this package's npm version). The legacy `.workflow-version`, if present,
|
|
18
|
+
is never deleted.
|
|
19
|
+
|
|
20
|
+
## Authoring rules
|
|
21
|
+
|
|
22
|
+
- **Idempotent** — safe to re-run; check before mutating (e.g. "if the file already has X, skip").
|
|
23
|
+
- **Non-destructive** — never clobber project-authored content (their `decisions.md`, `known_issues.md`, page specs). Add/rename/restructure only what the kernel owns.
|
|
24
|
+
- **Self-contained** — exact paths + commands, readable cold, like a mini-plan.
|
|
25
|
+
- **Mention rollback** — note how to undo if the step is risky.
|
|
26
|
+
|
|
27
|
+
## Template
|
|
28
|
+
|
|
29
|
+
```markdown
|
|
30
|
+
# Migration <version>-<slug>
|
|
31
|
+
|
|
32
|
+
**From:** versions < <version> **To:** <version>
|
|
33
|
+
|
|
34
|
+
## Why
|
|
35
|
+
<what changed in the kernel and why a project needs to follow>
|
|
36
|
+
|
|
37
|
+
## Steps
|
|
38
|
+
1. <exact, idempotent action with paths/commands>
|
|
39
|
+
2. ...
|
|
40
|
+
|
|
41
|
+
## Verification
|
|
42
|
+
<how to confirm the project is now consistent — e.g. docs cap-validator green>
|
|
43
|
+
|
|
44
|
+
## Rollback
|
|
45
|
+
<how to undo, or "n/a — additive only">
|
|
46
|
+
```
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Migration legacy-stamp-takeover
|
|
2
|
+
|
|
3
|
+
**From:** a deployment stamped only with the legacy `docs/ai/.workflow-version` (a kit-fallback
|
|
4
|
+
bootstrap, or a pre-extraction kit deployment) **To:** the memory substrate's
|
|
5
|
+
`docs/ai/.memory-version`
|
|
6
|
+
|
|
7
|
+
This is the **no-Node manual fallback** for `scripts/stamp-takeover.mjs`. The script is the
|
|
8
|
+
source of truth (pure state machine + atomic writes, unit-tested per row); this file documents
|
|
9
|
+
the same table so a non-Node project can do it by hand. Run it **first** in `upgrade`, before
|
|
10
|
+
any other migration.
|
|
11
|
+
|
|
12
|
+
## Why
|
|
13
|
+
|
|
14
|
+
The deployment stamp moved from `.workflow-version` (owned by the kit) to `.memory-version`
|
|
15
|
+
(owned by this substrate). They track the **same** shared deployment-lineage sequence — never
|
|
16
|
+
their package versions. The current lineage head is **`1.3.0`** (`LINEAGE_HEAD`). This migration
|
|
17
|
+
adopts an existing legacy stamp into the new file **without** changing the lineage value and
|
|
18
|
+
**without** deleting the legacy stamp (both may coexist; each tool migrates from its own stamp).
|
|
19
|
+
|
|
20
|
+
## State table (idempotent)
|
|
21
|
+
|
|
22
|
+
Look at `docs/ai/` and act by row. `V` is the legacy stamp's value; `head` = `1.3.0`.
|
|
23
|
+
|
|
24
|
+
| `docs/ai/` state | Action |
|
|
25
|
+
|---|---|
|
|
26
|
+
| only `.workflow-version=V` | copy `V` **verbatim** → `.memory-version`; **leave** `.workflow-version`; then apply only memory migrations `> V` |
|
|
27
|
+
| both `.memory-version` and `.workflow-version` | **no-op** for takeover; migrate from `.memory-version` |
|
|
28
|
+
| only `.memory-version` | no takeover; migrate from it |
|
|
29
|
+
| no stamp | conservative re-bootstrap offer (existing behaviour) |
|
|
30
|
+
| any present stamp unparseable, or `> head` (future) | **STOP and report** — never downgrade or guess |
|
|
31
|
+
|
|
32
|
+
## Steps (manual)
|
|
33
|
+
|
|
34
|
+
1. **Inspect** the two files. Distinguish *absent* (the file does not exist) from a *read failure*
|
|
35
|
+
(it exists but `cat` fails — permission/I/O): only absence is "no stamp"; a read failure must
|
|
36
|
+
**STOP** (don't treat it as absent):
|
|
37
|
+
```bash
|
|
38
|
+
for f in docs/ai/.memory-version docs/ai/.workflow-version; do
|
|
39
|
+
if [ ! -e "$f" ]; then echo "$f: (absent)";
|
|
40
|
+
elif v=$(cat "$f"); then echo "$f: $v";
|
|
41
|
+
else echo "$f: READ FAILED — STOP and report"; exit 1; fi
|
|
42
|
+
done
|
|
43
|
+
```
|
|
44
|
+
2. **Validate** each value that exists: it must be `MAJOR.MINOR.PATCH`, non-empty, and **not** greater
|
|
45
|
+
than `1.3.0`. If any present stamp is empty, unparseable, or in the future → **STOP and report**;
|
|
46
|
+
do nothing else.
|
|
47
|
+
3. **Apply** the matching row above. For the "only `.workflow-version=V`" row, copy verbatim and
|
|
48
|
+
write **atomically** — create an exclusive randomized temp in `docs/ai/` (so a planted temp-name
|
|
49
|
+
symlink can't be followed), then `mv` it over the target:
|
|
50
|
+
```bash
|
|
51
|
+
v=$(cat docs/ai/.workflow-version)
|
|
52
|
+
tmp=$(mktemp docs/ai/.memory-version.XXXXXX) && printf '%s\n' "$v" > "$tmp" && mv "$tmp" docs/ai/.memory-version
|
|
53
|
+
```
|
|
54
|
+
4. Continue the normal `upgrade` flow: apply memory migrations strictly newer than the resolved
|
|
55
|
+
stamp, then re-stamp `.memory-version` to the lineage head.
|
|
56
|
+
|
|
57
|
+
Node projects do all of this in one call — pass the project's `docs/ai` directory:
|
|
58
|
+
```bash
|
|
59
|
+
node "${CLAUDE_SKILL_DIR}/scripts/stamp-takeover.mjs" docs/ai # runs applyTakeover() on docs/ai
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Verification
|
|
63
|
+
|
|
64
|
+
- `docs/ai/.memory-version` exists and equals the resolved lineage value (a single semver line,
|
|
65
|
+
trailing newline). `docs/ai/.workflow-version`, if it existed, is **unchanged**.
|
|
66
|
+
- Re-running this migration changes nothing (idempotent).
|
|
67
|
+
- No `.memory-version.tmp-*` files remain in `docs/ai/`.
|
|
68
|
+
|
|
69
|
+
## Rollback
|
|
70
|
+
|
|
71
|
+
Delete `docs/ai/.memory-version` (the legacy `.workflow-version` was never modified). No other
|
|
72
|
+
files were changed.
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sabaiway/agent-workflow-memory",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Portable, cross-agent memory substrate for AI coding agents — an AGENTS.md entry point + docs/ai context with cap/archive/index enforcement, deployable standalone or as part of the agent-workflow family. The memory layer of the agent-workflow family.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai-agents",
|
|
7
|
+
"ai-coding",
|
|
8
|
+
"coding-agent",
|
|
9
|
+
"llm",
|
|
10
|
+
"ai-tools",
|
|
11
|
+
"claude-code",
|
|
12
|
+
"codex",
|
|
13
|
+
"cursor",
|
|
14
|
+
"agents-md",
|
|
15
|
+
"agent-memory",
|
|
16
|
+
"context-engineering",
|
|
17
|
+
"cross-agent",
|
|
18
|
+
"memory",
|
|
19
|
+
"developer-tools"
|
|
20
|
+
],
|
|
21
|
+
"homepage": "https://github.com/sabaiway/agent-workflow#readme",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/sabaiway/agent-workflow/issues"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/sabaiway/agent-workflow.git",
|
|
28
|
+
"directory": "agent-workflow-memory"
|
|
29
|
+
},
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"author": "sabaiway",
|
|
32
|
+
"type": "module",
|
|
33
|
+
"bin": {
|
|
34
|
+
"agent-workflow-memory": "bin/install.mjs"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"bin/",
|
|
38
|
+
"SKILL.md",
|
|
39
|
+
"README.md",
|
|
40
|
+
"CHANGELOG.md",
|
|
41
|
+
"LICENSE",
|
|
42
|
+
"capability.json",
|
|
43
|
+
"references/",
|
|
44
|
+
"scripts/",
|
|
45
|
+
"migrations/"
|
|
46
|
+
],
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Setup contracts
|
|
2
|
+
|
|
3
|
+
The three choices the bootstrap makes with the user — **visibility**, **conversational
|
|
4
|
+
language**, and **agent attribution** — each have a contract below. `SKILL.md` links here so the
|
|
5
|
+
main procedure stays lean; load this file when you need the full rule for a contract (e.g. while
|
|
6
|
+
filling the matching `AGENTS.md` block, or when an `upgrade` migration touches it).
|
|
7
|
+
|
|
8
|
+
Ask each as a **structured multiple-choice prompt where your agent supports it** (`AskUserQuestion`
|
|
9
|
+
in Claude Code), otherwise in prose — and always wait for the answer before writing.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Visibility contract
|
|
14
|
+
|
|
15
|
+
The user chooses at bootstrap whether the AI artifacts are visible in the repo or hidden — an
|
|
16
|
+
**explicit up-front question** (bootstrap step 2), never an assumed default. The two modes then
|
|
17
|
+
diverge:
|
|
18
|
+
|
|
19
|
+
- **visible** — artifacts are committed. Wire the project's `package.json` scripts (`docs:check` / `docs:index` / `docs:index:check` / `docs:archive` / `docs:archive:check` / `docs:archive:issues` / `docs:archive:issues:check` / `prepare: node scripts/install-git-hooks.mjs`) and add a minimal `.gitignore` (`docs/plans/`, `.claude/settings.local.json`). This is the canonical model.
|
|
20
|
+
- **hidden** (in-tree) — same files on disk, but the repo "looks normal": append the artifact paths (`AGENTS.md`, `CLAUDE.md`, `docs/ai/`, `docs/plans/`, `scripts/*.mjs` you added, `docs/ai/.memory-version`, and — if a kit fallback bootstrap stamped one — `docs/ai/.workflow-version`) to the global excludes file git **already uses** (`git config --get core.excludesFile`); if none is set, point it at `~/.gitignore_global` (`git config --global core.excludesFile ~/.gitignore_global`) and append there. **Verify `git status` shows the artifacts as ignored** afterwards. **Do not edit `package.json`** — that is a tracked change and would leak; the pre-commit hook (always untracked in `.git/hooks/`) calls the scripts via `node scripts/<x>.mjs` directly.
|
|
21
|
+
|
|
22
|
+
Not in this version: a fully-external hidden mode (artifacts relocated outside the repo tree).
|
|
23
|
+
Deferred to a later release + migration.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Communication contract
|
|
28
|
+
|
|
29
|
+
The user chooses at bootstrap (step 3) which language the agent **talks to them** in. The choice is
|
|
30
|
+
recorded in the *Communication language* block of the project's `AGENTS.md`, so every agent that
|
|
31
|
+
reads the entry point honours it — and stops drifting between languages mid-session.
|
|
32
|
+
|
|
33
|
+
Scope — **dialogue only**:
|
|
34
|
+
|
|
35
|
+
- **In the chosen language** — everything the agent produces *for the user to read*: questions, explanations, plan summaries, status updates, commit-message prose if asked, review notes.
|
|
36
|
+
- **Always in their source language** — code, identifiers, file paths, shell commands, log/console output, error strings, config keys, and abbreviations/acronyms. Translating these breaks copy-paste, search, and tooling.
|
|
37
|
+
- **Files aren't translated** — the deployed `docs/ai/` files, `AGENTS.md`, and this kernel stay in their source language regardless of the chosen language (cross-agent / cross-team portability). The conversational language is about the *chat*, not the *artifacts*.
|
|
38
|
+
|
|
39
|
+
Default to the language the user is already writing in; confirm rather than assume. On `upgrade`, a
|
|
40
|
+
pre-1.1.0 deployment with no block gets one (the agent asks).
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Attribution contract
|
|
45
|
+
|
|
46
|
+
The user chooses at bootstrap (step 4) whether the agent may **attribute work to itself or to AI**.
|
|
47
|
+
The choice is recorded in the *Attribution* block of the project's `AGENTS.md`, so every agent that
|
|
48
|
+
reads the entry point honours it. **Default is `off`** — people are routinely surprised to find an
|
|
49
|
+
AI listed as a repo contributor (a `Co-Authored-By` trailer is enough to do it), so opt-in, never
|
|
50
|
+
opt-out.
|
|
51
|
+
|
|
52
|
+
When attribution is **`off`**, no mention of the agent, AI, or the model appears **anywhere**:
|
|
53
|
+
|
|
54
|
+
- **No `Co-Authored-By` trailers** and **no "Generated with …" footers** on commits or PRs.
|
|
55
|
+
- **No AI/agent/model references** in code, comments, commit messages, PR titles/bodies, branch names, or `docs/` prose. The work reads as the human author's.
|
|
56
|
+
- **Two enforcement layers** — the *Attribution* block binds everything an agent writes **by hand**; the automatic `Co-Authored-By` trailer is added by the **harness**, not the prose, so for **Claude Code** the bootstrap also sets `"includeCoAuthoredBy": false` in the project's `.claude/settings.json`. Other tools: disable their equivalent co-author/footer setting if present.
|
|
57
|
+
|
|
58
|
+
When **`on`**, the agent may add its standard trailer / footer per the user's tooling defaults. This
|
|
59
|
+
block is about *attribution*, not authorship of the actual changes — quality, tests, and the "ask
|
|
60
|
+
before commit" rule are unchanged either way.
|
|
61
|
+
|
|
62
|
+
On `upgrade`, a pre-1.2.0 deployment with no block gets one (the agent asks, defaulting to `off`).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Minimal dependency-free `expect` shim mapping the Vitest matchers used by the
|
|
2
|
+
// kernel's *.test.mjs onto node:assert, so the suite runs under `node --test` with
|
|
3
|
+
// zero dependencies. Supports only the matchers these tests use.
|
|
4
|
+
import assert from 'node:assert/strict';
|
|
5
|
+
|
|
6
|
+
const has = (actual, expected) => {
|
|
7
|
+
if (typeof actual === 'string') return actual.includes(expected);
|
|
8
|
+
if (Array.isArray(actual)) return actual.includes(expected);
|
|
9
|
+
return false;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const matchers = (actual, negate) => ({
|
|
13
|
+
toBe: (expected) =>
|
|
14
|
+
negate ? assert.notStrictEqual(actual, expected) : assert.strictEqual(actual, expected),
|
|
15
|
+
toEqual: (expected) =>
|
|
16
|
+
negate ? assert.notDeepStrictEqual(actual, expected) : assert.deepStrictEqual(actual, expected),
|
|
17
|
+
toContain: (expected) =>
|
|
18
|
+
assert.ok(
|
|
19
|
+
negate ? !has(actual, expected) : has(actual, expected),
|
|
20
|
+
`expected ${JSON.stringify(actual)} ${negate ? 'not ' : ''}to contain ${JSON.stringify(expected)}`,
|
|
21
|
+
),
|
|
22
|
+
toMatch: (re) => (negate ? assert.doesNotMatch(actual, re) : assert.match(actual, re)),
|
|
23
|
+
toHaveLength: (n) =>
|
|
24
|
+
negate ? assert.notStrictEqual(actual.length, n) : assert.strictEqual(actual.length, n),
|
|
25
|
+
toBeNull: () => (negate ? assert.notStrictEqual(actual, null) : assert.strictEqual(actual, null)),
|
|
26
|
+
toBeInstanceOf: (Ctor) =>
|
|
27
|
+
assert.ok(
|
|
28
|
+
negate ? !(actual instanceof Ctor) : actual instanceof Ctor,
|
|
29
|
+
`expected value ${negate ? 'not ' : ''}to be instance of ${Ctor.name}`,
|
|
30
|
+
),
|
|
31
|
+
toBeGreaterThan: (n) =>
|
|
32
|
+
assert.ok(negate ? !(actual > n) : actual > n, `expected ${actual} ${negate ? 'not ' : ''}> ${n}`),
|
|
33
|
+
toBeLessThan: (n) =>
|
|
34
|
+
assert.ok(negate ? !(actual < n) : actual < n, `expected ${actual} ${negate ? 'not ' : ''}< ${n}`),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const expect = (actual) => {
|
|
38
|
+
const api = matchers(actual, false);
|
|
39
|
+
api.not = matchers(actual, true);
|
|
40
|
+
return api;
|
|
41
|
+
};
|