@reunionstudio/airlock-mcp 0.1.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/.agents/skills/airlock-mcp/SKILL.md +122 -0
- package/.agents/skills/airlock-mcp/agents/openai.yaml +4 -0
- package/LICENSE +187 -0
- package/README.md +126 -0
- package/SECURITY.md +31 -0
- package/bin/airlock-mcp.mjs +5 -0
- package/docs/architecture.md +82 -0
- package/docs/install-surface.md +112 -0
- package/docs/ooda-loop.md +40 -0
- package/docs/spec-workbench-architecture.md +161 -0
- package/docs/spec-workspace.md +33 -0
- package/docs/workflows.md +229 -0
- package/package.json +46 -0
- package/patterns/blank/README.md +14 -0
- package/patterns/blank/sample.records.json +19 -0
- package/patterns/blank/spec.config.json +72 -0
- package/patterns/guest-access/individual-isolation.md +27 -0
- package/patterns/guest-access/role-isolation.md +26 -0
- package/patterns/guest-access/shared-contribution.md +25 -0
- package/patterns/manifest.json +16 -0
- package/patterns/spec-types/commitment.md +24 -0
- package/patterns/spec-types/observation.md +22 -0
- package/patterns/spec-types/reconciliation.md +19 -0
- package/patterns/spec-types/reference-master-data.md +21 -0
- package/patterns/starter-posts/README.md +32 -0
- package/patterns/starter-posts/sample.records.json +27 -0
- package/patterns/starter-posts/spec.config.json +135 -0
- package/schemas/airlock-mcp-workspace.schema.json +14 -0
- package/setup.py +41 -0
- package/src/airlock_mcp/__init__.py +3 -0
- package/src/airlock_mcp/__main__.py +5 -0
- package/src/airlock_mcp/art.py +26 -0
- package/src/airlock_mcp/bootstrap.py +161 -0
- package/src/airlock_mcp/cli.py +450 -0
- package/src/airlock_mcp/jsonio.py +56 -0
- package/src/airlock_mcp/manage.py +247 -0
- package/src/airlock_mcp/models.py +43 -0
- package/src/airlock_mcp/patterns.py +49 -0
- package/src/airlock_mcp/project.py +39 -0
- package/src/airlock_mcp/records.py +43 -0
- package/src/airlock_mcp/specs.py +110 -0
- package/src/airlock_mcp/sql.py +15 -0
- package/src/airlock_mcp/summary.py +115 -0
- package/src/airlock_mcp/updater.py +76 -0
- package/src/airlock_mcp/validation.py +334 -0
- package/src/airlock_mcp/workspace.py +223 -0
- package/src/cli.mjs +89 -0
- package/src/install.mjs +100 -0
- package/src/mcp.mjs +184 -0
- package/src/text.mjs +108 -0
- package/src/workbench.mjs +368 -0
- package/workspaces/_template/brief.md +18 -0
- package/workspaces/_template/decisions.md +40 -0
- package/workspaces/_template/questions.md +9 -0
- package/workspaces/_template/review.md +21 -0
- package/workspaces/_template/sample.records.json +19 -0
- package/workspaces/_template/spec.config.json +72 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# OODA Loop For Airlock Specs
|
|
2
|
+
|
|
3
|
+
Airlock specs should support a business loop, not just a table.
|
|
4
|
+
|
|
5
|
+
## Observe
|
|
6
|
+
|
|
7
|
+
Name the evidence and systems that matter:
|
|
8
|
+
|
|
9
|
+
- human entries
|
|
10
|
+
- agent observations
|
|
11
|
+
- screenshots, PDFs, receipts, exports, or source files
|
|
12
|
+
- source APIs or app objects
|
|
13
|
+
- existing Airlock specs or reference data
|
|
14
|
+
- downstream system state
|
|
15
|
+
|
|
16
|
+
## Orient
|
|
17
|
+
|
|
18
|
+
Turn observations into a governed shape:
|
|
19
|
+
|
|
20
|
+
- one row grain
|
|
21
|
+
- durable identifiers
|
|
22
|
+
- business timestamps
|
|
23
|
+
- typed fields
|
|
24
|
+
- validated variants
|
|
25
|
+
- attachments
|
|
26
|
+
- guest access
|
|
27
|
+
- workflow
|
|
28
|
+
- references
|
|
29
|
+
- expectations
|
|
30
|
+
|
|
31
|
+
## Decide
|
|
32
|
+
|
|
33
|
+
Choose the smallest governed output worth creating now. If uncertainty is high,
|
|
34
|
+
start with `posts` and let real feedback shape the next spec.
|
|
35
|
+
|
|
36
|
+
## Act
|
|
37
|
+
|
|
38
|
+
Create the spec in Airlock only after local drafting is coherent. Then collect
|
|
39
|
+
records, review them, and decide whether to revise the spec or add the next
|
|
40
|
+
small spec.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Airlock MCP is intentionally small:
|
|
4
|
+
|
|
5
|
+
- Codex is the conversational interface.
|
|
6
|
+
- The repo is the durable workspace.
|
|
7
|
+
- The CLI is deterministic local tooling.
|
|
8
|
+
- Airlock stored procedures remain the authority for live validation and
|
|
9
|
+
mutation.
|
|
10
|
+
|
|
11
|
+
## Module Boundaries
|
|
12
|
+
|
|
13
|
+
- `cli.py`: argument parsing and command dispatch only.
|
|
14
|
+
- `art.py`: small terminal identity and about text.
|
|
15
|
+
- `bootstrap.py`: specs-repo bootstrap files, including `AGENTS.md` and the
|
|
16
|
+
repo-scoped Codex skill.
|
|
17
|
+
- `manage.py`: workspace discovery, archive, restore, rename, and next-action
|
|
18
|
+
helpers.
|
|
19
|
+
- `project.py`: checkout discovery and environment override handling.
|
|
20
|
+
- `patterns.py`: pattern manifest loading.
|
|
21
|
+
- `workspace.py`: create, import, and clone workspace file operations.
|
|
22
|
+
- `specs.py`: spec-config extraction, identity retitling, and sample-record
|
|
23
|
+
generation.
|
|
24
|
+
- `records.py`: deterministic records JSON to CSV rendering.
|
|
25
|
+
- `summary.py`: compact workspace recap for session re-entry.
|
|
26
|
+
- `updater.py`: self-update planning and execution.
|
|
27
|
+
- `validation.py`: local workspace and records checks.
|
|
28
|
+
- `sql.py`: validate-only SQL rendering.
|
|
29
|
+
- `jsonio.py`: JSON/text file helpers.
|
|
30
|
+
|
|
31
|
+
Keep product data in `patterns/`, workspace templates in `workspaces/_template/`,
|
|
32
|
+
and Airlock-specific validation rules in `validation.py`. Do not put another
|
|
33
|
+
copy of a pattern into Python code.
|
|
34
|
+
|
|
35
|
+
## Source-Of-Truth Rules
|
|
36
|
+
|
|
37
|
+
`patterns/manifest.json` lists CLI-visible starter patterns. Each listed
|
|
38
|
+
pattern directory must include:
|
|
39
|
+
|
|
40
|
+
- `README.md`
|
|
41
|
+
- `spec.config.json`
|
|
42
|
+
- `sample.records.json`
|
|
43
|
+
|
|
44
|
+
The CLI reads those files directly. That makes pattern edits reviewable as data
|
|
45
|
+
changes instead of code changes.
|
|
46
|
+
|
|
47
|
+
## Create, Import, Clone
|
|
48
|
+
|
|
49
|
+
The old Airlock Streamlit editor used mode-specific hydration:
|
|
50
|
+
|
|
51
|
+
- create: start from defaults
|
|
52
|
+
- edit: hydrate canonical config and preserve unmodeled sections
|
|
53
|
+
- clone: hydrate source config, but blank/reset identity fields
|
|
54
|
+
|
|
55
|
+
Airlock MCP maps that to files:
|
|
56
|
+
|
|
57
|
+
- `init-repo`: prepare a separate specs repo for Codex and Airlock MCP
|
|
58
|
+
- `init`: create from a pattern
|
|
59
|
+
- `import-spec`: edit/import an existing canonical or spec-library config in a
|
|
60
|
+
new workspace
|
|
61
|
+
- `clone`: copy a workspace, reset `core_config.spec_name` and
|
|
62
|
+
`core_config.spec_alias`, and regenerate sample records
|
|
63
|
+
- `rename`: move a workspace and, by default, retitle its spec identity
|
|
64
|
+
- `archive` and `restore`: move drafts in and out of `_archive`
|
|
65
|
+
- `list-workspaces`: show active drafts, with archived drafts available via
|
|
66
|
+
`--all`
|
|
67
|
+
|
|
68
|
+
This repo does not try to be the installed Airlock editor. It gives Codex and
|
|
69
|
+
humans a careful drafting surface before Airlock receives the final config.
|
|
70
|
+
|
|
71
|
+
## Update Boundary
|
|
72
|
+
|
|
73
|
+
`self-update` supports two intentionally simple paths:
|
|
74
|
+
|
|
75
|
+
- checkout mode: `git pull --ff-only`
|
|
76
|
+
- installed package mode: `pip install --upgrade <source>`
|
|
77
|
+
|
|
78
|
+
The command prints the selected plan first, supports `--dry-run`, and refuses a
|
|
79
|
+
git checkout with uncommitted changes unless `--force` is passed. Keep update
|
|
80
|
+
logic in `updater.py`; do not hide network or package-manager side effects in
|
|
81
|
+
other commands.
|
|
82
|
+
|
|
83
|
+
## Validation Boundary
|
|
84
|
+
|
|
85
|
+
Local checks catch:
|
|
86
|
+
|
|
87
|
+
- missing workspace files
|
|
88
|
+
- invalid JSON
|
|
89
|
+
- missing core fields
|
|
90
|
+
- duplicate columns
|
|
91
|
+
- unsupported column types
|
|
92
|
+
- missing date/datetime strftime formats
|
|
93
|
+
- `variant_shape` rules pointing at non-variant columns
|
|
94
|
+
- variant columns with no `variant_shape` rule
|
|
95
|
+
- shared guest-role access levels without matching enabled public subfolders
|
|
96
|
+
- sample records with undeclared or missing required fields
|
|
97
|
+
- payload fields that look like Airlock workflow/reviewer state
|
|
98
|
+
|
|
99
|
+
Local checks do not prove that installed Airlock will accept a spec. Always use
|
|
100
|
+
installed Airlock validation before mutation.
|
|
101
|
+
|
|
102
|
+
## Records Boundary
|
|
103
|
+
|
|
104
|
+
`sample.records.json` is the authoring shape. It supports nested JSON for
|
|
105
|
+
variant fields and is easy for Codex to patch over multiple sessions.
|
|
106
|
+
|
|
107
|
+
`export-csv` is the handoff adapter. It writes fields in `column_config` order,
|
|
108
|
+
ignores undeclared extras after validation has reported them, and serializes
|
|
109
|
+
objects or arrays as compact JSON strings. Keep other record-format adapters in
|
|
110
|
+
`records.py` so the CLI stays thin.
|
|
111
|
+
|
|
112
|
+
## Install Boundary
|
|
113
|
+
|
|
114
|
+
The public install surface is expected to be Airlock MCP shaped:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx @reunionstudio/airlock-mcp install
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The connector implementation belongs in `reunionstudio/airlock-mcp`. Airlock
|
|
121
|
+
MCP is the single installed interface for agents working with Airlock: building
|
|
122
|
+
specs, using specs to pull and push governed data, and capturing improvements
|
|
123
|
+
from real use cases. This workbench owns the spec-building implementation:
|
|
124
|
+
patterns, bootstrap, workspace files, local checks, and the Codex skill.
|
|
125
|
+
|
|
126
|
+
That command is the agent connector/setup entry point, not the user's spec
|
|
127
|
+
workspace. After installing or registering the connector, the user still creates
|
|
128
|
+
a separate `<project>-specs` repo and works there with Codex. Users should ask
|
|
129
|
+
for Airlock, not install a separate spec-building tool.
|
|
130
|
+
|
|
131
|
+
For Codex, the install command should use the platform MCP manager rather than
|
|
132
|
+
editing config files directly:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
codex mcp add airlock -- npx -y @reunionstudio/airlock-mcp server
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The npm package is an installer and launcher. The production MCP server can be
|
|
139
|
+
Rust when Airlock MCP grows beyond bootstrap guidance. If implemented with
|
|
140
|
+
stdio, stdout must remain protocol-only and all logging must go to stderr.
|
|
141
|
+
|
|
142
|
+
The current dogfood/development path can install Airlock MCP into the specs
|
|
143
|
+
repo before the MCP package is published, then run:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
airlock-mcp init-repo
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
That command writes the Codex-facing repo instructions and skill into the specs
|
|
150
|
+
repo. Keep those bootstrap assets as files, not generated prose hidden in the
|
|
151
|
+
CLI, so product guidance remains reviewable.
|
|
152
|
+
|
|
153
|
+
The normal development path for Airlock MCP itself is from a checkout:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
python3 -m pip install -e .
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The CLI discovers the checkout by walking upward for `patterns/manifest.json`.
|
|
160
|
+
Set `AIRLOCK_MCP_HOME=/path/to/airlock-mcp` if the command is launched from
|
|
161
|
+
another working directory.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Spec Workspace Files
|
|
2
|
+
|
|
3
|
+
Every draft workspace should preserve context for future Codex sessions.
|
|
4
|
+
|
|
5
|
+
- `brief.md`: business goal, users, systems, and first useful outcome.
|
|
6
|
+
- `decisions.md`: row grain, evidence, access, workflow, references, and OODA
|
|
7
|
+
decisions.
|
|
8
|
+
- `questions.md`: unresolved questions that materially affect the model.
|
|
9
|
+
- `spec.config.json`: draft full Airlock admin spec config.
|
|
10
|
+
- `sample.records.json`: example records in agent-friendly records JSON.
|
|
11
|
+
- `review.md`: local review notes, Airlock validation results, and next steps.
|
|
12
|
+
|
|
13
|
+
The workspace is intentionally plain files. Diffs are the design history.
|
|
14
|
+
|
|
15
|
+
Use `airlock-mcp summary <workspace>` to re-enter a draft. Use
|
|
16
|
+
`airlock-mcp next <workspace>` to choose the next conservative action. Use
|
|
17
|
+
`airlock-mcp export-csv <workspace>` to render `sample.records.json` in the
|
|
18
|
+
CSV shape Airlock loading paths commonly expect. Do not treat the CSV as the
|
|
19
|
+
source of truth; edit the JSON and regenerate it.
|
|
20
|
+
|
|
21
|
+
Use `airlock-mcp rename`, `archive`, and `restore` to organize draft folders.
|
|
22
|
+
`rename` retitles spec identity by default; pass `--keep-spec-identity` for a
|
|
23
|
+
pure folder move.
|
|
24
|
+
|
|
25
|
+
`review.md` should identify the workspace source mode:
|
|
26
|
+
|
|
27
|
+
- `create`: started from an Airlock MCP pattern
|
|
28
|
+
- `import`: hydrated from an existing spec JSON shape such as `specConfig` or
|
|
29
|
+
exported `SPEC_CONFIG`
|
|
30
|
+
- `clone`: copied from another workspace with spec identity reset
|
|
31
|
+
|
|
32
|
+
For clone and import flows, preserve the source path/name so future sessions can
|
|
33
|
+
tell whether changes are deliberate adaptations or accidental drift.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Workflows
|
|
2
|
+
|
|
3
|
+
## Start A New Specs Repo
|
|
4
|
+
|
|
5
|
+
Use this when a person opens a blank Codex project and wants to start working
|
|
6
|
+
with real Airlock specs. The project repo is where they work. Public users
|
|
7
|
+
should come through the single Airlock MCP install; this repo provides the
|
|
8
|
+
spec-building capability behind that experience.
|
|
9
|
+
|
|
10
|
+
Ask for the project or organization name first, then lowercase it, replace
|
|
11
|
+
spaces with hyphens, and append `-specs`. For example, `Home` becomes
|
|
12
|
+
`home-specs`. Reserve `airlock-specs` for the canonical reusable spec library.
|
|
13
|
+
Airlock itself does not create this repo; Codex can create it locally while
|
|
14
|
+
helping the user start an Airlock specs project.
|
|
15
|
+
Start in Codex, not Snowflake Cortex. Snow CLI or Cortex only matters later when
|
|
16
|
+
validating, creating, or operating specs against an installed Airlock app.
|
|
17
|
+
|
|
18
|
+
The preferred Codex prompt is:
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
I want to use Airlock MCP to start working with Airlock specs for Home.
|
|
22
|
+
|
|
23
|
+
Set up this project as an Airlock specs repo. Use the Airlock MCP
|
|
24
|
+
spec-building capability when we need to draft or revise specs. Welcome me,
|
|
25
|
+
help me think through real Airlock use cases, and ask only for the missing
|
|
26
|
+
decisions. Do not create the first workspace until I choose a path.
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
When dogfooding this implementation repo before the MCP package is published,
|
|
30
|
+
Codex can install the spec-building workbench from GitHub:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git init
|
|
34
|
+
python3 -m venv .venv
|
|
35
|
+
source .venv/bin/activate
|
|
36
|
+
python3 -m pip install git+https://github.com/reunionstudio/airlock-mcp.git
|
|
37
|
+
airlock-mcp init-repo
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This does not require a PyPI release. `pip` installs the package directly from
|
|
41
|
+
GitHub. It is a dogfood/developer path, not the public primary install.
|
|
42
|
+
|
|
43
|
+
The target public install shape should be:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx @reunionstudio/airlock-mcp install
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The connector implementation lives in `reunionstudio/airlock-mcp`; this
|
|
50
|
+
workbench keeps the Airlock MCP spec-building capability.
|
|
51
|
+
|
|
52
|
+
That should install or register the Airlock MCP connector for the user's agent
|
|
53
|
+
environment. After that, the user still creates a blank `<slug>-specs` project
|
|
54
|
+
and starts chatting there. Airlock MCP covers building specs, using specs to
|
|
55
|
+
pull and push governed data, and improving specs from real use cases.
|
|
56
|
+
|
|
57
|
+
For Codex, the install command should register the server with:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
codex mcp add airlock -- npx -y @reunionstudio/airlock-mcp server
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The MCP-style flow should be:
|
|
64
|
+
|
|
65
|
+
1. Run `npx @reunionstudio/airlock-mcp install` once for the agent environment.
|
|
66
|
+
2. Open Codex.
|
|
67
|
+
3. Create a new blank project named for the org or project, such as
|
|
68
|
+
`home-specs`.
|
|
69
|
+
4. Tell Codex: `Use Airlock to help me build and use specs.`
|
|
70
|
+
5. Airlock MCP welcomes, offers OODA brainstorming, a known-process draft, a
|
|
71
|
+
`posts` feedback loop, or installed-Airlock validation/use.
|
|
72
|
+
|
|
73
|
+
`init-repo` creates `AGENTS.md`, `.agents/skills/airlock-mcp/SKILL.md`, and
|
|
74
|
+
`workspaces/`. That is what lets Codex understand prompts such as
|
|
75
|
+
`Use $airlock-mcp` inside the specs repo.
|
|
76
|
+
|
|
77
|
+
After bootstrap, offer three paths before creating a workspace:
|
|
78
|
+
|
|
79
|
+
- brainstorm possible specs using the OODA loop
|
|
80
|
+
- start from a known process and create a blank workspace
|
|
81
|
+
- create a `posts` feedback loop for humans and agents to submit requests,
|
|
82
|
+
observations, and responses
|
|
83
|
+
|
|
84
|
+
## Start From Feedback
|
|
85
|
+
|
|
86
|
+
Use this when the user chooses a shared feedback loop for humans and agents.
|
|
87
|
+
If they are not sure what to model yet, offer OODA brainstorming before creating
|
|
88
|
+
this workspace.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
airlock-mcp init feedback-loop --pattern posts
|
|
92
|
+
airlock-mcp check workspaces/feedback-loop
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Then ask Codex to help decide what the posts should observe, who responds, and
|
|
96
|
+
what next spec should grow from the feedback.
|
|
97
|
+
|
|
98
|
+
## Start From A Known Process
|
|
99
|
+
|
|
100
|
+
Use this when the process is known but the data shape is not.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
airlock-mcp init weekly-timesheets --pattern blank
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Replace the draft columns once row grain, event timestamps, typed fields,
|
|
107
|
+
evidence, access, and workflow are clear.
|
|
108
|
+
|
|
109
|
+
## Import An Existing Spec
|
|
110
|
+
|
|
111
|
+
Use this for an Airlock spec-library file, exported `SPEC_CONFIG`, or a canonical
|
|
112
|
+
config from another repo.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
airlock-mcp import-spec ../airlock-specs/specs/internal/posts.json imported-posts
|
|
116
|
+
airlock-mcp check workspaces/imported-posts
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Supported input shapes:
|
|
120
|
+
|
|
121
|
+
- `{"specConfig": {...}}`
|
|
122
|
+
- `{"spec_config": {...}}`
|
|
123
|
+
- `{"SPEC_CONFIG": "{...}"}`
|
|
124
|
+
- a raw canonical object with `core_config` or `column_config`
|
|
125
|
+
- a legacy `{"specs": [{"config": ...}]}`
|
|
126
|
+
|
|
127
|
+
## Clone A Workspace
|
|
128
|
+
|
|
129
|
+
Use this when a related spec should preserve most design choices but needs a new
|
|
130
|
+
identity.
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
airlock-mcp clone workspaces/imported-posts team-posts
|
|
134
|
+
airlock-mcp check workspaces/team-posts
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Clone resets `core_config.spec_name`, `core_config.spec_alias`, and sample
|
|
138
|
+
records. It keeps the surrounding brief and decisions so Codex can adapt them.
|
|
139
|
+
|
|
140
|
+
## Organize Workspaces
|
|
141
|
+
|
|
142
|
+
Use this when a workbench has more than one draft in motion.
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
airlock-mcp list-workspaces
|
|
146
|
+
airlock-mcp list-workspaces --all
|
|
147
|
+
airlock-mcp rename workspaces/weekly-timesheets weekly-time-entries
|
|
148
|
+
airlock-mcp archive workspaces/old-draft
|
|
149
|
+
airlock-mcp restore workspaces/_archive/old-draft
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`rename` retitles `core_config.spec_name`, `core_config.spec_alias`, and sample
|
|
153
|
+
record spec names by default so the folder and spec identity stay together. Use
|
|
154
|
+
`--keep-spec-identity` when the move is purely organizational.
|
|
155
|
+
|
|
156
|
+
`archive` moves a workspace under `_archive`. `list-workspaces` hides internal
|
|
157
|
+
underscore directories by default and shows archived drafts with `--all`.
|
|
158
|
+
|
|
159
|
+
## Resume A Session
|
|
160
|
+
|
|
161
|
+
Use this at the start of a later Codex session before changing JSON.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
airlock-mcp summary workspaces/team-posts
|
|
165
|
+
airlock-mcp next workspaces/team-posts
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The summary shows the current spec identity, required fields, variant fields,
|
|
169
|
+
attachment posture, guest access model, sample record count, note-file status,
|
|
170
|
+
and local check counts.
|
|
171
|
+
|
|
172
|
+
`next` prints the same recap plus a conservative next action: fix local errors,
|
|
173
|
+
review warnings, fill open design prompts in `decisions.md`, add sample records,
|
|
174
|
+
or prepare export and validate-only SQL. Inline answers such as
|
|
175
|
+
`One row is: a submitted receipt` count as filled.
|
|
176
|
+
|
|
177
|
+
## Export Sample Records
|
|
178
|
+
|
|
179
|
+
Use this when the JSON examples should be reviewed or loaded through an
|
|
180
|
+
Airlock CSV-oriented path.
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
airlock-mcp export-csv workspaces/team-posts
|
|
184
|
+
airlock-mcp export-csv workspaces/team-posts --output /tmp/team-posts.csv
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
`sample.records.json` remains the authoring shape because it is easier for
|
|
188
|
+
Codex and humans to edit. `export-csv` writes columns in `column_config` order
|
|
189
|
+
and serializes `variant` values as compact JSON strings.
|
|
190
|
+
|
|
191
|
+
## Render Validate-Only SQL
|
|
192
|
+
|
|
193
|
+
Use this as a handoff artifact for an admin or agent with Snowflake access.
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
airlock-mcp render-sql workspaces/team-posts
|
|
197
|
+
airlock-mcp render-sql workspaces/team-posts --operation alter
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The rendered SQL uses `validate_only => TRUE` positionally. Review installed
|
|
201
|
+
Airlock documentation before changing it to a mutating call.
|
|
202
|
+
|
|
203
|
+
## Update The Workbench
|
|
204
|
+
|
|
205
|
+
Use dry-run first so the command is visible before anything changes.
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
airlock-mcp self-update --dry-run
|
|
209
|
+
airlock-mcp self-update
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
From a checkout, `self-update` uses `git pull --ff-only` and refuses to run with
|
|
213
|
+
uncommitted changes unless `--force` is passed. From an installed package, it
|
|
214
|
+
uses `pip install --upgrade` with the configured source.
|
|
215
|
+
|
|
216
|
+
## Session Rhythm
|
|
217
|
+
|
|
218
|
+
1. Run `airlock-mcp check <workspace>`.
|
|
219
|
+
2. Run `airlock-mcp summary <workspace>` and `airlock-mcp next <workspace>`
|
|
220
|
+
to re-enter the draft.
|
|
221
|
+
3. Use `airlock-mcp list-workspaces` when choosing which draft to resume.
|
|
222
|
+
4. Ask Codex to read the workspace and continue the draft.
|
|
223
|
+
5. Update `decisions.md` before changing `spec.config.json` when a decision
|
|
224
|
+
affects row grain, evidence, business time, access, workflow, or references.
|
|
225
|
+
6. Keep `questions.md` for decisions that need the human.
|
|
226
|
+
7. Use `review.md` for local check results, Airlock validation results, and the
|
|
227
|
+
next safe action.
|
|
228
|
+
8. Export CSV only after the local checker is clean or the exception is
|
|
229
|
+
deliberate and recorded.
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reunionstudio/airlock-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Single-install MCP interface for Airlock agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/reunionstudio/airlock-mcp.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/reunionstudio/airlock-mcp#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/reunionstudio/airlock-mcp/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"airlock",
|
|
16
|
+
"mcp",
|
|
17
|
+
"codex",
|
|
18
|
+
"agents",
|
|
19
|
+
"specs"
|
|
20
|
+
],
|
|
21
|
+
"bin": {
|
|
22
|
+
"airlock-mcp": "bin/airlock-mcp.mjs"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "node test/smoke.mjs"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin",
|
|
29
|
+
"docs",
|
|
30
|
+
"src",
|
|
31
|
+
".agents",
|
|
32
|
+
"patterns",
|
|
33
|
+
"schemas",
|
|
34
|
+
"workspaces",
|
|
35
|
+
"setup.py",
|
|
36
|
+
"README.md",
|
|
37
|
+
"SECURITY.md"
|
|
38
|
+
],
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18"
|
|
41
|
+
},
|
|
42
|
+
"license": "Apache-2.0",
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Starter Pattern: Blank Draft
|
|
2
|
+
|
|
3
|
+
Use `blank` when the user already has a process in mind and needs a small,
|
|
4
|
+
neutral observation-style starting point.
|
|
5
|
+
|
|
6
|
+
This pattern keeps the first draft intentionally plain:
|
|
7
|
+
|
|
8
|
+
- one stable record id
|
|
9
|
+
- one business timestamp
|
|
10
|
+
- one summary
|
|
11
|
+
- one validated `variant` context field
|
|
12
|
+
|
|
13
|
+
Replace the draft columns once the row grain and typed business facts are clear.
|
|
14
|
+
Do not keep this shape just because it is convenient.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"spec_name": "draft_spec",
|
|
3
|
+
"filename": "draft_001",
|
|
4
|
+
"records": [
|
|
5
|
+
{
|
|
6
|
+
"record_id": "REC-001",
|
|
7
|
+
"observed_at": "2026-06-13 09:00:00",
|
|
8
|
+
"summary": "Example draft record.",
|
|
9
|
+
"details": {
|
|
10
|
+
"source": {
|
|
11
|
+
"system": "manual"
|
|
12
|
+
},
|
|
13
|
+
"notes": {
|
|
14
|
+
"reason": "Used to test the draft shape."
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"core_config": {
|
|
3
|
+
"spec_name": "draft_spec",
|
|
4
|
+
"spec_alias": "Draft Spec",
|
|
5
|
+
"description": "Draft Airlock spec.",
|
|
6
|
+
"owner_role": "app_admin",
|
|
7
|
+
"is_published": false,
|
|
8
|
+
"is_archived": false
|
|
9
|
+
},
|
|
10
|
+
"column_config": [
|
|
11
|
+
{
|
|
12
|
+
"name": "record_id",
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Stable record identifier.",
|
|
15
|
+
"tests": ["not_null", "unique"]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "observed_at",
|
|
19
|
+
"type": "datetime",
|
|
20
|
+
"description": "Business timestamp for the observed event.",
|
|
21
|
+
"format": "%Y-%m-%d %H:%M:%S",
|
|
22
|
+
"tests": ["not_null"]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "summary",
|
|
26
|
+
"type": "string",
|
|
27
|
+
"description": "Short business-readable summary.",
|
|
28
|
+
"tests": ["not_null"]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "details",
|
|
32
|
+
"type": "variant",
|
|
33
|
+
"description": "Optional validated context.",
|
|
34
|
+
"tests": []
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"rules": [
|
|
38
|
+
{
|
|
39
|
+
"type": "variant_shape",
|
|
40
|
+
"field": "details",
|
|
41
|
+
"allowed_root_keys": ["source", "notes"],
|
|
42
|
+
"paths": [
|
|
43
|
+
{
|
|
44
|
+
"json_path": "$.source.system",
|
|
45
|
+
"type": "string",
|
|
46
|
+
"required": false
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"json_path": "$.notes.reason",
|
|
50
|
+
"type": "string",
|
|
51
|
+
"required": false
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
"file_rules": {
|
|
57
|
+
"file_format": {
|
|
58
|
+
"file_type": "csv",
|
|
59
|
+
"record_delimiter": "\n",
|
|
60
|
+
"field_delimiter": ",",
|
|
61
|
+
"field_optionally_enclosed_by": "\"",
|
|
62
|
+
"escape_unenclosed_field": "\\",
|
|
63
|
+
"encoding": "UTF8",
|
|
64
|
+
"parse_header": true,
|
|
65
|
+
"save_header": true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"attachment_policy": {
|
|
69
|
+
"attachments_enabled": true,
|
|
70
|
+
"attachment_required": false
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Guest Access: Individual Isolation
|
|
2
|
+
|
|
3
|
+
Use this when each person or agent should submit into an isolated path and
|
|
4
|
+
should not see another submitter's files.
|
|
5
|
+
|
|
6
|
+
Good fit:
|
|
7
|
+
|
|
8
|
+
- reimbursements by employee
|
|
9
|
+
- private intake drafts
|
|
10
|
+
- delegated assistant work for one principal
|
|
11
|
+
- sensitive observations where cross-user visibility is risky
|
|
12
|
+
|
|
13
|
+
Design notes:
|
|
14
|
+
|
|
15
|
+
- Enable isolated directories.
|
|
16
|
+
- Give each guest role the narrowest useful access level.
|
|
17
|
+
- Keep manager, reviewer, or owner visibility in Airlock roles rather than
|
|
18
|
+
payload columns.
|
|
19
|
+
- Use delegation when an agent acts for a specific person. Do not impersonate
|
|
20
|
+
the human by reusing their role assignment.
|
|
21
|
+
|
|
22
|
+
Questions to answer:
|
|
23
|
+
|
|
24
|
+
- Who owns the submitted record after review?
|
|
25
|
+
- Does a reviewer need managed-role visibility across isolated submitters?
|
|
26
|
+
- Can the submitter read returned drafts, approved files, or only their own
|
|
27
|
+
working path?
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Guest Access: Role Isolation
|
|
2
|
+
|
|
3
|
+
Use this when groups such as departments, store locations, teams, or external
|
|
4
|
+
partners need separate contribution areas.
|
|
5
|
+
|
|
6
|
+
Good fit:
|
|
7
|
+
|
|
8
|
+
- location-level operations logs
|
|
9
|
+
- department budget packets
|
|
10
|
+
- partner submissions
|
|
11
|
+
- team-owned weekly reports
|
|
12
|
+
|
|
13
|
+
Design notes:
|
|
14
|
+
|
|
15
|
+
- Model the group as an Airlock role.
|
|
16
|
+
- Use `managed_by_role` only when a non-admin business role should manage or
|
|
17
|
+
include subordinate roles.
|
|
18
|
+
- Keep role membership and assignment outside the submitted payload.
|
|
19
|
+
- Prefer reference specs for shared project, location, department, or partner
|
|
20
|
+
catalogs.
|
|
21
|
+
|
|
22
|
+
Questions to answer:
|
|
23
|
+
|
|
24
|
+
- Are records owned by the role, by individual contributors, or by both?
|
|
25
|
+
- Does a parent role need read or review visibility?
|
|
26
|
+
- Do role groups share a public read path after approval?
|