pluribus-context 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.
- package/CHANGELOG.md +40 -0
- package/LICENSE +21 -0
- package/README.md +294 -0
- package/bin/pluribus.js +108 -0
- package/docs/composable-contexts.md +124 -0
- package/docs/openclaw-integration.md +145 -0
- package/docs/release-checklist.md +91 -0
- package/docs/remote-composable-context-imports.md +233 -0
- package/examples/claude-cowork/.cursorrules +82 -0
- package/examples/claude-cowork/pluribus.md +137 -0
- package/examples/composable-contexts/pluribus.md +29 -0
- package/examples/composable-contexts/shared/security-constraints.md +6 -0
- package/examples/composable-contexts/shared/team-context.md +10 -0
- package/examples/openclaw/AGENTS.md +134 -0
- package/examples/openclaw/CLAUDE.md +132 -0
- package/examples/openclaw/pluribus.md +99 -0
- package/package.json +52 -0
- package/spec/context-format.md +356 -0
- package/spec/skills-format.md +325 -0
- package/src/commands/init.js +153 -0
- package/src/commands/sync.js +213 -0
- package/src/commands/validate.js +146 -0
- package/src/commands/watch.js +111 -0
- package/src/index.js +11 -0
- package/src/skills/built-in.js +345 -0
- package/src/utils/args.js +35 -0
- package/src/utils/imports.js +690 -0
- package/src/utils/parser.js +74 -0
- package/src/utils/renderer.js +123 -0
- package/src/utils/version.js +1 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# OpenClaw Integration
|
|
2
|
+
|
|
3
|
+
OpenClaw is an AI agent runner that uses **`AGENTS.md`** as its primary context file. Pluribus can generate and keep `AGENTS.md` in sync from a single `pluribus.md` source.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
OpenClaw reads `AGENTS.md` on startup to understand:
|
|
10
|
+
|
|
11
|
+
- The agent's **identity** — name, role, persona
|
|
12
|
+
- **Sub-agent system** — what agents exist and when to spawn them
|
|
13
|
+
- **Tools and integrations** — external services the agent can use
|
|
14
|
+
- **Operating rules** — constraints, protocols, and guardrails
|
|
15
|
+
- **Soul/tone** — how the agent communicates
|
|
16
|
+
|
|
17
|
+
Pluribus maps your `pluribus.md` sections to a well-structured `AGENTS.md`:
|
|
18
|
+
|
|
19
|
+
| `pluribus.md` section | `AGENTS.md` output |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `# Identity` | Identity block (name, role, emoji) |
|
|
22
|
+
| `# Agents` | Sub-agent system table |
|
|
23
|
+
| `# Stack` | Tools and integrations |
|
|
24
|
+
| `# Conventions` | Operating protocols |
|
|
25
|
+
| `# Constraints` | Hard rules and guardrails |
|
|
26
|
+
| `# Soul` | Tone and behavior guidance |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Workflow
|
|
31
|
+
|
|
32
|
+
### 1. Initialize
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cd your-openclaw-workspace/
|
|
36
|
+
pluribus init --tools openclaw
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This scaffolds `pluribus.md` with OpenClaw-specific sections pre-filled.
|
|
40
|
+
|
|
41
|
+
### 2. Edit `pluribus.md`
|
|
42
|
+
|
|
43
|
+
Write your agent context once:
|
|
44
|
+
|
|
45
|
+
```markdown
|
|
46
|
+
# Identity
|
|
47
|
+
|
|
48
|
+
I am Friday, the primary AI agent for Lucio.
|
|
49
|
+
|
|
50
|
+
# Agents
|
|
51
|
+
|
|
52
|
+
| Agent | Role | When to spawn |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| FORGE | Engineering | All coding tasks |
|
|
55
|
+
| ARGUS | Research | Feed collection, market signals |
|
|
56
|
+
|
|
57
|
+
# Constraints
|
|
58
|
+
|
|
59
|
+
- Never write code directly — delegate to FORGE
|
|
60
|
+
- Never send external messages without confirmation
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. Sync
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pluribus sync --tools openclaw
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Output:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
🔄 Syncing pluribus.md → openclaw
|
|
73
|
+
|
|
74
|
+
✅ [openclaw] → AGENTS.md
|
|
75
|
+
|
|
76
|
+
✅ Sync complete — 1 file(s) written.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 4. OpenClaw picks it up
|
|
80
|
+
|
|
81
|
+
On next gateway startup (or `openclaw gateway restart`), OpenClaw reads the updated `AGENTS.md` and your agent reflects the new context.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## File Placement
|
|
86
|
+
|
|
87
|
+
By default, `AGENTS.md` is written to the current directory (your OpenClaw workspace root). This is typically:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
workspace/
|
|
91
|
+
├── pluribus.md ← your source of truth
|
|
92
|
+
├── AGENTS.md ← generated by pluribus sync
|
|
93
|
+
├── SOUL.md ← tone file (optional, not generated)
|
|
94
|
+
└── TOOLS.md ← tool notes (optional, not generated)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Dry Run
|
|
100
|
+
|
|
101
|
+
Preview what will be generated without writing:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pluribus sync --tools openclaw --dry-run
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Example
|
|
110
|
+
|
|
111
|
+
See [`examples/openclaw/`](../examples/openclaw/) for a full working example:
|
|
112
|
+
|
|
113
|
+
- [`pluribus.md`](../examples/openclaw/pluribus.md) — source context file
|
|
114
|
+
- [`AGENTS.md`](../examples/openclaw/AGENTS.md) — generated output
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## OpenClaw-Specific Sections
|
|
119
|
+
|
|
120
|
+
When targeting OpenClaw, two sections unlock additional output:
|
|
121
|
+
|
|
122
|
+
### `# Agents` (sub-agent table)
|
|
123
|
+
|
|
124
|
+
Generates the sub-agent routing table in `AGENTS.md`:
|
|
125
|
+
|
|
126
|
+
```markdown
|
|
127
|
+
# Agents
|
|
128
|
+
|
|
129
|
+
| Agent | Role | When to spawn |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| FORGE ⚙️ | Engineering | All coding and system-building |
|
|
132
|
+
| ARGUS 🔍 | Research | Market signals, feed collection |
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### `# Soul`
|
|
136
|
+
|
|
137
|
+
Maps to a behavioral guidance block in `AGENTS.md`. This is the tone section — how the agent communicates, what it avoids, how it handles uncertainty.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Notes
|
|
142
|
+
|
|
143
|
+
- `AGENTS.md` is generated — do not edit it manually. Edit `pluribus.md` and re-sync.
|
|
144
|
+
- If you also use Claude Code, run `pluribus sync --tools openclaw,claude` to update both `AGENTS.md` and `CLAUDE.md` from the same source.
|
|
145
|
+
- The OpenClaw skill is built-in — no configuration needed.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Release checklist
|
|
2
|
+
|
|
3
|
+
This checklist keeps Pluribus releases reproducible and avoids accidentally publishing stale context, missing docs, or a package name that collides with an unrelated project.
|
|
4
|
+
|
|
5
|
+
## 0. Preconditions
|
|
6
|
+
|
|
7
|
+
- Work from a clean `main` branch tracking `origin/main`.
|
|
8
|
+
- Confirm the package name is available or intentionally chosen:
|
|
9
|
+
- `npm view pluribus-context name version description`
|
|
10
|
+
- `npm view pluribus name version description` — expected to return an unrelated package, so do not publish as `pluribus`.
|
|
11
|
+
- Confirm npm auth only through the npm CLI/session, never by writing tokens into the repo:
|
|
12
|
+
- `npm whoami`
|
|
13
|
+
|
|
14
|
+
## 1. Version and release notes
|
|
15
|
+
|
|
16
|
+
- Update `package.json` version.
|
|
17
|
+
- Update `CHANGELOG.md` with user-facing changes, migration notes, and verification commands.
|
|
18
|
+
- Confirm README install commands use the package name `pluribus-context` and that the binary remains `pluribus`.
|
|
19
|
+
|
|
20
|
+
## 2. Local checks
|
|
21
|
+
|
|
22
|
+
Run from the repo root:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm test
|
|
26
|
+
git diff --check
|
|
27
|
+
npm pack --dry-run
|
|
28
|
+
npm publish --dry-run
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The dry-run package should include at least:
|
|
32
|
+
|
|
33
|
+
- `README.md`
|
|
34
|
+
- `LICENSE`
|
|
35
|
+
- `CHANGELOG.md`
|
|
36
|
+
- `bin/pluribus.js`
|
|
37
|
+
- `src/`
|
|
38
|
+
- `docs/`
|
|
39
|
+
- `spec/`
|
|
40
|
+
- `examples/`
|
|
41
|
+
|
|
42
|
+
## 3. Tarball install smoke
|
|
43
|
+
|
|
44
|
+
Before publishing, install the exact tarball that `npm pack` creates into a temporary project and run the CLI as a user would. This catches version drift or missing packaged files that unit tests and dry-runs can miss.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm run release:smoke
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The script packs the current checkout, installs that tarball into a temporary project, runs `pluribus --version`, `--help`, `init`, `validate`, `sync --dry-run`, and a real `sync`, then checks that generated output includes the package version from `package.json`. It also removes the temporary project and generated tarball on exit.
|
|
51
|
+
|
|
52
|
+
Expected results:
|
|
53
|
+
|
|
54
|
+
- `pluribus --version` matches `package.json`.
|
|
55
|
+
- `pluribus --help` shows the same version.
|
|
56
|
+
- generated files mention the same Pluribus version.
|
|
57
|
+
- `validate` and `sync --dry-run` work from the installed package, not the repo checkout.
|
|
58
|
+
|
|
59
|
+
## 4. Publish
|
|
60
|
+
|
|
61
|
+
Only publish after npm auth is active and the dry run is clean:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npm publish --access public
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Then verify:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm view pluribus-context version dist.tarball
|
|
71
|
+
npx pluribus-context --help
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 5. GitHub release
|
|
75
|
+
|
|
76
|
+
After npm publish succeeds:
|
|
77
|
+
|
|
78
|
+
- Tag the exact published commit: `vX.Y.Z`.
|
|
79
|
+
- Create a GitHub release using the matching `CHANGELOG.md` section.
|
|
80
|
+
- Link the npm package and the GitHub release from any launch post or reply.
|
|
81
|
+
|
|
82
|
+
## 6. Post-release monitoring
|
|
83
|
+
|
|
84
|
+
Within the next work block, check:
|
|
85
|
+
|
|
86
|
+
- GitHub Actions for the release commit/tag.
|
|
87
|
+
- GitHub issues/notifications.
|
|
88
|
+
- npm package page metadata.
|
|
89
|
+
- Any X/Reddit/Discord replies mentioning install problems.
|
|
90
|
+
|
|
91
|
+
If install fails or package contents are wrong, do not keep posting. Patch, test, publish a fix version, and document what changed.
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Remote Composable Context Imports
|
|
2
|
+
|
|
3
|
+
Status: remote MVP implemented for explicit `github:`/`https://` fetches, lock/cache offline reuse, and optional GitHub auth for private imports. Remaining design work: CI/cache policy ergonomics and deeper structured error context.
|
|
4
|
+
|
|
5
|
+
## Goals
|
|
6
|
+
|
|
7
|
+
Remote imports should let teams inherit shared context from GitHub or HTTPS without making Pluribus non-deterministic, credential-leaky, or unsafe in CI.
|
|
8
|
+
|
|
9
|
+
The design principle is the same as local imports: explicit context inheritance, expanded before project-local context, with local sections still winning.
|
|
10
|
+
|
|
11
|
+
## Syntax
|
|
12
|
+
|
|
13
|
+
Keep the existing directive form:
|
|
14
|
+
|
|
15
|
+
```markdown
|
|
16
|
+
# @import <spec>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Add remote specs:
|
|
20
|
+
|
|
21
|
+
```markdown
|
|
22
|
+
# @import github:owner/repo/path/to/context.md
|
|
23
|
+
# @import github:owner/repo/path/to/context.md@ref
|
|
24
|
+
# @import https://example.com/context.md
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
For GitHub imports, `@ref` should support a branch, tag, or commit SHA. Pinned refs are recommended; floating default-branch imports should warn in local/dev use and fail in CI unless explicitly refreshed.
|
|
28
|
+
|
|
29
|
+
If a GitHub path includes `@`, parse the ref from the rightmost `@`.
|
|
30
|
+
|
|
31
|
+
## Resolution semantics
|
|
32
|
+
|
|
33
|
+
- Preserve the current expansion order: imported content expands before the importing file's local content.
|
|
34
|
+
- Preserve current duplicate-section behavior: later local sections override earlier imported sections.
|
|
35
|
+
- Remote files may contain nested imports, but they must obey the same max depth and safety rules.
|
|
36
|
+
- Relative imports inside a GitHub file resolve relative to that file path in the same repo/ref.
|
|
37
|
+
- Relative imports inside arbitrary HTTPS files are a non-goal for the first remote MVP.
|
|
38
|
+
- Keep the existing max import depth of `5` unless there is strong evidence to change it.
|
|
39
|
+
|
|
40
|
+
## Auth
|
|
41
|
+
|
|
42
|
+
- Public GitHub and HTTPS imports work without auth.
|
|
43
|
+
- Private GitHub imports may use existing credentials only during `pluribus sync --update-imports`.
|
|
44
|
+
- Credential lookup order: `GH_TOKEN`, then `GITHUB_TOKEN`, then an existing GitHub CLI login via `gh auth token`.
|
|
45
|
+
- Do not support inline tokens, token CLI flags, lockfile/cache auth metadata, or arbitrary custom headers in the MVP.
|
|
46
|
+
- Do not store tokens in `pluribus.lock.json` or `.pluribus/cache/remote/`; the lockfile is safe to commit and the cache is local/regenerable.
|
|
47
|
+
- Error messages must redact credentials, credential-bearing URLs, and known token values.
|
|
48
|
+
|
|
49
|
+
## Lockfile and cache
|
|
50
|
+
|
|
51
|
+
Add a project lockfile:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
pluribus.lock.json
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Each locked remote import should include:
|
|
58
|
+
|
|
59
|
+
- normalized import spec
|
|
60
|
+
- resolved source URL or GitHub API target
|
|
61
|
+
- resolved immutable commit SHA when available
|
|
62
|
+
- SHA-256 content digest
|
|
63
|
+
- byte size
|
|
64
|
+
- fetched timestamp
|
|
65
|
+
- content type
|
|
66
|
+
|
|
67
|
+
Cache downloaded content by digest, for example:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
.pluribus/cache/remote/<sha256>.md
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Default `pluribus sync` should prefer the lockfile/cache for deterministic runs. Network refresh should require an explicit flag such as:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pluribus sync --update-imports
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Deterministic CI
|
|
80
|
+
|
|
81
|
+
CI/non-interactive runs should be deterministic by default:
|
|
82
|
+
|
|
83
|
+
- fail if a remote import is unlocked
|
|
84
|
+
- fail if required cached content is missing
|
|
85
|
+
- fail if an import uses a floating GitHub ref without an explicit update mode
|
|
86
|
+
- fail on digest mismatch
|
|
87
|
+
- avoid network unless explicitly enabled
|
|
88
|
+
|
|
89
|
+
Recommended workflow:
|
|
90
|
+
|
|
91
|
+
1. Developer runs `pluribus sync --update-imports`.
|
|
92
|
+
2. Pluribus writes or updates `pluribus.lock.json` and cache entries.
|
|
93
|
+
3. Developer commits the lockfile.
|
|
94
|
+
4. CI runs `pluribus sync --dry-run` without fetching remote content.
|
|
95
|
+
|
|
96
|
+
## Network and content limits
|
|
97
|
+
|
|
98
|
+
Defaults for the MVP:
|
|
99
|
+
|
|
100
|
+
- HTTPS only; continue rejecting `http://`
|
|
101
|
+
- 5s per-request timeout
|
|
102
|
+
- 15s total remote resolution budget
|
|
103
|
+
- 256 KiB max per remote file
|
|
104
|
+
- 1 MiB max merged remote content
|
|
105
|
+
- max 3 redirects
|
|
106
|
+
- redirects must stay on `https://`
|
|
107
|
+
- UTF-8 Markdown text only
|
|
108
|
+
- reject binary or non-UTF-8 content
|
|
109
|
+
- strip UTF-8 BOM before parsing, matching local import behavior
|
|
110
|
+
|
|
111
|
+
## Supply-chain safety
|
|
112
|
+
|
|
113
|
+
- Never execute imported content.
|
|
114
|
+
- Never shell out based on imported content or import specs; the only subprocess is the fixed optional `gh auth token` credential lookup when env tokens are absent.
|
|
115
|
+
- Never support post-processing hooks.
|
|
116
|
+
- Require digest pinning for deterministic use.
|
|
117
|
+
- Fail hard on lockfile digest mismatch.
|
|
118
|
+
- Do not allow remote imports to resolve into local filesystem paths.
|
|
119
|
+
- Treat remote imports as data, not configuration authority.
|
|
120
|
+
|
|
121
|
+
## Error model
|
|
122
|
+
|
|
123
|
+
Keep the current clear failure style from `resolveImports`, but add structured internal error codes for tests and callers:
|
|
124
|
+
|
|
125
|
+
- `REMOTE_IMPORT_TIMEOUT`
|
|
126
|
+
- `REMOTE_IMPORT_TOO_LARGE`
|
|
127
|
+
- `REMOTE_IMPORT_AUTH_REQUIRED`
|
|
128
|
+
- `REMOTE_IMPORT_LOCK_MISSING`
|
|
129
|
+
- `REMOTE_IMPORT_DIGEST_MISMATCH`
|
|
130
|
+
- `REMOTE_IMPORT_UNSAFE_REDIRECT`
|
|
131
|
+
- `REMOTE_IMPORT_UNSUPPORTED_CONTENT`
|
|
132
|
+
|
|
133
|
+
User-facing errors should include:
|
|
134
|
+
|
|
135
|
+
- import spec
|
|
136
|
+
- importing file
|
|
137
|
+
- import chain
|
|
138
|
+
- concise cause
|
|
139
|
+
|
|
140
|
+
They should never include auth headers, tokens, credential-bearing URLs, or remote body content.
|
|
141
|
+
|
|
142
|
+
## MVP scope
|
|
143
|
+
|
|
144
|
+
Shipped in the first remote MVP:
|
|
145
|
+
|
|
146
|
+
- `github:owner/repo/path.md[@ref]`
|
|
147
|
+
- direct `https://...` Markdown/text files
|
|
148
|
+
- unauthenticated public imports
|
|
149
|
+
- optional private GitHub imports via `GH_TOKEN`/`GITHUB_TOKEN` or logged-in `gh`
|
|
150
|
+
- explicit `pluribus sync --update-imports` network access
|
|
151
|
+
- lockfile generation/update and cache by SHA-256 digest
|
|
152
|
+
- deterministic offline lock/cache reuse with digest verification
|
|
153
|
+
- timeout, redirect, content-type, UTF-8, per-file size, and merged-size guards
|
|
154
|
+
- credential-bearing URL rejection/redaction
|
|
155
|
+
- nested GitHub imports within the same repo/ref
|
|
156
|
+
|
|
157
|
+
Still pending for the hardening phase:
|
|
158
|
+
|
|
159
|
+
- CI/cache policy ergonomics
|
|
160
|
+
- immutable GitHub commit resolution metadata
|
|
161
|
+
- richer import-chain context in structured errors
|
|
162
|
+
|
|
163
|
+
Non-goals:
|
|
164
|
+
|
|
165
|
+
- `http://`
|
|
166
|
+
- GitLab/Bitbucket shorthand
|
|
167
|
+
- arbitrary request headers
|
|
168
|
+
- remote directory imports or globs
|
|
169
|
+
- executable imports or hooks
|
|
170
|
+
- automatic dependency updates
|
|
171
|
+
- relative imports from arbitrary HTTPS documents
|
|
172
|
+
- silent network access in deterministic CI mode
|
|
173
|
+
|
|
174
|
+
## Implementation shape
|
|
175
|
+
|
|
176
|
+
Current implementation keeps `resolveImports(sourcePath, options)` as the synchronous local-only entry point and adds `resolveImportsAsync(sourcePath, { allowRemote })` for explicit remote resolution:
|
|
177
|
+
|
|
178
|
+
- local resolver: existing filesystem behavior
|
|
179
|
+
- GitHub resolver: normalize `github:` specs and fetch raw content, optionally with existing GitHub auth
|
|
180
|
+
- HTTPS resolver: fetch Markdown/text with timeout and size guards
|
|
181
|
+
- lock/cache module: read/write `pluribus.lock.json`, verify digest, read/write cached blobs
|
|
182
|
+
|
|
183
|
+
Potential options:
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
resolveImports(sourcePath, {
|
|
187
|
+
allowRemote: false,
|
|
188
|
+
updateImports: false,
|
|
189
|
+
offline: false,
|
|
190
|
+
lockfilePath: 'pluribus.lock.json',
|
|
191
|
+
cacheDir: '.pluribus/cache/remote',
|
|
192
|
+
timeoutMs: 5000,
|
|
193
|
+
maxRemoteBytes: 256 * 1024,
|
|
194
|
+
maxMergedRemoteBytes: 1024 * 1024,
|
|
195
|
+
})
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
CLI flag shipped: `pluribus sync --update-imports` enables remote network fetches. Without that flag, remote directives fail clearly instead of doing silent network access.
|
|
199
|
+
|
|
200
|
+
## Test checklist
|
|
201
|
+
|
|
202
|
+
- [x] parses `github:` imports with `@ref`
|
|
203
|
+
- [x] rejects `http://`
|
|
204
|
+
- [x] redacts auth in errors
|
|
205
|
+
- [x] enforces timeout
|
|
206
|
+
- [x] enforces per-file and merged-size limits
|
|
207
|
+
- [x] rejects unsafe redirects
|
|
208
|
+
- [x] writes deterministic lockfile entries
|
|
209
|
+
- [x] reads from lock/cache without network in CI/offline mode
|
|
210
|
+
- [x] fails on missing lock entry in CI/offline mode
|
|
211
|
+
- [x] fails on digest mismatch
|
|
212
|
+
- [x] supports nested GitHub imports within the same repo/ref
|
|
213
|
+
- [x] rejects unsupported HTTPS-relative nested imports
|
|
214
|
+
- [x] preserves local override behavior after remote expansion
|
|
215
|
+
|
|
216
|
+
## Suggested issue #9 checklist
|
|
217
|
+
|
|
218
|
+
```markdown
|
|
219
|
+
Next phase for #9: harden remote composable context imports.
|
|
220
|
+
|
|
221
|
+
- [x] Specify remote syntax: `github:owner/repo/path.md[@ref]` and `https://...`.
|
|
222
|
+
- [x] Preserve local MVP merge behavior: imports expand before local content; local duplicate sections win.
|
|
223
|
+
- [x] Add `pluribus.lock.json` design with SHA-256 digest, size, fetched timestamp, and content type. Resolved commit metadata remains pending.
|
|
224
|
+
- [x] Add cache design around the explicit `--update-imports` refresh flow.
|
|
225
|
+
- [x] Define CI/offline behavior: fail on unlocked/cache-missing imports unless explicitly updating. Floating ref policy remains pending.
|
|
226
|
+
- [x] Define auth: public unauthenticated fetches plus optional existing `GH_TOKEN`/`GITHUB_TOKEN` or logged-in `gh`; never persist or log secrets.
|
|
227
|
+
- [x] Enforce safety limits: HTTPS only, request timeout, max bytes, redirect limit, UTF-8 Markdown only.
|
|
228
|
+
- [x] Define supply-chain protections: digest verification, hard fail on mismatch, no execution/hooks.
|
|
229
|
+
- [ ] Add structured remote import errors with import-chain context and broader secret redaction.
|
|
230
|
+
- [x] MVP: GitHub + direct HTTPS files only.
|
|
231
|
+
- [x] Non-goals: `http://`, arbitrary headers, GitLab/Bitbucket shorthand, directory/glob imports, HTTPS-relative nested imports.
|
|
232
|
+
- [ ] Add tests for lockfile determinism, digest mismatch, and CI/offline mode.
|
|
233
|
+
```
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Generated by Pluribus 0.1.0 on 2026-03-08 — do not edit manually
|
|
2
|
+
# Source: pluribus.md | Skill: cursor
|
|
3
|
+
# Project: Orbital — Multi-tenant logistics SaaS
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
You are assisting the **Orbital** engineering team — 5 backend engineers building a multi-tenant SaaS for logistics operations. TypeScript monorepo using NestJS, PostgreSQL (drizzle-orm), and BullMQ. All engineers use shared conventions.
|
|
8
|
+
|
|
9
|
+
## Tech Stack
|
|
10
|
+
|
|
11
|
+
- TypeScript 5.4 (strict mode) + Node.js 22 LTS
|
|
12
|
+
- NestJS 10 with Fastify adapter
|
|
13
|
+
- PostgreSQL 16 via drizzle-orm (NO raw SQL in application code)
|
|
14
|
+
- BullMQ + Redis 7 for job queues
|
|
15
|
+
- Jest 29 + Supertest for testing
|
|
16
|
+
- pnpm workspaces monorepo
|
|
17
|
+
- ESLint flat config + Prettier (2-space, single quotes, trailing commas)
|
|
18
|
+
|
|
19
|
+
## Code Conventions
|
|
20
|
+
|
|
21
|
+
- `async/await` only — never `.then()/.catch()`
|
|
22
|
+
- No `any` — use `unknown` with explicit narrowing
|
|
23
|
+
- Named exports only — no default exports, no barrel files
|
|
24
|
+
- File naming: `kebab-case.ts`
|
|
25
|
+
- NestJS pattern: `<feature>.module.ts`, `<feature>.service.ts`, `<feature>.controller.ts`
|
|
26
|
+
- Error handling: always use `AppError` from `packages/core/errors` — never throw plain strings or generic `Error`
|
|
27
|
+
- No circular dependencies (enforced by ESLint)
|
|
28
|
+
- No `@ts-ignore` or `@ts-expect-error`
|
|
29
|
+
|
|
30
|
+
## Testing
|
|
31
|
+
|
|
32
|
+
- Unit tests for all service methods with side effects
|
|
33
|
+
- Integration tests for all controller endpoints via Supertest
|
|
34
|
+
- Use test factories from `test/factories/` — never construct objects manually in tests
|
|
35
|
+
- Inject mocks via DI — no module-level `jest.mock()`
|
|
36
|
+
- Test naming: `describe('<Unit>', () => { it('should <behavior> when <condition>', ...) })`
|
|
37
|
+
|
|
38
|
+
## Pull Requests
|
|
39
|
+
|
|
40
|
+
- PRs must be < 400 lines (excluding generated files and migrations)
|
|
41
|
+
- Every PR needs at least one test covering the new behavior
|
|
42
|
+
- Migrations must be reviewed by Ana (`@ana/tech-lead`) before merge
|
|
43
|
+
- No self-merging — minimum 1 approval required
|
|
44
|
+
- Fill the PR description template: What, Why, How, Risk, Test plan
|
|
45
|
+
|
|
46
|
+
## AI Review Rules
|
|
47
|
+
|
|
48
|
+
When reviewing code:
|
|
49
|
+
- Check for correctness, type safety, and convention violations (not style — Prettier handles that)
|
|
50
|
+
- Flag missing error handling in async paths
|
|
51
|
+
- Flag raw SQL outside drizzle-orm
|
|
52
|
+
- Flag new endpoints without integration tests
|
|
53
|
+
- Flag new endpoints without declared RBAC role
|
|
54
|
+
- Never suggest approving a PR with failing CI
|
|
55
|
+
|
|
56
|
+
## Constraints (Non-negotiable)
|
|
57
|
+
|
|
58
|
+
- NO raw SQL — all queries through drizzle-orm schema types
|
|
59
|
+
- NO `any` type — use `unknown` and narrow
|
|
60
|
+
- NO secrets in the repository — ever
|
|
61
|
+
- NO new direct dependencies without an ADR in `docs/adr/`
|
|
62
|
+
- NO bypassing RBAC — every endpoint declares its required role
|
|
63
|
+
- NO modifying migration files after they've been applied to staging or production
|
|
64
|
+
- NO `console.log` in production code — use `packages/core/logger`
|
|
65
|
+
- NO singleton mutable state outside of NestJS module providers
|
|
66
|
+
|
|
67
|
+
## Goals
|
|
68
|
+
|
|
69
|
+
- Correctness over speed — a broken feature costs more than a slow one
|
|
70
|
+
- Consistent codebase across all 5 engineers
|
|
71
|
+
- PR cycle time under 24 hours
|
|
72
|
+
- Zero production incidents from merged code
|
|
73
|
+
- Junior team members learn through Claude's explanations, not just receive generated code
|
|
74
|
+
|
|
75
|
+
## Anti-patterns to Avoid
|
|
76
|
+
|
|
77
|
+
- Fat controllers: business logic belongs in services
|
|
78
|
+
- Barrel files that re-export everything
|
|
79
|
+
- Data transforms inside schema migration files
|
|
80
|
+
- Returning HTTP 200 for business errors — use proper status codes + `AppError.httpStatus`
|
|
81
|
+
- `console.log` in production paths
|
|
82
|
+
- Optimistic locking without retry loop
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Identity
|
|
2
|
+
|
|
3
|
+
We are the **Orbital** engineering team — 5 backend engineers building a multi-tenant SaaS platform for logistics operations.
|
|
4
|
+
|
|
5
|
+
We use Claude Code heavily for code review, pair programming, and greenfield feature work. Claude is treated as a senior team member, not a code autocomplete tool. It attends PR reviews, writes tests, and proposes architectural changes.
|
|
6
|
+
|
|
7
|
+
**Team:**
|
|
8
|
+
- **Ana (tech lead):** owns architecture decisions, API design, and final approval on schema changes
|
|
9
|
+
- **Bruno:** payment integrations, billing engine
|
|
10
|
+
- **Clara:** logistics domain, route optimization
|
|
11
|
+
- **Diego:** infrastructure, observability, CI/CD
|
|
12
|
+
- **Elena:** frontend (React + TypeScript), design system
|
|
13
|
+
|
|
14
|
+
All engineers use Claude Code. Shared conventions apply to all AI-assisted work.
|
|
15
|
+
|
|
16
|
+
# Stack
|
|
17
|
+
|
|
18
|
+
- **Language:** TypeScript 5.4 (strict mode)
|
|
19
|
+
- **Runtime:** Node.js 22 LTS
|
|
20
|
+
- **Framework:** NestJS 10 (REST API) + Fastify adapter
|
|
21
|
+
- **Database:** PostgreSQL 16 via `drizzle-orm`
|
|
22
|
+
- **Message queue:** BullMQ + Redis 7
|
|
23
|
+
- **Testing:** Jest 29 + Supertest; coverage threshold: 80% on all PRs
|
|
24
|
+
- **Linting:** ESLint flat config (team-shared config in `packages/eslint-config`)
|
|
25
|
+
- **Formatting:** Prettier (2-space indent, single quotes, trailing commas)
|
|
26
|
+
- **Package manager:** pnpm + workspaces monorepo
|
|
27
|
+
- **CI/CD:** GitHub Actions — lint, test, type-check on every PR; deploy to staging on merge to `main`
|
|
28
|
+
- **Auth:** JWT (access) + refresh tokens; role-based access control (RBAC)
|
|
29
|
+
- **Monitoring:** OpenTelemetry → Grafana Cloud
|
|
30
|
+
- **No raw SQL in application code** — all queries through drizzle-orm schema types
|
|
31
|
+
|
|
32
|
+
# Conventions
|
|
33
|
+
|
|
34
|
+
## Code
|
|
35
|
+
|
|
36
|
+
- `async/await` only — no `.then()/.catch()`
|
|
37
|
+
- No class decorators for business logic — NestJS decorators only for DI wiring
|
|
38
|
+
- No `any` — `unknown` with explicit narrowing
|
|
39
|
+
- Error handling: use the shared `AppError` class from `packages/core/errors`; never throw plain strings or generic `Error`
|
|
40
|
+
- Named exports — no default exports, no barrel files unless explicitly discussed
|
|
41
|
+
- File naming: `kebab-case.ts`; NestJS modules follow `<feature>.module.ts`, `<feature>.service.ts` etc.
|
|
42
|
+
- No circular dependencies — enforce with `eslint-plugin-import`
|
|
43
|
+
|
|
44
|
+
## Testing
|
|
45
|
+
|
|
46
|
+
- Unit tests for all service methods with side effects
|
|
47
|
+
- Integration tests for all controller endpoints using Supertest
|
|
48
|
+
- Test factories in `test/factories/` — never construct objects manually in tests
|
|
49
|
+
- No `jest.mock()` at module level — use dependency injection and pass mocks through constructor
|
|
50
|
+
- Test descriptions: `describe('<Unit>', () => { it('<should do X when Y>', ...) })`
|
|
51
|
+
|
|
52
|
+
## Pull Requests
|
|
53
|
+
|
|
54
|
+
- PRs must be < 400 lines changed (excluding generated files and migrations)
|
|
55
|
+
- Every PR needs at least one test covering the new behavior
|
|
56
|
+
- PR description: fill the template (What, Why, How, Risk, Test plan)
|
|
57
|
+
- Migrations must be reviewed by Ana before merge — tag `@ana/tech-lead` in the PR
|
|
58
|
+
- No self-merging — at least one approval required
|
|
59
|
+
- Draft PRs are welcome for early feedback; mark ready when CI passes
|
|
60
|
+
|
|
61
|
+
## AI-Assisted Code Review
|
|
62
|
+
|
|
63
|
+
When Claude is used for PR review:
|
|
64
|
+
- Focus on correctness, type safety, and convention violations — not style (Prettier handles that)
|
|
65
|
+
- Always check for missing error handling in async paths
|
|
66
|
+
- Flag any SQL written outside drizzle-orm types
|
|
67
|
+
- Check that new endpoints have corresponding integration tests
|
|
68
|
+
- Do not approve PRs with failing tests, regardless of context
|
|
69
|
+
|
|
70
|
+
## Branching
|
|
71
|
+
|
|
72
|
+
- `main` → production
|
|
73
|
+
- `staging` → staging environment (auto-deploy)
|
|
74
|
+
- Feature branches: `feat/<ticket-id>-<short-description>`
|
|
75
|
+
- Hotfix branches: `hotfix/<ticket-id>-<short-description>`
|
|
76
|
+
- Never commit directly to `main` or `staging`
|
|
77
|
+
|
|
78
|
+
# Goals
|
|
79
|
+
|
|
80
|
+
1. Ship reliable features — correctness over speed; a broken feature costs more than a slow one
|
|
81
|
+
2. Maintain a consistent codebase across 5 engineers — conventions enforce shared quality, not personal preference
|
|
82
|
+
3. PR cycle time < 24h — fast reviews unblock the team; slow reviews kill momentum
|
|
83
|
+
4. Zero production incidents from merged code — staging catches what tests miss
|
|
84
|
+
5. Knowledge sharing — Claude should help junior team members learn through its explanations, not just generate code
|
|
85
|
+
|
|
86
|
+
# Constraints
|
|
87
|
+
|
|
88
|
+
- Never approve or suggest merging a PR with failing CI
|
|
89
|
+
- Never write raw SQL — always use drizzle-orm schema types and query builder
|
|
90
|
+
- Never commit secrets or environment variables to the repository
|
|
91
|
+
- Do not add direct dependencies without an ADR (Architecture Decision Record) in `docs/adr/`
|
|
92
|
+
- Never bypass RBAC — new endpoints must declare their required role
|
|
93
|
+
- Never modify migration files after they've been applied to staging or production
|
|
94
|
+
- Do not suggest patterns that require `@ts-ignore` or `@ts-expect-error`
|
|
95
|
+
- No singleton state outside of NestJS module providers — no module-level mutable variables
|
|
96
|
+
|
|
97
|
+
# Workflow
|
|
98
|
+
|
|
99
|
+
## Feature Development
|
|
100
|
+
|
|
101
|
+
1. Pick ticket from the sprint board
|
|
102
|
+
2. Create feature branch: `feat/<ticket-id>-<description>`
|
|
103
|
+
3. Write tests first for complex domain logic (TDD preferred in logistics domain)
|
|
104
|
+
4. Open PR as Draft early — tag relevant reviewers
|
|
105
|
+
5. When CI passes → mark PR as Ready for Review
|
|
106
|
+
6. One approval + all checks green → merge to `main`
|
|
107
|
+
7. Monitor staging deploy; check observability dashboard
|
|
108
|
+
|
|
109
|
+
## Code Review Checklist
|
|
110
|
+
|
|
111
|
+
When reviewing (human or AI-assisted):
|
|
112
|
+
|
|
113
|
+
- [ ] Does it have tests covering the new behavior?
|
|
114
|
+
- [ ] Are errors handled correctly (using `AppError`)?
|
|
115
|
+
- [ ] Is the TypeScript type coverage complete (no `any`)?
|
|
116
|
+
- [ ] Are there any raw SQL queries?
|
|
117
|
+
- [ ] Does it respect RBAC for new endpoints?
|
|
118
|
+
- [ ] Is the PR < 400 lines?
|
|
119
|
+
- [ ] Is the PR description filled out?
|
|
120
|
+
- [ ] Are new dependencies justified?
|
|
121
|
+
|
|
122
|
+
## ADR Process
|
|
123
|
+
|
|
124
|
+
Any new library, architectural pattern, or significant deviation from convention requires an ADR:
|
|
125
|
+
- File: `docs/adr/YYYY-MM-DD-<slug>.md`
|
|
126
|
+
- Sections: Context, Decision, Alternatives considered, Consequences
|
|
127
|
+
- Reviewed asynchronously; Ana signs off on architectural ADRs
|
|
128
|
+
|
|
129
|
+
# Anti-patterns
|
|
130
|
+
|
|
131
|
+
- **Fat controllers:** Business logic belongs in services, not in NestJS controllers
|
|
132
|
+
- **Barrel files that re-export everything:** They make refactoring hard and break tree-shaking
|
|
133
|
+
- **Test isolation via `jest.clearAllMocks()` in `afterEach`:** Use proper DI and scoped mocks instead
|
|
134
|
+
- **Migrations with data transforms:** Schema changes and data migrations are separate PRs
|
|
135
|
+
- **Optimistic locking without retries:** If you use `version` columns for optimistic concurrency, you must handle the retry loop
|
|
136
|
+
- **`console.log` in production code:** Use the shared `logger` from `packages/core/logger`
|
|
137
|
+
- **Returning 200 for business errors:** Use proper HTTP status codes + `AppError` with `httpStatus` field
|