Skip to content

Commit 1162f2c

Browse files
jonathanpeterwuStackMemory Bot (CLI)
andauthored
docs(sop): ground PROSE Expectations in SOPs (#24)
Use Standard Operating Procedures (SOPs) as the contract base for the PROSE platform overview spec. - Update docs/specs/PROSE-platform-overview.md to explain that Expectations are derived from SOPs - Add SOP → PROSE → Tests workflow section - Add SOP basis column to the test-mapping table - Create docs/sops/ with 5 example SOPs (SOP-101 through SOP-202) - Update integration tests to reference their SOP basis Co-authored-by: StackMemory Bot (CLI) <bot@stackmemory.ai>
1 parent f23e97b commit 1162f2c

7 files changed

Lines changed: 214 additions & 26 deletions
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# SOP-101 Frame Lifecycle
2+
3+
**Owner:** Platform Team
4+
**Status:** Active
5+
**Related PROSE Expectation:** [E.1 Frame stack integrity](../specs/PROSE-platform-overview.md#e1-frame-stack-integrity)
6+
7+
## Objective
8+
Ensure context frames are created, activated, and closed in a deterministic, non-circular order so that only one frame is active at a time.
9+
10+
## Procedure
11+
12+
1. **Frame creation**
13+
- A frame is created with a unique name, type, and optional parent frame.
14+
- The newly created frame becomes the active frame.
15+
16+
2. **Frame activation**
17+
- Only the most recently pushed frame may be active.
18+
- Previous frames remain in the stack but are inactive.
19+
20+
3. **Frame closure**
21+
- Closing a frame removes it from the top of the stack.
22+
- The previous frame automatically becomes active.
23+
- No frame may reference itself as a parent, directly or transitively.
24+
25+
## Verification
26+
27+
- Run integration test: `active frame stack remains consistent`
28+
- Expected result: after pushing frames A → B → C and popping twice, only A remains active.
29+
30+
## Non-compliance
31+
32+
Orphaned active frames, circular parent references, or multiple simultaneous active frames are considered non-compliant and must fail validation.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# SOP-102 Decision Record Keeping
2+
3+
**Owner:** Platform Team
4+
**Status:** Active
5+
**Related PROSE Expectation:** [E.2 Decision immutability](../specs/PROSE-platform-overview.md#e2-decision-immutability)
6+
7+
## Objective
8+
Preserve decisions as tamper-evident audit records so that historical rationale remains trustworthy across sessions.
9+
10+
## Procedure
11+
12+
1. **Recording a decision**
13+
- Capture title, rationale, timestamp, and author context.
14+
- Assign a stable identifier at creation time.
15+
16+
2. **Storage**
17+
- Store the decision in the project-local SQLite database.
18+
- Do not overwrite existing decision records.
19+
20+
3. **Retrieval**
21+
- Decisions must be retrievable by identifier, title, or full-text search.
22+
23+
## Verification
24+
25+
- Run integration test: `recorded decisions are immutable`
26+
- Expected result: re-adding a decision with the same title creates a new record; the original rationale remains unchanged.
27+
28+
## Non-compliance
29+
30+
Mutating an existing decision's title, rationale, or identifier is non-compliant.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# SOP-103 Project Boundary Enforcement
2+
3+
**Owner:** Platform Team
4+
**Status:** Active
5+
**Related PROSE Expectation:** [E.3 Project isolation](../specs/PROSE-platform-overview.md#e3-project-isolation)
6+
7+
## Objective
8+
Prevent context leakage between projects so that each project directory owns an independent memory store.
9+
10+
## Procedure
11+
12+
1. **Project initialization**
13+
- Create a `.stackmemory/` directory inside the target project directory.
14+
- Store all project-specific data within that directory.
15+
16+
2. **Operation scoping**
17+
- Resolve the active project by the current working directory.
18+
- Do not search parent directories for sibling project stores.
19+
20+
3. **Cross-project sync**
21+
- Context may only be shared between projects through explicit, user-initiated sync commands.
22+
23+
## Verification
24+
25+
- Run integration test: `projects in different directories are isolated`
26+
- Expected result: a decision recorded in project A is not visible in project B.
27+
28+
## Non-compliance
29+
30+
Reading or writing another project's data without explicit sync is non-compliant.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# SOP-201 CLI Exit-Code Compliance
2+
3+
**Owner:** CLI Team
4+
**Status:** Active
5+
**Related PROSE Expectation:** [E.4 CLI contract](../specs/PROSE-platform-overview.md#e4-cli-contract)
6+
7+
## Objective
8+
Provide deterministic exit codes so that scripts, CI pipelines, and automation tools can rely on CLI outcomes.
9+
10+
## Procedure
11+
12+
1. **Success**
13+
- Return exit code `0` when a command completes its intended function.
14+
15+
2. **Failure**
16+
- Return a non-zero exit code when a command cannot complete its intended function.
17+
- Include a human-readable error message on stderr or stdout.
18+
19+
3. **Documentation**
20+
- Document exit-code behavior for commands used in automation.
21+
22+
## Verification
23+
24+
- Run integration test: `CLI commands return correct exit codes`
25+
- Expected result: successful commands exit `0`; invalid commands exit non-zero.
26+
27+
## Non-compliance
28+
29+
Returning `0` on failure or a non-zero code on success is non-compliant.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# SOP-202 Data Portability
2+
3+
**Owner:** Platform Team
4+
**Status:** Active
5+
**Related PROSE Expectation:** [E.5 SQLite contract](../specs/PROSE-platform-overview.md#e5-sqlite-contract)
6+
7+
## Objective
8+
Ensure the project memory store is self-contained and portable across machines without external dependencies.
9+
10+
## Procedure
11+
12+
1. **Self-contained storage**
13+
- Keep the primary database file inside `.stackmemory/`.
14+
- Avoid reliance on remote databases for core context storage.
15+
16+
2. **Schema compatibility**
17+
- Maintain forward-compatible schemas within major CLI versions.
18+
- Document migration steps when schema changes are required.
19+
20+
3. **Backup and restore**
21+
- A user must be able to copy `.stackmemory/` to another machine and resume work with the same CLI version.
22+
23+
## Verification
24+
25+
- Run integration test: `SQLite database is self-contained in .stackmemory`
26+
- Expected result: after initialization and recording context, a `.db` or `.sqlite` file exists under `.stackmemory/`.
27+
28+
## Non-compliance
29+
30+
Requiring external services for basic context retrieval or scattering state outside `.stackmemory/` is non-compliant.

docs/specs/PROSE-platform-overview.md

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
# PROSE Platform Overview
22

33
> PROSE = **P**urpose, **R**ules & Constraints, **O**bservables, **S**cenarios, **E**xpectations
4+
>
5+
> Expectations are grounded in **SOPs** — Standard Operating Procedures that define repeatable business outcomes and standardized outputs.
46
57
This document describes StackMemory's platform behavior in plain English. Each section is intentionally testable and maps directly to integration tests in `src/__tests__/integration/platform-overview.test.ts`.
68

9+
The contract layer of PROSE is derived from SOPs: every Expectation below corresponds to a procedural guarantee that QA can validate and that can be turned into executable scripts.
10+
711
---
812

913
## P — Purpose
@@ -71,44 +75,73 @@ Capturing a snapshot persists the current context state for later handoff.
7175

7276
## E — Expectations
7377

74-
Properties that must always hold true and guarantees the platform makes to users and integrations.
78+
Properties that must always hold true and guarantees the platform makes to users and integrations. Each Expectation is backed by one or more SOPs so that business outcomes can be standardized, QA'd, and automated.
7579

7680
### E.1 Frame stack integrity
7781
At any time, there is at most one active frame, and the frame stack is non-circular.
7882

83+
**SOP basis:** `SOP-101 Frame Lifecycle` — frames must be pushed and popped in a deterministic order; no orphaned active frames are allowed.
84+
7985
### E.2 Decision immutability
8086
Once recorded, a decision's identifier, title, and rationale must not change.
8187

88+
**SOP basis:** `SOP-102 Decision Record Keeping` — decisions are audit records and must remain tamper-evident.
89+
8290
### E.3 Project isolation
8391
Two projects initialized in different directories must not share context unless explicitly synced.
8492

93+
**SOP basis:** `SOP-103 Project Boundary Enforcement` — each project directory owns its SQLite database and must not leak state into neighboring projects.
94+
8595
### E.4 CLI contract
8696
All CLI commands return a zero exit code on success and a non-zero exit code on failure, with human-readable output.
8797

98+
**SOP basis:** `SOP-201 CLI Exit-Code Compliance` — scripts and CI pipelines depend on reliable exit codes.
99+
88100
### E.5 SQLite contract
89101
The local SQLite database is self-contained within `.stackmemory/` and portable across machines with the same CLI version.
90102

103+
**SOP basis:** `SOP-202 Data Portability` — the database must be relocatable and restorable without external services.
104+
105+
---
106+
107+
## SOP → PROSE → Tests workflow
108+
109+
```
110+
SOP (business outcome)
111+
112+
113+
PROSE Expectation (plain-English contract)
114+
115+
116+
Integration test (executable validation)
117+
118+
119+
Feature-script parity (automation)
120+
```
121+
122+
For example, `SOP-101 Frame Lifecycle` becomes PROSE `E.1`, which becomes the test `active frame stack remains consistent`. QA can run the same test suite to verify SOP compliance, and the test can be used to generate or validate automation scripts.
123+
91124
---
92125

93126
## Test mapping
94127

95-
| PROSE ID | Test case |
96-
|----------|-----------|
97-
| P.1 | `initializes a project with stackmemory init` |
98-
| P.2 | `retrieves decisions across sessions` |
99-
| R.1 | `fails gracefully outside an initialized project` |
100-
| R.2 | `returns empty results for non-matching search` |
101-
| R.3 | `init is idempotent` |
102-
| O.1 | `reports status for initialized and uninitialized projects` |
103-
| O.2 | `lists pushed frames` |
104-
| O.3 | `lists recorded decisions` |
105-
| O.4 | `searches stored context` |
106-
| S.1 | `pushing a frame creates a scoped entry` |
107-
| S.2 | `popping a frame restores the previous frame` |
108-
| S.3 | `recording a decision persists rationale` |
109-
| S.4 | `capturing a snapshot persists handoff state` |
110-
| E.1 | `active frame stack remains consistent` |
111-
| E.2 | `recorded decisions are immutable` |
112-
| E.3 | `projects in different directories are isolated` |
113-
| E.4 | `CLI commands return correct exit codes` |
114-
| E.5 | `SQLite database is self-contained in .stackmemory` |
128+
| PROSE ID | SOP basis | Test case |
129+
|----------|-----------|-----------|
130+
| P.1 | | `initializes a project with stackmemory init` |
131+
| P.2 | | `retrieves decisions across sessions` |
132+
| R.1 | | `fails gracefully outside an initialized project` |
133+
| R.2 | | `returns empty results for non-matching search` |
134+
| R.3 | | `init is idempotent` |
135+
| O.1 | | `reports status for initialized and uninitialized projects` |
136+
| O.2 | | `lists pushed frames` |
137+
| O.3 | | `lists recorded decisions` |
138+
| O.4 | | `searches stored context` |
139+
| S.1 | | `pushing a frame creates a scoped entry` |
140+
| S.2 | | `popping a frame restores the previous frame` |
141+
| S.3 | | `recording a decision persists rationale` |
142+
| S.4 | | `capturing a snapshot persists handoff state` |
143+
| E.1 | `SOP-101 Frame Lifecycle` | `active frame stack remains consistent` |
144+
| E.2 | `SOP-102 Decision Record Keeping` | `recorded decisions are immutable` |
145+
| E.3 | `SOP-103 Project Boundary Enforcement` | `projects in different directories are isolated` |
146+
| E.4 | `SOP-201 CLI Exit-Code Compliance` | `CLI commands return correct exit codes` |
147+
| E.5 | `SOP-202 Data Portability` | `SQLite database is self-contained in .stackmemory` |

src/__tests__/integration/platform-overview.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,13 @@ describe('PROSE Platform Overview', { timeout: 60_000 }, () => {
263263

264264
// ---------------------------------------------------------------------------
265265
// E — Expectations
266+
//
267+
// Each Expectation is grounded in an SOP (Standard Operating Procedure) so
268+
// that business outcomes can be standardized, QA'd, and automated.
269+
// SOP source: docs/sops/
266270
// ---------------------------------------------------------------------------
267271

268-
describe('E.1 Frame stack integrity', () => {
272+
describe('E.1 Frame stack integrity (SOP-101)', () => {
269273
it('active frame stack remains consistent', () => {
270274
run('init', testDir);
271275
run('context push "Alpha frame"', testDir);
@@ -282,7 +286,7 @@ describe('PROSE Platform Overview', { timeout: 60_000 }, () => {
282286
});
283287
});
284288

285-
describe('E.2 Decision immutability', () => {
289+
describe('E.2 Decision immutability (SOP-102)', () => {
286290
it('recorded decisions are immutable', () => {
287291
run('init', testDir);
288292
run(
@@ -304,7 +308,7 @@ describe('PROSE Platform Overview', { timeout: 60_000 }, () => {
304308
});
305309
});
306310

307-
describe('E.3 Project isolation', () => {
311+
describe('E.3 Project isolation (SOP-103)', () => {
308312
it('projects in different directories are isolated', () => {
309313
const projectA = path.join(testDir, 'project-a');
310314
const projectB = path.join(testDir, 'project-b');
@@ -322,7 +326,7 @@ describe('PROSE Platform Overview', { timeout: 60_000 }, () => {
322326
});
323327
});
324328

325-
describe('E.4 CLI contract', () => {
329+
describe('E.4 CLI contract (SOP-201)', () => {
326330
it('CLI commands return correct exit codes', () => {
327331
expect(() => run('init', testDir)).not.toThrow();
328332
expect(() => run('decision list', testDir)).not.toThrow();
@@ -332,7 +336,7 @@ describe('PROSE Platform Overview', { timeout: 60_000 }, () => {
332336
});
333337
});
334338

335-
describe('E.5 SQLite contract', () => {
339+
describe('E.5 SQLite contract (SOP-202)', () => {
336340
it('SQLite database is self-contained in .stackmemory', () => {
337341
run('init', testDir);
338342
run('decision add "DB test" --why "Check local DB"', testDir);

0 commit comments

Comments
 (0)