@se-studio/skills 1.9.8 → 1.9.10
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 +12 -0
- package/LICENSE.pstack +21 -0
- package/README.md +4 -0
- package/VENDOR_PSTACK.md +52 -0
- package/package.json +1 -1
- package/references/agent-session/customer-agents-block.md +5 -3
- package/references/agent-session/customer-architecture.mdc +1 -1
- package/references/agent-session/customer-code-review.md +2 -2
- package/references/agent-session/fleet-status.mjs +125 -0
- package/references/agent-session/production-merge.md +35 -19
- package/references/agent-session/projects.registry.json +5 -3
- package/references/agent-session/release-verification.md +82 -0
- package/skills/architect/SKILL.md +87 -0
- package/skills/architect/references/design-red-flags.md +57 -0
- package/skills/architect/references/rationale-template.md +35 -0
- package/skills/architect/references/runner-prompt.md +20 -0
- package/skills/blast-radius/SKILL.md +55 -0
- package/skills/coding-discipline/SKILL.md +2 -2
- package/skills/contentful-cms-core/SKILL.md +11 -0
- package/skills/how/SKILL.md +43 -0
- package/skills/how/references/explainer-prompt.md +55 -0
- package/skills/how/references/explorer-prompt.md +35 -0
- package/skills/interrogate/SKILL.md +78 -0
- package/skills/interrogate/references/code-quality-review.md +47 -0
- package/skills/interrogate/references/lead-judgment.md +58 -0
- package/skills/interrogate/references/reviewer-prompt.md +62 -0
- package/skills/interrogate/references/rubric.md +77 -0
- package/skills/principle-boundary-discipline/SKILL.md +38 -0
- package/skills/principle-encode-lessons-in-structure/SKILL.md +15 -0
- package/skills/principle-fix-root-causes/SKILL.md +27 -0
- package/skills/principle-guard-the-context-window/SKILL.md +16 -0
- package/skills/principle-make-operations-idempotent/SKILL.md +28 -0
- package/skills/principle-minimize-reader-load/SKILL.md +22 -0
- package/skills/principle-model-the-domain/SKILL.md +28 -0
- package/skills/principle-prove-it-works/SKILL.md +26 -0
- package/skills/principle-sequence-verifiable-units/SKILL.md +21 -0
- package/skills/principle-subtract-before-you-add/SKILL.md +22 -0
- package/skills/principle-test-behavior-not-implementation/SKILL.md +25 -0
- package/skills/principle-type-system-discipline/SKILL.md +22 -0
- package/skills/se-marketing-sites-smoke-test-setup/SKILL.md +27 -1
- package/skills/site-workflows-agent-session/SKILL.md +23 -10
- package/skills/tdd/SKILL.md +46 -0
- package/skills/typescript-best-practices/SKILL.md +35 -0
- package/skills/typescript-best-practices/references/patterns.md +324 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @se-studio/skills
|
|
2
2
|
|
|
3
|
+
## 1.9.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e737e76: Allow agents to promote se-core-product `dev` → `main` (npm Release Main) only after the same ask + second-confirm gate as customer production. Updates `production-merge.md`, agent-session skill, and related docs.
|
|
8
|
+
|
|
9
|
+
## 1.9.9
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 96e1908: Add fleet-status so an agent session lists every local checkout, its drift, and its worktrees before and after the work.
|
|
14
|
+
|
|
3
15
|
## 1.9.8
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/LICENSE.pstack
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lauren Tan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -89,6 +89,10 @@ Do not edit `packages/contentful-cms/skills/` directly. See `packages/contentful
|
|
|
89
89
|
|
|
90
90
|
**Do not use `.claude/skills/` in the repo** as a skill source — it is untracked and local. Use `.agents/skills/` (via `pnpm skills:sync`) or `cms-edit skill install`.
|
|
91
91
|
|
|
92
|
+
## Vendored pstack (trial)
|
|
93
|
+
|
|
94
|
+
SE Studio may vendor a **subset** of [cursor/plugins pstack](https://github.com/cursor/plugins/tree/main/pstack) skills under `skills/` for a se-core-product-only trial. See [`VENDOR_PSTACK.md`](./VENDOR_PSTACK.md) for the pin, adopt/exclude list, Auto-only adaptations, and MIT attribution (`LICENSE.pstack`). Gate rule: [`.cursor/rules/pstack-trial-gates.mdc`](../../.cursor/rules/pstack-trial-gates.mdc). Do **not** run `/setup-pstack` or install excluded skills (`poteto-mode`, `arena`, `swarm`, Benny, etc.). No npm release of these trial skills until Nick approves a customer rollout.
|
|
95
|
+
|
|
92
96
|
## References
|
|
93
97
|
|
|
94
98
|
- [Anthropic skill authoring best practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices)
|
package/VENDOR_PSTACK.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Vendored pstack skills (SE Studio trial)
|
|
2
|
+
|
|
3
|
+
**Status:** se-core-product Project trial only. Not a customer rollout.
|
|
4
|
+
**Upstream:** [cursor/plugins `pstack/`](https://github.com/cursor/plugins/tree/main/pstack)
|
|
5
|
+
**Pinned commit:** `1b6d44ff26d4e242f4e8f68c391e6d2f7ca16def` (`main` as of vendor date)
|
|
6
|
+
**Plugin version observed:** `0.15.20` (`pstack/plugin.json`)
|
|
7
|
+
**License:** MIT — see [`LICENSE.pstack`](./LICENSE.pstack)
|
|
8
|
+
|
|
9
|
+
## What was vendored
|
|
10
|
+
|
|
11
|
+
Canonical copies live under `packages/skills/skills/<name>/` (synced to `.agents/skills/` via `pnpm skills:sync`).
|
|
12
|
+
|
|
13
|
+
### Skills (6)
|
|
14
|
+
|
|
15
|
+
| Directory | Adaptation |
|
|
16
|
+
|-----------|------------|
|
|
17
|
+
| `interrogate` | Auto-only reviewers; panel ≤1–2; no `pstack-models.mdc` / setup-pstack; no xhigh/max |
|
|
18
|
+
| `blast-radius` | Dual-Auto optional instead of arena; soft refs to uninstalled skills |
|
|
19
|
+
| `how` | Auto/`inherit-parent` for explorers and explainers; complex path capped at ≤4 explorers + 1 explainer (≈5 Auto Tasks); soft-dep `why` skip-if-missing |
|
|
20
|
+
| `architect` | **Arena disabled** — single Auto sketch agent; still requires ≥2 design candidates; Phase C does not waive SE gates; runner-prompt aligned to single-Auto; soft-deps skip-if-missing |
|
|
21
|
+
| `typescript-best-practices` | Frontmatter only (`paths` / `disable-model-invocation` moved to body notes) |
|
|
22
|
+
| `tdd` | Frontmatter only |
|
|
23
|
+
|
|
24
|
+
### Principles (12)
|
|
25
|
+
|
|
26
|
+
`principle-type-system-discipline`, `principle-prove-it-works`, `principle-test-behavior-not-implementation`, `principle-fix-root-causes`, `principle-boundary-discipline`, `principle-subtract-before-you-add`, `principle-make-operations-idempotent`, `principle-sequence-verifiable-units`, `principle-minimize-reader-load`, `principle-encode-lessons-in-structure`, `principle-guard-the-context-window`, `principle-model-the-domain`
|
|
27
|
+
|
|
28
|
+
## Explicitly not vendored
|
|
29
|
+
|
|
30
|
+
| Category | Names |
|
|
31
|
+
|----------|-------|
|
|
32
|
+
| Modes / setup | `poteto-mode`, `setup-pstack` |
|
|
33
|
+
| Principles | `principle-never-block-on-the-human`, `principle-migrate-callers-then-delete-legacy-apis` |
|
|
34
|
+
| Benny | `automations/benny/**` |
|
|
35
|
+
| Fan-out | `swarm`, `arena` |
|
|
36
|
+
| Adapt later | `recall`, `create-verification-skill`, `maintain-verification-skill` |
|
|
37
|
+
|
|
38
|
+
## Frontmatter contract
|
|
39
|
+
|
|
40
|
+
Upstream `SKILL.md` files used extra keys (`disable-model-invocation`, `paths`). SE Studio allows **only** `name` and `description` (see `packages/skills/README.md`). Extra keys were moved into an “SE Studio vendoring notes” section in each skill body.
|
|
41
|
+
|
|
42
|
+
## Gate rule
|
|
43
|
+
|
|
44
|
+
Repo always-applied rule: [`.cursor/rules/pstack-trial-gates.mdc`](../../.cursor/rules/pstack-trial-gates.mdc). SE Studio approval gates win over any pstack principle.
|
|
45
|
+
|
|
46
|
+
## Publish posture
|
|
47
|
+
|
|
48
|
+
**No** `@se-studio/skills` changeset for this trial. Skills sync in this monorepo only. Customer Project rollout is a separate decision after the two-week trial.
|
|
49
|
+
|
|
50
|
+
## Operator note (not in repo)
|
|
51
|
+
|
|
52
|
+
Do not run `/setup-pstack` or `/add-plugin pstack` for this trial. If `~/.cursor/rules/pstack-models.mdc` exists on a machine, delete or replace it with an Auto-only stub before trial chats.
|
package/package.json
CHANGED
|
@@ -19,7 +19,7 @@ Default mode for this repo: **site-first**.
|
|
|
19
19
|
- Agents may commit and push **`develop`** and **`feature/*`**.
|
|
20
20
|
- Merge feature → `develop` only when Nick approves **in chat** (no `nick-go` GitHub label).
|
|
21
21
|
- Customer production (`main`, HSD `production`) **only** after the human-ask + confirm gate (`production-merge.md` in `@se-studio/skills`). The human must ask to merge integration → production in this conversation; the agent must restate site, branches, and that it publishes production; then wait for a second **yes**.
|
|
22
|
-
- **Never** treat “deploy”, “ship it”, or “rollout” as permission. **Never** ship from a production checkout (e.g. HSD `production-hsd-website`). Use the develop checkout only.
|
|
22
|
+
- **Never** treat “deploy”, “ship it”, or “rollout” as permission. **Never** ship from a production checkout (e.g. HSD `production-hsd-website`). Use the develop checkout only. se-core-product `dev` → `main` (npm promote) is ask + confirm in a **core** session — do not promote core from this customer session.
|
|
23
23
|
- Prefer **draft PRs** to `develop` over direct pushes when `gh` is available.
|
|
24
24
|
|
|
25
25
|
### Core vs customer placement
|
|
@@ -48,8 +48,8 @@ State placement in chat (and the PR) before smoke/server-config commits aimed at
|
|
|
48
48
|
|
|
49
49
|
When work depends on a new `@se-studio/*` npm release:
|
|
50
50
|
|
|
51
|
-
1. Release from `se-core-product` (`dev` →
|
|
52
|
-
2. Confirm version on npm
|
|
51
|
+
1. Release from `se-core-product` (integrate + version on `dev` → promote to `main` → Release Main publishes)
|
|
52
|
+
2. Confirm version on npm (from that `main` release)
|
|
53
53
|
3. `pnpm update @se-studio/<package>@<version> -r` in this repo
|
|
54
54
|
4. Then push / merge to `develop` after chat approval
|
|
55
55
|
|
|
@@ -88,3 +88,5 @@ Site-local learnings: `docs/AGENT_PROCESS_NOTES.md`. Say **“promote process no
|
|
|
88
88
|
### Production handoff
|
|
89
89
|
|
|
90
90
|
When **marketing** work is ready, agents **stop** and hand off. Merge `develop` → production only after ask + confirm (`production-merge.md`). One site at a time. No `vercel deploy`. cms-edit host extra gate: `cms-edit-prod-merge.md`.
|
|
91
|
+
|
|
92
|
+
When the promote depends on new/changed Contentful content, complete **release verification** (`release-verification.md` in `@se-studio/skills`): publish state (CDA vs CPA), content smoke (not HTTP-only), preview compare (≥3 pages on published-only build), and no unresolved failed production build. Nick override never skips publish-state or content smoke.
|
|
@@ -37,7 +37,7 @@ Source of truth: `se-core-product` `docs/PHILOSOPHY.md`. Code review: `CODE_REVI
|
|
|
37
37
|
|
|
38
38
|
- Consent and analytics go through core adapters. No direct `dataLayer` pushes.
|
|
39
39
|
- Never send names, emails, phones, form answers, or raw errors to analytics/URLs.
|
|
40
|
-
- Forms submit server-side
|
|
40
|
+
- Forms submit server-side (provider is site-chosen; core has no default). Preview/develop must not post to production CRM/forms destinations or production GTM.
|
|
41
41
|
- No secrets in code/tests/logs. Avoid new `NEXT_PUBLIC_*` unless the browser must see the value.
|
|
42
42
|
|
|
43
43
|
## Tests / ship / review
|
|
@@ -27,7 +27,7 @@ Run all five lenses. Skip a lens only when the diff clearly cannot touch it (say
|
|
|
27
27
|
- [ ] CMS routes stay static (`●`). No `headers()`/`cookies()` in a layout that forces the tree dynamic without measured justification.
|
|
28
28
|
- [ ] Fetches go through core helpers with cache tags. No raw CDA `fetch`.
|
|
29
29
|
- [ ] Images/video use core `Visual` + `calculateVisualSizes` (values match layout; mobile vs laptop not reversed).
|
|
30
|
-
- [ ] Preview/develop must not post to production
|
|
30
|
+
- [ ] Preview/develop must not post to production CRM/forms destinations or production GTM.
|
|
31
31
|
|
|
32
32
|
### 3. Performance and size
|
|
33
33
|
|
|
@@ -50,7 +50,7 @@ Run all five lenses. Skip a lens only when the diff clearly cannot touch it (say
|
|
|
50
50
|
- Secrets, tokens, or `.env` values in code, tests, comments, or logs. Avoid new `NEXT_PUBLIC_*` unless the browser must see the value.
|
|
51
51
|
- Personal data or form field values in events, dataLayer, HubSpot payloads, or URLs.
|
|
52
52
|
- Consent granted by default where a CMP decides, or bypassing site consent gating.
|
|
53
|
-
- Forms: preview posting to production
|
|
53
|
+
- Forms: preview posting to production CRM/forms destinations or GTM, or bypassing server-side submit.
|
|
54
54
|
- Hard-coded heading skips, `Visual` without size helpers, or needless duplicate mobile/desktop content.
|
|
55
55
|
- Failing typecheck, lint, or tests; new behaviour with no test where the site already tests that layer.
|
|
56
56
|
- Smoke/discovery/`server-config` hacks to unblock deploy smoke (belongs in `@se-studio/site-check`).
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Read-only status of every registry checkout on this machine.
|
|
4
|
+
* Run from any directory: node packages/skills/references/agent-session/fleet-status.mjs
|
|
5
|
+
*/
|
|
6
|
+
import { execFileSync } from 'node:child_process';
|
|
7
|
+
import { readFileSync } from 'node:fs';
|
|
8
|
+
import { homedir } from 'node:os';
|
|
9
|
+
import { dirname, join } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
|
|
12
|
+
const registryPath = join(dirname(fileURLToPath(import.meta.url)), 'projects.registry.json');
|
|
13
|
+
const registry = JSON.parse(readFileSync(registryPath, 'utf8'));
|
|
14
|
+
|
|
15
|
+
function expand(path) {
|
|
16
|
+
if (path.startsWith('~/')) return join(homedir(), path.slice(2));
|
|
17
|
+
return path;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function git(cwd, args) {
|
|
21
|
+
try {
|
|
22
|
+
return execFileSync('git', args, {
|
|
23
|
+
cwd,
|
|
24
|
+
encoding: 'utf8',
|
|
25
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
26
|
+
}).trim();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
const stderr = error.stderr?.toString().trim() || error.message;
|
|
29
|
+
return { error: stderr.split('\n')[0] };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function ignored(file) {
|
|
34
|
+
const base = file.split('/').pop();
|
|
35
|
+
if (base === 'skills-lock.json' || base === 'next-env.d.ts' || base === 'redirects.ts') {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return file === '.agents/skills' || file.startsWith('.agents/skills/');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function statusPaths(cwd) {
|
|
42
|
+
const raw = git(cwd, ['status', '--porcelain']);
|
|
43
|
+
if (raw.error) return raw;
|
|
44
|
+
const tracked = [];
|
|
45
|
+
const untracked = [];
|
|
46
|
+
for (const line of raw.split('\n').filter(Boolean)) {
|
|
47
|
+
const path = line.slice(3).split(' -> ').pop();
|
|
48
|
+
if (ignored(path)) continue;
|
|
49
|
+
if (line.startsWith('??')) untracked.push(path);
|
|
50
|
+
else tracked.push(`${line.slice(0, 2).trim()} ${path}`);
|
|
51
|
+
}
|
|
52
|
+
return { tracked, untracked };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function worktrees(cwd, primary) {
|
|
56
|
+
const raw = git(cwd, ['worktree', 'list', '--porcelain']);
|
|
57
|
+
if (raw.error) return [];
|
|
58
|
+
const trees = [];
|
|
59
|
+
let current = null;
|
|
60
|
+
for (const line of raw.split('\n')) {
|
|
61
|
+
if (line.startsWith('worktree ')) {
|
|
62
|
+
if (current) trees.push(current);
|
|
63
|
+
current = { path: line.slice(9), branch: '(detached)' };
|
|
64
|
+
} else if (current && line.startsWith('branch ')) {
|
|
65
|
+
current.branch = line.slice('branch refs/heads/'.length);
|
|
66
|
+
} else if (current && line.startsWith('HEAD ')) {
|
|
67
|
+
current.head = line.slice(5, 12);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (current) trees.push(current);
|
|
71
|
+
return trees.filter((tree) => tree.path !== primary);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function printList(label, items, limit = 12) {
|
|
75
|
+
const shown = items.slice(0, limit);
|
|
76
|
+
for (const item of shown) console.log(` ${label} ${item}`);
|
|
77
|
+
if (items.length > limit) console.log(` ${label} +${items.length - limit} more`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log(`fleet-status ${new Date().toISOString().slice(0, 10)}`);
|
|
81
|
+
|
|
82
|
+
for (const project of registry.projects) {
|
|
83
|
+
const path = expand(project.path);
|
|
84
|
+
const branch = project.branch;
|
|
85
|
+
console.log('');
|
|
86
|
+
const inside = git(path, ['rev-parse', '--is-inside-work-tree']);
|
|
87
|
+
if (inside.error || inside !== 'true') {
|
|
88
|
+
console.log(`${project.key} MISSING ${path}`);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const fetched = git(path, ['fetch', '--prune', 'origin', branch]);
|
|
93
|
+
const current = git(path, ['branch', '--show-current']);
|
|
94
|
+
const head = git(path, ['rev-parse', '--short', 'HEAD']);
|
|
95
|
+
const ahead = git(path, ['rev-list', '--count', `origin/${branch}..HEAD`]);
|
|
96
|
+
const behind = git(path, ['rev-list', '--count', `HEAD..origin/${branch}`]);
|
|
97
|
+
const wrong = current !== branch ? ` primary is ${current}` : '';
|
|
98
|
+
const drift =
|
|
99
|
+
ahead.error || behind.error ? ' origin unknown' : ` ahead ${ahead} behind ${behind}`;
|
|
100
|
+
console.log(`${project.key} ${branch} ${head.error ? '?' : head}${drift}${wrong}`);
|
|
101
|
+
if (fetched.error) console.log(` fetch: ${fetched.error}`);
|
|
102
|
+
|
|
103
|
+
const status = statusPaths(path);
|
|
104
|
+
if (status.error) {
|
|
105
|
+
console.log(` status: ${status.error}`);
|
|
106
|
+
} else {
|
|
107
|
+
printList('dirty', status.tracked);
|
|
108
|
+
printList('untracked', status.untracked);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
for (const tree of worktrees(path, path)) {
|
|
112
|
+
const when = git(tree.path, ['log', '-1', '--format=%cs']);
|
|
113
|
+
const date = when.error ? '?' : when;
|
|
114
|
+
const feature = tree.branch.startsWith('feature/') || tree.branch.startsWith('cursor/');
|
|
115
|
+
if (!feature) {
|
|
116
|
+
console.log(` checkout ${tree.path} ${tree.branch} ${tree.head ?? ''} ${date}`);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const extra = git(tree.path, ['rev-list', '--count', `origin/${branch}..HEAD`]);
|
|
120
|
+
const aheadOf = extra.error ? '?' : extra;
|
|
121
|
+
console.log(
|
|
122
|
+
` worktree ${tree.path} ${tree.branch} ${tree.head ?? ''} ${date} commits not in origin/${branch}: ${aheadOf}`,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -1,30 +1,35 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Production and core `main` merge (human ask + confirm)
|
|
2
2
|
|
|
3
|
-
Agents may merge a **customer** integration branch to that site’s production branch **only** when this gate passes. The point is **no automatic or accidental publishing**.
|
|
3
|
+
Agents may merge a **customer** integration branch to that site’s production branch, **or** promote **se-core-product** `dev` → `main`, **only** when this gate passes. The point is **no automatic or accidental publishing**.
|
|
4
4
|
|
|
5
5
|
This is **not** a silent exception. Two human messages in **this conversation** are required: an explicit merge request, then a separate confirmation after the agent restates what will publish.
|
|
6
6
|
|
|
7
|
-
**se-core-product `main`
|
|
7
|
+
**se-core-product `main` is ask + confirm** (same pattern as customer production). Package releases integrate and version on `dev` (CI Dev), then publish when promoted to `main` (Release Main / OIDC). Agents may run that promote **only** after ask + second confirm below.
|
|
8
8
|
|
|
9
9
|
Canonical skill: `site-workflows-agent-session`. Customer `AGENTS.md` copies the short form from `customer-agents-block.md`.
|
|
10
10
|
|
|
11
|
-
## Production branches
|
|
11
|
+
## Production / promote branches
|
|
12
12
|
|
|
13
|
-
| Repo | Integration |
|
|
14
|
-
|
|
15
|
-
| Customer marketing sites | `develop` | usually `main` |
|
|
13
|
+
| Repo | Integration | Target (what merges) |
|
|
14
|
+
|------|-------------|----------------------|
|
|
15
|
+
| Customer marketing sites | `develop` | usually `main` (Git-connected Vercel production) |
|
|
16
16
|
| HopSkipDrive | `develop` | **`production`** |
|
|
17
|
+
| **se-core-product** | `dev` | **`main`** (Release Main → npm publish; may deploy anything on `main`) |
|
|
17
18
|
|
|
18
|
-
Never ship from a registry `productionPath` checkout. Merge with `gh` from the **develop** checkout.
|
|
19
|
+
Never ship customer production from a registry `productionPath` checkout. Merge with `gh` from the **develop** checkout (customers) or the se-core primary / approved checkout (core promote).
|
|
19
20
|
|
|
20
21
|
## Gate (all must hold)
|
|
21
22
|
|
|
22
|
-
1. **Ask.** In this conversation the human named the **site or repo** and asked to merge
|
|
23
|
+
1. **Ask.** In this conversation the human named the **site or repo** and asked to merge:
|
|
24
|
+
- **Customer:** integration → production (e.g. “merge develop to main”, “merge develop into production for OM1”).
|
|
25
|
+
- **se-core-product:** `dev` → `main` / npm promote (e.g. “promote to main”, “merge dev to main”, “publish packages”).
|
|
23
26
|
2. **Confirm.** The agent **stops**, restates the exact merge, and waits for a **second** affirmative reply (`yes` / `confirm` / `do it`) to **that** restatement. The original ask is not confirmation.
|
|
24
|
-
3. **One repo.** Merge one customer repo at a time. Do not fan out “all sites to production”.
|
|
25
|
-
4. **Git only.** `gh pr merge` or equivalent to `origin/<
|
|
27
|
+
3. **One repo.** Merge one customer repo at a time. Do not fan out “all sites to production”. Core promote is one `dev` → `main` merge (do not also merge customer production in the same step unless asked and confirmed separately).
|
|
28
|
+
4. **Git only.** `gh pr merge` or equivalent to `origin/<targetBranch>`. **Never** `vercel deploy`, `pnpm cms-edit:deploy`, or Netlify promote. Do **not** run `pnpm release` / `npm publish` from a laptop unless the human explicitly asked for a **manual** publish (normal path is Release Main on push to `main`).
|
|
29
|
+
5. **Prerequisites (core promote).** Version bumps must already be on `dev` (pending `.changeset/*.md` consumed by CI Dev). Do not promote while changesets remain. Post `## Merge approval` on the promote PR (who, where, when Europe/London, head SHA, review). Merge approval is **in addition to** ask + confirm — not a substitute.
|
|
30
|
+
6. **Release verification (customer).** When the customer promote depends on new or changed Contentful entries, complete [`release-verification.md`](./release-verification.md) (publish state via CDA vs CPA, content smoke, preview compare, no unresolved failed production build). Record results on the promote PR. A Nick override never skips publish-state or content smoke.
|
|
26
31
|
|
|
27
|
-
### Restatement (required before merge)
|
|
32
|
+
### Restatement — customer production (required before merge)
|
|
28
33
|
|
|
29
34
|
Send this shape, filled in, then wait:
|
|
30
35
|
|
|
@@ -33,29 +38,40 @@ Send this shape, filled in, then wait:
|
|
|
33
38
|
> That publishes **production** (Git-connected Vercel).
|
|
34
39
|
> I will not merge until you reply **yes** to this message.
|
|
35
40
|
|
|
36
|
-
|
|
41
|
+
### Restatement — se-core-product `main` (required before merge)
|
|
42
|
+
|
|
43
|
+
Send this shape, filled in, then wait:
|
|
44
|
+
|
|
45
|
+
> You asked to merge **se-core-product**
|
|
46
|
+
> `origin/dev` → `origin/main`.
|
|
47
|
+
> That runs **Release Main** and **publishes npm packages** (and may deploy anything on `main`).
|
|
48
|
+
> I will not merge until you reply **yes** to this message.
|
|
49
|
+
|
|
50
|
+
If they say no, stop. If they name a different repo or target, restate again.
|
|
37
51
|
|
|
38
52
|
## Not permission (do not merge)
|
|
39
53
|
|
|
40
54
|
These are **not** an ask, and never count as confirmation:
|
|
41
55
|
|
|
42
56
|
- “ship it”, “deploy”, “rollout”, “publish”, “go live”, “it’s ready”
|
|
43
|
-
- Opening or merging a PR to `develop`
|
|
44
|
-
- A production PR already existing
|
|
57
|
+
- Opening or merging a PR to `develop` / `dev`
|
|
58
|
+
- A production or `main` PR already existing
|
|
45
59
|
- “when Vercel is green, merge it” (pre-authorisation)
|
|
46
60
|
- Scheduler / previous-session leftovers
|
|
47
61
|
- CI needing `main`, default-branch workflows
|
|
48
62
|
- cms-edit host “must be on production” without an explicit merge request
|
|
63
|
+
- “version packages” / merge to `dev` alone (does **not** publish npm)
|
|
49
64
|
|
|
50
65
|
## After a confirmed merge
|
|
51
66
|
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
**Customer:** Wait for that site’s marketing (and cms-edit host, if Git-connected) Vercel **production** Ready. Do not merge a second site until the first is Ready or the human asks again and confirms again.
|
|
68
|
+
|
|
69
|
+
**se-core-product:** Wait for Release Main to finish; confirm versions on npm (`npm view @se-studio/<pkg> version`) before bumping customer lockfiles.
|
|
54
70
|
|
|
55
71
|
## cms-edit-only extra gate
|
|
56
72
|
|
|
57
|
-
Hosted cms-edit rollouts still use [`cms-edit-prod-merge.md`](./cms-edit-prod-merge.md) **in addition** to this confirm gate (path allowlist, npm version, health check). Confirmation is required there too.
|
|
73
|
+
Hosted cms-edit rollouts still use [`cms-edit-prod-merge.md`](./cms-edit-prod-merge.md) **in addition** to this confirm gate (path allowlist, npm version, health check). Confirmation is required there too. That path is **customer** `develop` → production only — not se-core `main`.
|
|
58
74
|
|
|
59
75
|
## If the gate fails
|
|
60
76
|
|
|
61
|
-
Do **not** merge. Open a PR targeting production if useful, hand off, and wait.
|
|
77
|
+
Do **not** merge. Open a PR targeting production / `main` if useful, hand off, and wait.
|
|
@@ -118,13 +118,15 @@
|
|
|
118
118
|
{
|
|
119
119
|
"key": "eagle",
|
|
120
120
|
"displayName": "Eagle Website",
|
|
121
|
-
"path": "~/source/customers/
|
|
121
|
+
"path": "~/source/customers/eaglecap/eagle-website",
|
|
122
122
|
"worktreesRoot": "~/source/customers/eagle/worktrees",
|
|
123
|
-
"branch": "
|
|
123
|
+
"branch": "develop",
|
|
124
124
|
"productionBranch": "main",
|
|
125
125
|
"type": "customer",
|
|
126
|
+
"contentfulSpaceId": "dnov2dthcze8",
|
|
127
|
+
"hostedMcp": "cms-edit-eagle",
|
|
126
128
|
"validate": "pnpm validate",
|
|
127
|
-
"notes": "
|
|
129
|
+
"notes": "Integration is origin/develop. Production is origin/main. cms-edit host builds only on main. Hosted MCP: https://eagle.content.se.studio/api/mcp. This machine's develop checkout is ~/source/customers/eaglecap/eagle-website. Feature worktrees go under worktreesRoot."
|
|
128
130
|
}
|
|
129
131
|
]
|
|
130
132
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Release verification (promote to production)
|
|
2
|
+
|
|
3
|
+
Standing rules from Nick, **7 Oct 2026** (19:41 BST), after Brightline provider pages went live without a published Contentful template Hero (missing headshots).
|
|
4
|
+
|
|
5
|
+
These rules apply to **every tool** — Cursor agents, Grok Build, and other local tools on Nick's Mac. A **Nick override** may skip review, but **never** skips rules **1** and **2**.
|
|
6
|
+
|
|
7
|
+
Canonical pointers: `AGENTS.md` § Release verification, `.cursor/rules/release-verification.mdc`, promote PR template section.
|
|
8
|
+
|
|
9
|
+
## Rules
|
|
10
|
+
|
|
11
|
+
### 1. Check publish state before promoting
|
|
12
|
+
|
|
13
|
+
Before any promote to production that depends on **new or changed Contentful entries**:
|
|
14
|
+
|
|
15
|
+
1. List every **entry**, **template**, **person** / person-type, and **content stack** the new/changed pages render through.
|
|
16
|
+
2. Confirm each is **published** in the production Contentful environment (usually `master`) with **no pending draft changes**.
|
|
17
|
+
3. Compare **CDA** (published / Delivery API) vs **CPA** (preview / Preview API).
|
|
18
|
+
4. Record the result in the **promote PR** (entry ids, content types, pass/fail).
|
|
19
|
+
|
|
20
|
+
Helper: `@se-studio/site-check/publish-state` (`checkPublishState`, CLI `check-publish-state`).
|
|
21
|
+
|
|
22
|
+
cms-edit: before a promote, verify linked **templates** and **person** entries are published (not draft-only). See `contentful-cms-core` publish guidance and `publish-handoff.md`.
|
|
23
|
+
|
|
24
|
+
### 2. Smoke tests check content, not just status
|
|
25
|
+
|
|
26
|
+
Live / production smoke must assert that **key page blocks render**, not only HTTP 200.
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
|
|
30
|
+
- Person pages: headshot image + name in the hero
|
|
31
|
+
- Listing cards: card images present and loadable
|
|
32
|
+
|
|
33
|
+
Use `contentAssert` on `smoke.cases.json` cases (`mustInclude`, `mustHaveSelector`, `imagesMustLoad`). Requires `@se-studio/site-check` with content-assert support.
|
|
34
|
+
|
|
35
|
+
### 3. Compare against the approved preview before merging a promote
|
|
36
|
+
|
|
37
|
+
Before merging a promote PR:
|
|
38
|
+
|
|
39
|
+
1. Run a build / preview against **published** content (Delivery token only — **no** preview token / CPA).
|
|
40
|
+
2. Compare **at least 3 representative pages** with the signed-off preview.
|
|
41
|
+
3. Note the comparison in the promote PR.
|
|
42
|
+
|
|
43
|
+
### 4. A failed production build blocks further merges to main
|
|
44
|
+
|
|
45
|
+
If a production build fails (Vercel or equivalent):
|
|
46
|
+
|
|
47
|
+
- **Do not** merge further PRs to that site’s production branch (`main` / HSD `production`) until the cause is found.
|
|
48
|
+
- Write the cause in the PR (e.g. unresolved / unpublished entry, missing template).
|
|
49
|
+
- Fix publish state or code, then re-verify rules 1–2 before retrying.
|
|
50
|
+
|
|
51
|
+
### 5. Applies to every tool; override limits
|
|
52
|
+
|
|
53
|
+
- Cursor, Grok Build, scripts, and humans follow the same checklist.
|
|
54
|
+
- `## Merge approval` with `none, Nick override` skips **review**, not rules **1** and **2**.
|
|
55
|
+
|
|
56
|
+
## Promote PR checklist (paste into the PR)
|
|
57
|
+
|
|
58
|
+
```markdown
|
|
59
|
+
## Release verification
|
|
60
|
+
|
|
61
|
+
- [ ] **Publish state (rule 1):** Listed entries/templates/people/content stack; CDA vs CPA clean; results recorded below
|
|
62
|
+
- [ ] **Content smoke (rule 2):** Live smoke asserts key blocks (not HTTP-only)
|
|
63
|
+
- [ ] **Preview compare (rule 3):** ≥3 pages vs signed-off preview on published-only build
|
|
64
|
+
- [ ] **Production build (rule 4):** No open failed production build; or cause documented and fixed
|
|
65
|
+
|
|
66
|
+
### Publish-state results
|
|
67
|
+
| Entry / type | Role | CDA | CPA | Pending draft? |
|
|
68
|
+
|--------------|------|-----|-----|----------------|
|
|
69
|
+
| | | | | |
|
|
70
|
+
|
|
71
|
+
### Preview compare
|
|
72
|
+
| Page URL | Matches signed-off preview? | Notes |
|
|
73
|
+
|----------|-------------------------------|-------|
|
|
74
|
+
| | | |
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Related
|
|
78
|
+
|
|
79
|
+
- [`production-merge.md`](./production-merge.md) — ask + confirm gate (still required)
|
|
80
|
+
- [`cms-edit-prod-merge.md`](./cms-edit-prod-merge.md) — cms-edit-only path allowlist
|
|
81
|
+
- `docs/CONSUMER_SITE_TESTING.md` — smoke setup
|
|
82
|
+
- `docs/RELEASE_VERIFICATION.md` — short index in the repo
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architect
|
|
3
|
+
description: "Sketch types, signatures, and module structure before code, then stay in the loop while implementation fills in. Use for /architect, 'architect this', 'design this', or non-trivial work where jumping to code would lock in the wrong shape."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Architect
|
|
7
|
+
|
|
8
|
+
Sketch types, function signatures, class shapes, and module boundaries with `not implemented` bodies and pseudocode. Synthesize across multiple model perspectives, then fill in code against the chosen sketch.
|
|
9
|
+
|
|
10
|
+
## SE Studio vendoring notes
|
|
11
|
+
|
|
12
|
+
- Upstream frontmatter `disable-model-invocation: true` moved out of YAML (SE Studio skills allow only name + description).
|
|
13
|
+
- **SE Studio trial: arena disabled.** Phase B uses a single sketch agent on the parent/`auto` model. Do not invoke the `arena` or `swarm` skills. Do not create or read `~/.cursor/rules/pstack-models.mdc` / `setup-pstack`. Never use `xhigh` or `max` model tiers.
|
|
14
|
+
- Skills / principles referenced but not in this trial install (`why`, `exhaust-the-design-space`, `foundational-thinking`, `outcome-oriented-execution`, `redesign-from-first-principles`, `laziness-protocol`, `separate-before-serializing-shared-state`): **skip if missing** — apply the idea inline; do not hunt for, install, or fail the workflow because the skill directory is absent.
|
|
15
|
+
- **SE gates win over Phase C.** “No human checkpoint before implement” covers design sketch → code fill-in only. It does **not** waive merge approval, cms-edit publish, production ask+confirm, release verification, or design-review-before-build for placement / schema / caching / analytics-forms (`AGENTS.md`, `.cursor/rules/pstack-trial-gates.mdc`, architecture R9.2).
|
|
16
|
+
|
|
17
|
+
## Start
|
|
18
|
+
|
|
19
|
+
Open a todolist with one entry per phase before starting.
|
|
20
|
+
|
|
21
|
+
1. Ground
|
|
22
|
+
2. Sketch
|
|
23
|
+
3. Agree
|
|
24
|
+
4. Implement
|
|
25
|
+
5. Scrap
|
|
26
|
+
|
|
27
|
+
## Phase A: Ground the problem
|
|
28
|
+
|
|
29
|
+
Build a real mental model of every system the new code touches. Run the **how** skill over the relevant subsystems (respect `/how` trial Task caps). Naming a file isn't grounding. Produce the architectural explanation `how` prescribes. If the design redefines ownership or layering and a **why** skill is available, also run it on the existing shape so the rationale becomes a constraint, not a guess. **`why` is not in this trial — skip if missing:** ground with `how` plus PR/commit history and say so.
|
|
30
|
+
|
|
31
|
+
Skip Phase A only when the work is genuinely greenfield with no surrounding system to integrate.
|
|
32
|
+
|
|
33
|
+
## Phase B: Sketch
|
|
34
|
+
|
|
35
|
+
**SE Studio trial fork (no arena):** spawn **one** Task subagent (`subagent_type: generalPurpose`, `readonly: true`) on the parent model. Omit `model` (treat as `auto` / `inherit-parent`). Pass `references/runner-prompt.md` as the runner prompt, plus Phase A grounding artifacts.
|
|
36
|
+
|
|
37
|
+
Do **not** run the `arena` skill. Do **not** fan out multiple model runners. Do **not** look up `architect runners` / `arena runners` in a `pstack-models.mdc` rule — that file must not exist for this trial; if it does, ignore it and stay on Auto.
|
|
38
|
+
|
|
39
|
+
The single sketch agent must still produce **at least two structurally distinct candidates** before synthesis (whole-shape alternatives, not point fixes). This keeps the exhaust-the-design-space pressure without multi-model spend. Screen every candidate against [`references/design-red-flags.md`](references/design-red-flags.md) before synthesis. Assume the next contributor is an agent that sees only the files it opened, copies the nearest example, and takes the shortest path that compiles. Prefer the design where a change that looks right from one file is right for the whole repo.
|
|
40
|
+
|
|
41
|
+
Compare viable candidates on interface depth. Prefer the design that hides more complexity behind a smaller, simpler public surface. A rich interface can keep call chains short by concentrating capability instead of scattering it across layers.
|
|
42
|
+
|
|
43
|
+
The sketch agent returns one synthesized design package. Its synthesis decision fills the rationale's "Synthesis decision" section.
|
|
44
|
+
|
|
45
|
+
## Phase C: Agree (opt-in for design; SE gates still bind)
|
|
46
|
+
|
|
47
|
+
Default for **ordinary** implement-from-sketch work: proceed to Phase D with the synthesized design without pausing for a design sign-off.
|
|
48
|
+
|
|
49
|
+
That default is **not** “never block on the human.” SE Studio approval gates still win:
|
|
50
|
+
|
|
51
|
+
- Do **not** merge, push `main`, publish Contentful, or promote production without the usual Nick / `## Merge approval` / ask+confirm / release-verification rules.
|
|
52
|
+
- For changes that need a **design review before build** (placement, schema, caching, analytics/forms — architecture R9.2 / Project design-review), surface the synthesized design, post or prepare `## Design review`, and **pause** until that gate is satisfied — even when the invoker did not say “with checkpoint.”
|
|
53
|
+
- Opt in to an extra checkpoint anytime the invoker asks: "/architect with checkpoint," "stop and show me before implementing," or similar. Then surface the synthesized design and pause for sign-off.
|
|
54
|
+
|
|
55
|
+
The synthesis can ship as its own commit either way (scaffold first), subject to the gates above. Planned and scoped breakage during fill-in is fine. For adversarial pressure on the design before implementing, run the **interrogate** skill on the synthesized sketch (Auto reviewers only; see interrogate skill).
|
|
56
|
+
|
|
57
|
+
If the human pushes back on the shape (in a checkpoint or after the fact), treat that as Phase A evidence. Re-ground and re-run Phase B before writing more code.
|
|
58
|
+
|
|
59
|
+
## Phase D: Implement against the sketch
|
|
60
|
+
|
|
61
|
+
Replace `not implemented` bodies with code, pseudocode with logic. The synthesized sketch is the contract. Deviations from it are signal to surface, not friction to absorb silently. If a function needs a parameter the sketch didn't anticipate, ask whether the sketch was wrong, the requirement was missed, or the implementation is overreaching.
|
|
62
|
+
|
|
63
|
+
## Phase E: Scrap when the architecture is wrong
|
|
64
|
+
|
|
65
|
+
If implementation keeps producing friction the sketch can't absorb, throw the sketch out. Don't bolt fixes onto a wrong design.
|
|
66
|
+
|
|
67
|
+
The signal is a *pattern*, not single instances. Tells:
|
|
68
|
+
|
|
69
|
+
- The same shape of workaround appearing repeatedly across unrelated code.
|
|
70
|
+
- Multiple unrelated edge cases that all need special-case branches.
|
|
71
|
+
- Types that need escape hatches (`any`, casts, optional fields always set in practice) to compile.
|
|
72
|
+
- The "we need a lock" reflex when the sketch said the state wasn't shared.
|
|
73
|
+
- Callers having to know the abstraction's internal rules to use it.
|
|
74
|
+
- Two or more independent Phase D deviations of the same shape across the implementation.
|
|
75
|
+
|
|
76
|
+
Use judgment. A few edge cases don't condemn an architecture. Some problems are legitimately complex. Complexity in the data is not complexity in the design.
|
|
77
|
+
|
|
78
|
+
When you scrap:
|
|
79
|
+
|
|
80
|
+
1. Re-run the **how** skill over what's been built.
|
|
81
|
+
2. Redesign as if the new constraints had been day-one assumptions.
|
|
82
|
+
3. Subtract before adding, per the **subtract-before-you-add** principle skill. The new sketch should be smaller than the old one before it grows.
|
|
83
|
+
4. Return to Phase B and re-run the **single-model** sketch path (still no arena).
|
|
84
|
+
|
|
85
|
+
## Outputs
|
|
86
|
+
|
|
87
|
+
The caller's usage is written first and the type sketch derived from it. One file with new types and signatures for small changes. Module map plus type definitions for larger work. The rationale ships alongside, shaped per `references/rationale-template.md`, including the usage sketch and the synthesis decision.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Design red flags
|
|
2
|
+
|
|
3
|
+
Screen every candidate before synthesis. A red flag is a reason to revise or reject the shape.
|
|
4
|
+
|
|
5
|
+
## Shallow module
|
|
6
|
+
|
|
7
|
+
A shallow module exposes a large interface while hiding little complexity. Judge depth by the capability and policy hidden behind the public surface relative to the size of that surface. Prefer a simple interface backed by substantial behavior.
|
|
8
|
+
|
|
9
|
+
Do not confuse a deep module with a deep call chain. A deep call chain scatters understanding across layers. A deep module concentrates capability behind one interface.
|
|
10
|
+
|
|
11
|
+
Look for these signs:
|
|
12
|
+
|
|
13
|
+
- Callers coordinate several methods to complete one operation.
|
|
14
|
+
- Public options expose internal stages or implementation choices.
|
|
15
|
+
- Learning the interface does not save the caller from learning the implementation.
|
|
16
|
+
|
|
17
|
+
## Information leakage
|
|
18
|
+
|
|
19
|
+
Information leakage makes multiple modules depend on the same internal decision. A representation, policy, or protocol detail appears in more than one place, so changing it requires coordinated edits.
|
|
20
|
+
|
|
21
|
+
Public re-exports of transport or wire types are leakage. Parse external data into domain types behind the interface. Keep storage schemas, framework objects, and protocol details private.
|
|
22
|
+
|
|
23
|
+
## Temporal decomposition
|
|
24
|
+
|
|
25
|
+
Temporal decomposition organizes modules by execution order instead of the knowledge they own. Separate load, validate, transform, and save stages often repeat one representation and its invariants across several boundaries.
|
|
26
|
+
|
|
27
|
+
Group code around domain knowledge and ownership. Methods that run at different times can still belong to one module when they protect the same decisions.
|
|
28
|
+
|
|
29
|
+
## Pass-through method
|
|
30
|
+
|
|
31
|
+
A pass-through method forwards the same arguments to another method with the same shape. It adds a layer without hiding complexity.
|
|
32
|
+
|
|
33
|
+
Remove it or move responsibility to the module that can complete the operation. Keep a forwarding boundary only when it adds policy, adaptation, or a distinct abstraction.
|
|
34
|
+
|
|
35
|
+
## Split ownership
|
|
36
|
+
|
|
37
|
+
More than one module writes the same state or keeps its own copy of it. An agent that edits one writer can't see the others, so their rules diverge.
|
|
38
|
+
|
|
39
|
+
Give each piece of state one owner. Other modules read it or ask the owner to change it.
|
|
40
|
+
|
|
41
|
+
## Two ways to do one task
|
|
42
|
+
|
|
43
|
+
The design supports more than one way to do the same task. An agent copies whichever way it finds first, so every way keeps gaining callers.
|
|
44
|
+
|
|
45
|
+
Keep one way. Move callers off the others and delete them in the same change.
|
|
46
|
+
|
|
47
|
+
## Importable internals
|
|
48
|
+
|
|
49
|
+
A caller can import a module's internals. An agent takes the shortest path that compiles, so it imports them directly and they become part of the interface.
|
|
50
|
+
|
|
51
|
+
Make internals unreachable from outside the module, so an import from outside fails the build.
|
|
52
|
+
|
|
53
|
+
## Hand-synced list
|
|
54
|
+
|
|
55
|
+
Two or more places list the same items, and adding an item means editing every list. An agent that sees one list updates only that one.
|
|
56
|
+
|
|
57
|
+
Keep one list and derive the others from it. If a list can't be derived, make the build fail when the lists disagree.
|