codex-workspace-bootstrap 0.4.0__tar.gz → 0.5.1__tar.gz
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.
- {codex_workspace_bootstrap-0.4.0/src/codex_workspace_bootstrap.egg-info → codex_workspace_bootstrap-0.5.1}/PKG-INFO +80 -5
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/README.md +79 -4
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/pyproject.toml +1 -1
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap/__init__.py +1 -1
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap/cli.py +95 -4
- codex_workspace_bootstrap-0.5.1/src/codex_workspace_bootstrap/fixes.py +72 -0
- codex_workspace_bootstrap-0.5.1/src/codex_workspace_bootstrap/instructions.py +654 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap/preflight.py +61 -53
- codex_workspace_bootstrap-0.5.1/src/codex_workspace_bootstrap/sarif.py +205 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1/src/codex_workspace_bootstrap.egg-info}/PKG-INFO +80 -5
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap.egg-info/SOURCES.txt +4 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/tests/test_cli.py +33 -1
- codex_workspace_bootstrap-0.5.1/tests/test_instruction_integrity.py +381 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/tests/test_preflight.py +60 -0
- codex_workspace_bootstrap-0.5.1/tests/test_public_repo_patterns.py +72 -0
- codex_workspace_bootstrap-0.5.1/tests/test_sarif.py +96 -0
- codex_workspace_bootstrap-0.4.0/src/codex_workspace_bootstrap/sarif.py +0 -83
- codex_workspace_bootstrap-0.4.0/tests/test_sarif.py +0 -44
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/LICENSE +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/setup.cfg +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap/__main__.py +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap/agents.py +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap/audit.py +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap/doctor.py +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap.egg-info/dependency_links.txt +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap.egg-info/entry_points.txt +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/src/codex_workspace_bootstrap.egg-info/top_level.txt +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/tests/test_audit.py +0 -0
- {codex_workspace_bootstrap-0.4.0 → codex_workspace_bootstrap-0.5.1}/tests/test_doctor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-workspace-bootstrap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Preflight AI coding repositories before Codex, Copilot, Cline, Claude, Gemini, Continue, or Cursor touches them.
|
|
5
5
|
Author: kohli217
|
|
6
6
|
License: MIT
|
|
@@ -30,12 +30,13 @@ Dynamic: license-file
|
|
|
30
30
|
|
|
31
31
|
[](https://github.com/kohli217/codex-workspace-bootstrap/actions/workflows/ci.yml)
|
|
32
32
|
[](https://github.com/kohli217/codex-workspace-bootstrap/actions/workflows/codeql.yml)
|
|
33
|
+
[](https://scorecard.dev/viewer/?uri=github.com/kohli217/codex-workspace-bootstrap)
|
|
33
34
|
[](https://github.com/kohli217/codex-workspace-bootstrap/releases/latest)
|
|
34
35
|
[](https://pypi.org/project/codex-workspace-bootstrap/)
|
|
35
36
|
[](LICENSE)
|
|
36
37
|
[](pyproject.toml)
|
|
37
38
|
|
|
38
|
-
**Preflight your repository before an AI coding agent touches it.**
|
|
39
|
+
**Preflight your repository before an AI coding agent touches it — and catch instruction drift before different agents follow different rules.**
|
|
39
40
|
|
|
40
41
|
Windows-first. Local by default. CI-friendly. Designed for repositories used with Codex, Copilot, Cline, Claude Code, Gemini CLI, Continue, Cursor, and similar coding agents.
|
|
41
42
|
|
|
@@ -58,6 +59,7 @@ State: NEEDS ATTENTION
|
|
|
58
59
|
Project: Python
|
|
59
60
|
AI instructions: none detected
|
|
60
61
|
Audit: 10 passed, 4 warnings, 0 blocking
|
|
62
|
+
Instruction integrity: 0 findings, 0 drift, 0 invalid commands, 0 metadata
|
|
61
63
|
Next actions:
|
|
62
64
|
[P1] Add repository instructions for AI coding agents -> cwb init-agents .
|
|
63
65
|
[P2] Make the Codex CLI available when local Codex workflows are intended -> codex --version
|
|
@@ -70,6 +72,43 @@ cwb init-agents .
|
|
|
70
72
|
cwb preflight .
|
|
71
73
|
```
|
|
72
74
|
|
|
75
|
+
### See it catch real mistakes
|
|
76
|
+
|
|
77
|
+
A reproducible demo creates a temporary repository where the project uses **pnpm** but `AGENTS.md` tells the agent to use **npm** and references a nonexistent `lint` script.
|
|
78
|
+
|
|
79
|
+
```powershell
|
|
80
|
+
py examples/first-run-demo/run_demo.py
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Expected outcome:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
=== BEFORE ===
|
|
87
|
+
State: NEEDS ATTENTION
|
|
88
|
+
Findings:
|
|
89
|
+
- package-manager-mismatch
|
|
90
|
+
- missing-package-script
|
|
91
|
+
|
|
92
|
+
=== AFTER ===
|
|
93
|
+
State: READY
|
|
94
|
+
Findings: none
|
|
95
|
+
|
|
96
|
+
Demo verification: PASS
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
See [examples/first-run-demo](examples/first-run-demo) for the full reproducible demo. It uses disposable temporary Git repositories and is verified in CI.
|
|
100
|
+
|
|
101
|
+
### Try it on your repository
|
|
102
|
+
|
|
103
|
+
```powershell
|
|
104
|
+
py -m pip install codex-workspace-bootstrap
|
|
105
|
+
cwb preflight .
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
If the result is useful, noisy, or surprising, open a [Usage report](https://github.com/kohli217/codex-workspace-bootstrap/issues/new?template=usage_report.yml). Public references are optional; do not include private repository contents, credentials, or secret values.
|
|
109
|
+
|
|
110
|
+
Useful feedback includes false positives, missing repository layouts, monorepo behavior, and which check saved you time.
|
|
111
|
+
|
|
73
112
|
The goal is not a vanity score. The result is one of:
|
|
74
113
|
|
|
75
114
|
- **READY** — core repository signals and AI instructions are present, with no blocking finding;
|
|
@@ -101,6 +140,17 @@ The preflight detects repository instruction/config signals for:
|
|
|
101
140
|
|
|
102
141
|
It does not claim these files are correct merely because they exist. It tells you what was detected so a maintainer can review the actual instructions.
|
|
103
142
|
|
|
143
|
+
### Cross-agent instruction integrity
|
|
144
|
+
|
|
145
|
+
When multiple AI instruction files exist, `cwb` reads executable-looking commands and checks them against repository evidence. It understands nested `AGENTS.md` / `AGENTS.override.md`, nested Cursor `.cursor/rules`, and common path-specific frontmatter such as Copilot `applyTo` and rule `globs`. It can flag:
|
|
146
|
+
|
|
147
|
+
- package-manager mismatches against `packageManager` and lockfiles;
|
|
148
|
+
- cross-agent package-manager drift;
|
|
149
|
+
- missing `package.json` scripts referenced by instructions;
|
|
150
|
+
- conflicting test/lint/build validation commands when instruction files have no shared command for the same validation family.
|
|
151
|
+
|
|
152
|
+
The lint is intentionally conservative: different files may contain additional commands without being treated as conflicts when they share a compatible validation baseline. Commands from different scopes are not compared as if they were global rules. Path-specific rules are validated individually against repository evidence but are not cross-compared for drift unless their full selector semantics can be represented safely. A repository is not marked READY when it only has nested/path-specific instructions and no repository-wide instruction baseline.
|
|
153
|
+
|
|
104
154
|
### Risk signals
|
|
105
155
|
|
|
106
156
|
The audit warns about common secret-bearing filenames without printing their contents. When Git is available, it distinguishes **tracked**, **ignored**, and **untracked/unknown** candidates. Tracked risky filenames can become blocking findings in strict mode.
|
|
@@ -146,6 +196,7 @@ Write reports for automation or review:
|
|
|
146
196
|
```powershell
|
|
147
197
|
cwb preflight . --json preflight.json
|
|
148
198
|
cwb preflight . --markdown preflight.md
|
|
199
|
+
cwb preflight . --sarif preflight.sarif
|
|
149
200
|
```
|
|
150
201
|
|
|
151
202
|
Use strict mode when blocking findings should return a non-zero exit code:
|
|
@@ -154,6 +205,12 @@ Use strict mode when blocking findings should return a non-zero exit code:
|
|
|
154
205
|
cwb preflight . --strict
|
|
155
206
|
```
|
|
156
207
|
|
|
208
|
+
Fail CI on any instruction-integrity finding:
|
|
209
|
+
|
|
210
|
+
```powershell
|
|
211
|
+
cwb preflight . --fail-on-integrity
|
|
212
|
+
```
|
|
213
|
+
|
|
157
214
|
### Detailed audit
|
|
158
215
|
|
|
159
216
|
```powershell
|
|
@@ -163,6 +220,20 @@ cwb audit . --sarif audit.sarif
|
|
|
163
220
|
cwb audit . --strict
|
|
164
221
|
```
|
|
165
222
|
|
|
223
|
+
### Safe fix preview
|
|
224
|
+
|
|
225
|
+
```powershell
|
|
226
|
+
cwb fix .
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
This is preview-only by default. To apply only low-risk supported fixes:
|
|
230
|
+
|
|
231
|
+
```powershell
|
|
232
|
+
cwb fix . --apply
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Existing conflicting instruction files are never auto-rewritten. They remain human-review findings.
|
|
236
|
+
|
|
166
237
|
### Non-destructive doctor
|
|
167
238
|
|
|
168
239
|
```powershell
|
|
@@ -188,16 +259,19 @@ The reusable Action is published on GitHub Marketplace.
|
|
|
188
259
|
- uses: actions/setup-python@v7
|
|
189
260
|
with:
|
|
190
261
|
python-version: "3.13"
|
|
191
|
-
- uses: kohli217/codex-workspace-bootstrap@v0.
|
|
262
|
+
- uses: kohli217/codex-workspace-bootstrap@v0.5.1
|
|
192
263
|
with:
|
|
193
264
|
path: .
|
|
194
265
|
strict: "true"
|
|
266
|
+
fail_on_integrity: "true"
|
|
195
267
|
```
|
|
196
268
|
|
|
197
|
-
The Action adds the preflight Markdown report to the **GitHub Actions job summary**, so maintainers get a readable readiness snapshot without digging through raw logs. Optional SARIF output can be uploaded to GitHub Code Scanning.
|
|
269
|
+
The Action adds the preflight Markdown report to the **GitHub Actions job summary**, so maintainers get a readable readiness snapshot without digging through raw logs. Optional SARIF output contains both repository-audit and instruction-integrity findings and can be uploaded to GitHub Code Scanning.
|
|
198
270
|
|
|
199
271
|
See [docs/GITHUB_ACTION.md](docs/GITHUB_ACTION.md).
|
|
200
272
|
|
|
273
|
+
Read-only evaluations against real public repositories are documented in [docs/PUBLIC_REPO_EVALUATIONS.md](docs/PUBLIC_REPO_EVALUATIONS.md). They are reproducible technical evaluations, not claims of third-party adoption.
|
|
274
|
+
|
|
201
275
|
## Where it fits
|
|
202
276
|
|
|
203
277
|
This project is a **preflight layer**, not an AI coding agent and not a deep security scanner.
|
|
@@ -216,6 +290,7 @@ The intent is to complement those tools, not replace them.
|
|
|
216
290
|
- Core checks run locally.
|
|
217
291
|
- Suspected secret files are not opened or printed by the filename-risk check.
|
|
218
292
|
- Repository contents are not sent to a remote AI service by the core audit.
|
|
293
|
+
- Instruction files are read locally for deterministic linting; extracted commands are never executed by the integrity lint.
|
|
219
294
|
- Existing `AGENTS.md` files are protected unless overwrite is explicit.
|
|
220
295
|
- A passing preflight is evidence about the checks performed, **not a security guarantee**.
|
|
221
296
|
|
|
@@ -248,7 +323,7 @@ py -m pip install codex-workspace-bootstrap
|
|
|
248
323
|
Pinned GitHub release artifact:
|
|
249
324
|
|
|
250
325
|
```powershell
|
|
251
|
-
py -m pip install "https://github.com/kohli217/codex-workspace-bootstrap/releases/download/v0.
|
|
326
|
+
py -m pip install "https://github.com/kohli217/codex-workspace-bootstrap/releases/download/v0.5.1/codex_workspace_bootstrap-0.5.1-py3-none-any.whl"
|
|
252
327
|
```
|
|
253
328
|
|
|
254
329
|
## Development
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/kohli217/codex-workspace-bootstrap/actions/workflows/ci.yml)
|
|
4
4
|
[](https://github.com/kohli217/codex-workspace-bootstrap/actions/workflows/codeql.yml)
|
|
5
|
+
[](https://scorecard.dev/viewer/?uri=github.com/kohli217/codex-workspace-bootstrap)
|
|
5
6
|
[](https://github.com/kohli217/codex-workspace-bootstrap/releases/latest)
|
|
6
7
|
[](https://pypi.org/project/codex-workspace-bootstrap/)
|
|
7
8
|
[](LICENSE)
|
|
8
9
|
[](pyproject.toml)
|
|
9
10
|
|
|
10
|
-
**Preflight your repository before an AI coding agent touches it.**
|
|
11
|
+
**Preflight your repository before an AI coding agent touches it — and catch instruction drift before different agents follow different rules.**
|
|
11
12
|
|
|
12
13
|
Windows-first. Local by default. CI-friendly. Designed for repositories used with Codex, Copilot, Cline, Claude Code, Gemini CLI, Continue, Cursor, and similar coding agents.
|
|
13
14
|
|
|
@@ -30,6 +31,7 @@ State: NEEDS ATTENTION
|
|
|
30
31
|
Project: Python
|
|
31
32
|
AI instructions: none detected
|
|
32
33
|
Audit: 10 passed, 4 warnings, 0 blocking
|
|
34
|
+
Instruction integrity: 0 findings, 0 drift, 0 invalid commands, 0 metadata
|
|
33
35
|
Next actions:
|
|
34
36
|
[P1] Add repository instructions for AI coding agents -> cwb init-agents .
|
|
35
37
|
[P2] Make the Codex CLI available when local Codex workflows are intended -> codex --version
|
|
@@ -42,6 +44,43 @@ cwb init-agents .
|
|
|
42
44
|
cwb preflight .
|
|
43
45
|
```
|
|
44
46
|
|
|
47
|
+
### See it catch real mistakes
|
|
48
|
+
|
|
49
|
+
A reproducible demo creates a temporary repository where the project uses **pnpm** but `AGENTS.md` tells the agent to use **npm** and references a nonexistent `lint` script.
|
|
50
|
+
|
|
51
|
+
```powershell
|
|
52
|
+
py examples/first-run-demo/run_demo.py
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Expected outcome:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
=== BEFORE ===
|
|
59
|
+
State: NEEDS ATTENTION
|
|
60
|
+
Findings:
|
|
61
|
+
- package-manager-mismatch
|
|
62
|
+
- missing-package-script
|
|
63
|
+
|
|
64
|
+
=== AFTER ===
|
|
65
|
+
State: READY
|
|
66
|
+
Findings: none
|
|
67
|
+
|
|
68
|
+
Demo verification: PASS
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
See [examples/first-run-demo](examples/first-run-demo) for the full reproducible demo. It uses disposable temporary Git repositories and is verified in CI.
|
|
72
|
+
|
|
73
|
+
### Try it on your repository
|
|
74
|
+
|
|
75
|
+
```powershell
|
|
76
|
+
py -m pip install codex-workspace-bootstrap
|
|
77
|
+
cwb preflight .
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If the result is useful, noisy, or surprising, open a [Usage report](https://github.com/kohli217/codex-workspace-bootstrap/issues/new?template=usage_report.yml). Public references are optional; do not include private repository contents, credentials, or secret values.
|
|
81
|
+
|
|
82
|
+
Useful feedback includes false positives, missing repository layouts, monorepo behavior, and which check saved you time.
|
|
83
|
+
|
|
45
84
|
The goal is not a vanity score. The result is one of:
|
|
46
85
|
|
|
47
86
|
- **READY** — core repository signals and AI instructions are present, with no blocking finding;
|
|
@@ -73,6 +112,17 @@ The preflight detects repository instruction/config signals for:
|
|
|
73
112
|
|
|
74
113
|
It does not claim these files are correct merely because they exist. It tells you what was detected so a maintainer can review the actual instructions.
|
|
75
114
|
|
|
115
|
+
### Cross-agent instruction integrity
|
|
116
|
+
|
|
117
|
+
When multiple AI instruction files exist, `cwb` reads executable-looking commands and checks them against repository evidence. It understands nested `AGENTS.md` / `AGENTS.override.md`, nested Cursor `.cursor/rules`, and common path-specific frontmatter such as Copilot `applyTo` and rule `globs`. It can flag:
|
|
118
|
+
|
|
119
|
+
- package-manager mismatches against `packageManager` and lockfiles;
|
|
120
|
+
- cross-agent package-manager drift;
|
|
121
|
+
- missing `package.json` scripts referenced by instructions;
|
|
122
|
+
- conflicting test/lint/build validation commands when instruction files have no shared command for the same validation family.
|
|
123
|
+
|
|
124
|
+
The lint is intentionally conservative: different files may contain additional commands without being treated as conflicts when they share a compatible validation baseline. Commands from different scopes are not compared as if they were global rules. Path-specific rules are validated individually against repository evidence but are not cross-compared for drift unless their full selector semantics can be represented safely. A repository is not marked READY when it only has nested/path-specific instructions and no repository-wide instruction baseline.
|
|
125
|
+
|
|
76
126
|
### Risk signals
|
|
77
127
|
|
|
78
128
|
The audit warns about common secret-bearing filenames without printing their contents. When Git is available, it distinguishes **tracked**, **ignored**, and **untracked/unknown** candidates. Tracked risky filenames can become blocking findings in strict mode.
|
|
@@ -118,6 +168,7 @@ Write reports for automation or review:
|
|
|
118
168
|
```powershell
|
|
119
169
|
cwb preflight . --json preflight.json
|
|
120
170
|
cwb preflight . --markdown preflight.md
|
|
171
|
+
cwb preflight . --sarif preflight.sarif
|
|
121
172
|
```
|
|
122
173
|
|
|
123
174
|
Use strict mode when blocking findings should return a non-zero exit code:
|
|
@@ -126,6 +177,12 @@ Use strict mode when blocking findings should return a non-zero exit code:
|
|
|
126
177
|
cwb preflight . --strict
|
|
127
178
|
```
|
|
128
179
|
|
|
180
|
+
Fail CI on any instruction-integrity finding:
|
|
181
|
+
|
|
182
|
+
```powershell
|
|
183
|
+
cwb preflight . --fail-on-integrity
|
|
184
|
+
```
|
|
185
|
+
|
|
129
186
|
### Detailed audit
|
|
130
187
|
|
|
131
188
|
```powershell
|
|
@@ -135,6 +192,20 @@ cwb audit . --sarif audit.sarif
|
|
|
135
192
|
cwb audit . --strict
|
|
136
193
|
```
|
|
137
194
|
|
|
195
|
+
### Safe fix preview
|
|
196
|
+
|
|
197
|
+
```powershell
|
|
198
|
+
cwb fix .
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
This is preview-only by default. To apply only low-risk supported fixes:
|
|
202
|
+
|
|
203
|
+
```powershell
|
|
204
|
+
cwb fix . --apply
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Existing conflicting instruction files are never auto-rewritten. They remain human-review findings.
|
|
208
|
+
|
|
138
209
|
### Non-destructive doctor
|
|
139
210
|
|
|
140
211
|
```powershell
|
|
@@ -160,16 +231,19 @@ The reusable Action is published on GitHub Marketplace.
|
|
|
160
231
|
- uses: actions/setup-python@v7
|
|
161
232
|
with:
|
|
162
233
|
python-version: "3.13"
|
|
163
|
-
- uses: kohli217/codex-workspace-bootstrap@v0.
|
|
234
|
+
- uses: kohli217/codex-workspace-bootstrap@v0.5.1
|
|
164
235
|
with:
|
|
165
236
|
path: .
|
|
166
237
|
strict: "true"
|
|
238
|
+
fail_on_integrity: "true"
|
|
167
239
|
```
|
|
168
240
|
|
|
169
|
-
The Action adds the preflight Markdown report to the **GitHub Actions job summary**, so maintainers get a readable readiness snapshot without digging through raw logs. Optional SARIF output can be uploaded to GitHub Code Scanning.
|
|
241
|
+
The Action adds the preflight Markdown report to the **GitHub Actions job summary**, so maintainers get a readable readiness snapshot without digging through raw logs. Optional SARIF output contains both repository-audit and instruction-integrity findings and can be uploaded to GitHub Code Scanning.
|
|
170
242
|
|
|
171
243
|
See [docs/GITHUB_ACTION.md](docs/GITHUB_ACTION.md).
|
|
172
244
|
|
|
245
|
+
Read-only evaluations against real public repositories are documented in [docs/PUBLIC_REPO_EVALUATIONS.md](docs/PUBLIC_REPO_EVALUATIONS.md). They are reproducible technical evaluations, not claims of third-party adoption.
|
|
246
|
+
|
|
173
247
|
## Where it fits
|
|
174
248
|
|
|
175
249
|
This project is a **preflight layer**, not an AI coding agent and not a deep security scanner.
|
|
@@ -188,6 +262,7 @@ The intent is to complement those tools, not replace them.
|
|
|
188
262
|
- Core checks run locally.
|
|
189
263
|
- Suspected secret files are not opened or printed by the filename-risk check.
|
|
190
264
|
- Repository contents are not sent to a remote AI service by the core audit.
|
|
265
|
+
- Instruction files are read locally for deterministic linting; extracted commands are never executed by the integrity lint.
|
|
191
266
|
- Existing `AGENTS.md` files are protected unless overwrite is explicit.
|
|
192
267
|
- A passing preflight is evidence about the checks performed, **not a security guarantee**.
|
|
193
268
|
|
|
@@ -220,7 +295,7 @@ py -m pip install codex-workspace-bootstrap
|
|
|
220
295
|
Pinned GitHub release artifact:
|
|
221
296
|
|
|
222
297
|
```powershell
|
|
223
|
-
py -m pip install "https://github.com/kohli217/codex-workspace-bootstrap/releases/download/v0.
|
|
298
|
+
py -m pip install "https://github.com/kohli217/codex-workspace-bootstrap/releases/download/v0.5.1/codex_workspace_bootstrap-0.5.1-py3-none-any.whl"
|
|
224
299
|
```
|
|
225
300
|
|
|
226
301
|
## Development
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codex-workspace-bootstrap"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.1"
|
|
8
8
|
description = "Preflight AI coding repositories before Codex, Copilot, Cline, Claude, Gemini, Continue, or Cursor touches them."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -9,14 +9,15 @@ from . import __version__
|
|
|
9
9
|
from .agents import generate_agents
|
|
10
10
|
from .audit import audit_repository, summary
|
|
11
11
|
from .doctor import doctor_findings
|
|
12
|
+
from .fixes import apply_fix_plan, build_fix_plan
|
|
12
13
|
from .preflight import build_preflight, render_markdown
|
|
13
|
-
from .sarif import checks_to_sarif
|
|
14
|
+
from .sarif import checks_to_sarif, preflight_report_to_sarif
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def _parser() -> argparse.ArgumentParser:
|
|
17
18
|
parser = argparse.ArgumentParser(
|
|
18
19
|
prog="codex-workspace-bootstrap",
|
|
19
|
-
description="
|
|
20
|
+
description="Preflight AI coding repositories for readiness, instruction integrity, and CI enforcement.",
|
|
20
21
|
)
|
|
21
22
|
parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
|
|
22
23
|
sub = parser.add_subparsers(dest="command", required=True)
|
|
@@ -25,11 +26,29 @@ def _parser() -> argparse.ArgumentParser:
|
|
|
25
26
|
preflight.add_argument("path", nargs="?", default=".")
|
|
26
27
|
preflight.add_argument("--json", dest="json_path", help="Write the complete preflight report to JSON")
|
|
27
28
|
preflight.add_argument("--markdown", dest="markdown_path", help="Write a concise Markdown preflight report")
|
|
29
|
+
preflight.add_argument(
|
|
30
|
+
"--sarif",
|
|
31
|
+
dest="sarif_path",
|
|
32
|
+
help="Write audit and instruction-integrity findings as SARIF 2.1.0",
|
|
33
|
+
)
|
|
28
34
|
preflight.add_argument(
|
|
29
35
|
"--strict",
|
|
30
36
|
action="store_true",
|
|
31
37
|
help="Return a non-zero exit code when blocking findings are present",
|
|
32
38
|
)
|
|
39
|
+
preflight.add_argument(
|
|
40
|
+
"--fail-on-integrity",
|
|
41
|
+
action="store_true",
|
|
42
|
+
help="Return a non-zero exit code when AI instruction integrity findings are present",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
fix = sub.add_parser("fix", help="Preview safe repository-readiness fixes")
|
|
46
|
+
fix.add_argument("path", nargs="?", default=".")
|
|
47
|
+
fix.add_argument(
|
|
48
|
+
"--apply",
|
|
49
|
+
action="store_true",
|
|
50
|
+
help="Apply only low-risk supported fixes; conflicting instructions are never auto-rewritten",
|
|
51
|
+
)
|
|
33
52
|
|
|
34
53
|
audit = sub.add_parser("audit", help="Audit a repository and local toolchain")
|
|
35
54
|
audit.add_argument("path", nargs="?", default=".")
|
|
@@ -63,7 +82,9 @@ def _run_preflight(
|
|
|
63
82
|
path: str,
|
|
64
83
|
json_path: str | None,
|
|
65
84
|
markdown_path: str | None,
|
|
85
|
+
sarif_path: str | None,
|
|
66
86
|
strict: bool,
|
|
87
|
+
fail_on_integrity: bool,
|
|
67
88
|
) -> int:
|
|
68
89
|
root = Path(path).expanduser().resolve()
|
|
69
90
|
if not root.exists() or not root.is_dir():
|
|
@@ -84,7 +105,7 @@ def _run_preflight(
|
|
|
84
105
|
if instructions:
|
|
85
106
|
print("AI instructions:")
|
|
86
107
|
for item in instructions:
|
|
87
|
-
print(f" - {item['tool']}: {item['path']}")
|
|
108
|
+
print(f" - {item['tool']}: {item['path']} [scope={item.get('scope', '.')}]")
|
|
88
109
|
else:
|
|
89
110
|
print("AI instructions: none detected")
|
|
90
111
|
|
|
@@ -94,6 +115,23 @@ def _run_preflight(
|
|
|
94
115
|
f"{totals['warnings']} warnings, {totals['blocking']} blocking"
|
|
95
116
|
)
|
|
96
117
|
|
|
118
|
+
instruction_totals = report["instruction_summary"]
|
|
119
|
+
print(
|
|
120
|
+
f"Instruction integrity: {instruction_totals['findings']} findings, "
|
|
121
|
+
f"{instruction_totals['drift']} drift, "
|
|
122
|
+
f"{instruction_totals['invalid_commands']} invalid commands, "
|
|
123
|
+
f"{instruction_totals['metadata']} metadata"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
findings = report["instruction_findings"]
|
|
127
|
+
if findings:
|
|
128
|
+
print("Instruction findings:")
|
|
129
|
+
for item in findings:
|
|
130
|
+
print(
|
|
131
|
+
f" [{item['severity'].upper()}] {item['kind']}: {item['message']} "
|
|
132
|
+
f"[scope={item.get('scope', '.')}]"
|
|
133
|
+
)
|
|
134
|
+
|
|
97
135
|
actions = report["next_actions"]
|
|
98
136
|
if actions:
|
|
99
137
|
print("Next actions:")
|
|
@@ -112,8 +150,52 @@ def _run_preflight(
|
|
|
112
150
|
output.write_text(render_markdown(report), encoding="utf-8")
|
|
113
151
|
print(f"Preflight Markdown report written to: {output}")
|
|
114
152
|
|
|
153
|
+
if sarif_path:
|
|
154
|
+
_write_json(
|
|
155
|
+
sarif_path,
|
|
156
|
+
preflight_report_to_sarif(report),
|
|
157
|
+
"Preflight SARIF report",
|
|
158
|
+
)
|
|
159
|
+
|
|
115
160
|
if strict and report["state"] == "BLOCKED":
|
|
116
161
|
return 1
|
|
162
|
+
if fail_on_integrity and report["instruction_summary"]["findings"]:
|
|
163
|
+
return 1
|
|
164
|
+
return 0
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _run_fix(path: str, apply: bool) -> int:
|
|
168
|
+
root = Path(path).expanduser().resolve()
|
|
169
|
+
if not root.exists() or not root.is_dir():
|
|
170
|
+
print(f"error: repository path does not exist or is not a directory: {root}", file=sys.stderr)
|
|
171
|
+
return 2
|
|
172
|
+
|
|
173
|
+
plan = build_fix_plan(root)
|
|
174
|
+
print(f"Repository: {root}")
|
|
175
|
+
if not plan:
|
|
176
|
+
print("Fix plan: no supported fixes or instruction-integrity findings.")
|
|
177
|
+
return 0
|
|
178
|
+
|
|
179
|
+
print("Fix plan:")
|
|
180
|
+
for item in plan:
|
|
181
|
+
mode = "AUTO" if item.apply_supported else "REVIEW"
|
|
182
|
+
target = f" -> {item.target}" if item.target else ""
|
|
183
|
+
print(f" [{mode}] {item.description}{target}")
|
|
184
|
+
|
|
185
|
+
if not apply:
|
|
186
|
+
print("Preview only. Re-run with --apply to apply low-risk supported fixes.")
|
|
187
|
+
return 0
|
|
188
|
+
|
|
189
|
+
applied = apply_fix_plan(root, plan)
|
|
190
|
+
if applied:
|
|
191
|
+
print("Applied:")
|
|
192
|
+
for path_item in applied:
|
|
193
|
+
print(f" - {path_item}")
|
|
194
|
+
else:
|
|
195
|
+
print("No automatic changes were applied.")
|
|
196
|
+
manual = sum(not item.apply_supported for item in plan)
|
|
197
|
+
if manual:
|
|
198
|
+
print(f"{manual} finding(s) require human review and were left unchanged.")
|
|
117
199
|
return 0
|
|
118
200
|
|
|
119
201
|
def _run_audit(
|
|
@@ -200,7 +282,16 @@ def _run_init_agents(path: str, force: bool) -> int:
|
|
|
200
282
|
def main(argv: list[str] | None = None) -> int:
|
|
201
283
|
args = _parser().parse_args(argv)
|
|
202
284
|
if args.command == "preflight":
|
|
203
|
-
return _run_preflight(
|
|
285
|
+
return _run_preflight(
|
|
286
|
+
args.path,
|
|
287
|
+
args.json_path,
|
|
288
|
+
args.markdown_path,
|
|
289
|
+
args.sarif_path,
|
|
290
|
+
args.strict,
|
|
291
|
+
args.fail_on_integrity,
|
|
292
|
+
)
|
|
293
|
+
if args.command == "fix":
|
|
294
|
+
return _run_fix(args.path, args.apply)
|
|
204
295
|
if args.command == "audit":
|
|
205
296
|
return _run_audit(args.path, args.json_path, args.sarif_path, args.strict)
|
|
206
297
|
if args.command == "doctor":
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import asdict, dataclass
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .agents import generate_agents
|
|
7
|
+
from .instructions import detect_instruction_signals, lint_instructions
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class FixPlanItem:
|
|
12
|
+
kind: str
|
|
13
|
+
description: str
|
|
14
|
+
apply_supported: bool
|
|
15
|
+
target: str | None = None
|
|
16
|
+
|
|
17
|
+
def to_dict(self) -> dict[str, object]:
|
|
18
|
+
return asdict(self)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def build_fix_plan(root: Path) -> list[FixPlanItem]:
|
|
22
|
+
root = root.resolve()
|
|
23
|
+
plan: list[FixPlanItem] = []
|
|
24
|
+
|
|
25
|
+
signals = detect_instruction_signals(root)
|
|
26
|
+
findings = lint_instructions(root, signals)
|
|
27
|
+
|
|
28
|
+
has_repository_wide = any(
|
|
29
|
+
signal.scope == "." and signal.kind in {"repository", "override"}
|
|
30
|
+
for signal in signals
|
|
31
|
+
)
|
|
32
|
+
if not has_repository_wide:
|
|
33
|
+
plan.append(
|
|
34
|
+
FixPlanItem(
|
|
35
|
+
"create-agents",
|
|
36
|
+
(
|
|
37
|
+
"Create an evidence-based AGENTS.md because no supported repository-wide "
|
|
38
|
+
"AI instruction baseline was detected."
|
|
39
|
+
),
|
|
40
|
+
True,
|
|
41
|
+
"AGENTS.md",
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
for finding in findings:
|
|
46
|
+
plan.append(
|
|
47
|
+
FixPlanItem(
|
|
48
|
+
f"manual-{finding.kind}",
|
|
49
|
+
finding.message,
|
|
50
|
+
False,
|
|
51
|
+
", ".join(finding.files) if finding.files else None,
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return plan
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def apply_fix_plan(root: Path, plan: list[FixPlanItem]) -> list[str]:
|
|
59
|
+
root = root.resolve()
|
|
60
|
+
applied: list[str] = []
|
|
61
|
+
|
|
62
|
+
for item in plan:
|
|
63
|
+
if not item.apply_supported:
|
|
64
|
+
continue
|
|
65
|
+
if item.kind == "create-agents":
|
|
66
|
+
target = root / "AGENTS.md"
|
|
67
|
+
if target.exists():
|
|
68
|
+
continue
|
|
69
|
+
target.write_text(generate_agents(root), encoding="utf-8")
|
|
70
|
+
applied.append(str(target))
|
|
71
|
+
|
|
72
|
+
return applied
|