ai-project-maintainer 0.3.1 → 0.4.1

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.
Files changed (51) hide show
  1. package/README.md +45 -9
  2. package/ai-project-maintainer/agents/openai.yaml +6 -6
  3. package/ai-project-maintainer/references/ci-guardrails.md +55 -55
  4. package/ai-project-maintainer/references/database.md +60 -60
  5. package/ai-project-maintainer/references/electron-desktop.md +43 -43
  6. package/ai-project-maintainer/references/incident-response.md +52 -52
  7. package/ai-project-maintainer/references/security.md +48 -48
  8. package/ai-project-maintainer/references/tool-router.md +53 -53
  9. package/ai-project-maintainer/scripts/bootstrap-local-tools.ps1 +109 -109
  10. package/ai-project-maintainer/scripts/ci-smoke-gate.mjs +26 -26
  11. package/ai-project-maintainer/scripts/init-project.mjs +28 -16
  12. package/ai-project-maintainer/scripts/lib/check-registry.mjs +10 -9
  13. package/ai-project-maintainer/scripts/lib/checks.mjs +22 -10
  14. package/ai-project-maintainer/scripts/lib/command-runner.mjs +17 -3
  15. package/ai-project-maintainer/scripts/lib/policy.mjs +6 -4
  16. package/ai-project-maintainer/scripts/lib/report.mjs +56 -32
  17. package/assets/demo-90s-storyboard.svg +98 -0
  18. package/assets/demo-90s.gif +0 -0
  19. package/assets/social-preview.png +0 -0
  20. package/assets/social-preview.svg +55 -0
  21. package/docs/DEMO.md +39 -44
  22. package/docs/DEMO.zh-CN.md +40 -46
  23. package/docs/GITHUB-LAUNCH-CHECKLIST.md +11 -11
  24. package/docs/POLICY-AND-EXCEPTIONS.zh-CN.md +1 -1
  25. package/docs/PROMOTION.md +49 -21
  26. package/docs/SECURITY-WORKFLOW.md +63 -0
  27. package/docs/UPGRADE-ROADMAP.zh-CN.md +28 -27
  28. package/docs/demo-output/90-second-demo.html +187 -0
  29. package/docs/demo-output/before-after-case.md +91 -0
  30. package/docs/demo-output/security-report.md +45 -37
  31. package/docs/superpowers/plans/2026-06-29-ci-dogfooding.md +200 -200
  32. package/examples/demo-ai-app/.ai-maintainer/business-flows.yml +14 -0
  33. package/examples/demo-ai-app/.ai-maintainer/db-migration-policy.yml +6 -0
  34. package/examples/demo-ai-app/.ai-maintainer/evidence-sources.yml +18 -0
  35. package/examples/demo-ai-app/.ai-maintainer/exceptions.yml +1 -0
  36. package/examples/demo-ai-app/.ai-maintainer/incident-runbook.md +11 -0
  37. package/examples/demo-ai-app/.ai-maintainer/observability-checklist.yml +7 -0
  38. package/examples/demo-ai-app/.ai-maintainer/policy.yml +27 -0
  39. package/examples/demo-ai-app/.ai-maintainer/project-profile.yml +15 -0
  40. package/examples/demo-ai-app/.ai-maintainer/release-checklist.yml +7 -0
  41. package/examples/demo-ai-app/.ai-maintainer/risk-policy.yml +5 -0
  42. package/examples/demo-ai-app/.ai-maintainer/threat-model.md +18 -0
  43. package/examples/demo-ai-app/README.md +38 -0
  44. package/examples/demo-ai-app/package-lock.json +15 -0
  45. package/examples/demo-ai-app/package.json +16 -0
  46. package/examples/demo-ai-app/scripts/build.mjs +18 -0
  47. package/examples/demo-ai-app/scripts/create-before-state.mjs +86 -0
  48. package/examples/demo-ai-app/scripts/run-demo-gate.mjs +95 -0
  49. package/examples/demo-ai-app/src/order-risk.js +28 -0
  50. package/examples/demo-ai-app/test/order-risk.test.mjs +24 -0
  51. package/package.json +11 -3
@@ -17,7 +17,7 @@ function gradeForScore(score) {
17
17
  return "F";
18
18
  }
19
19
 
20
- function buildMaintenanceSummary({ blockers, warnings, coverageGaps, invalidExceptions }) {
20
+ function buildMaintenanceSummary({ blockers, warnings, coverageGaps, invalidExceptions }) {
21
21
  const score = Math.max(
22
22
  0,
23
23
  Math.min(100, 100 - blockers.length * 25 - warnings.length * 3 - coverageGaps.length * 2 - invalidExceptions.length * 20),
@@ -31,10 +31,17 @@ function buildMaintenanceSummary({ blockers, warnings, coverageGaps, invalidExce
31
31
  coverageGaps: coverageGaps.length,
32
32
  invalidExceptions: invalidExceptions.length,
33
33
  },
34
- };
35
- }
36
-
37
- export function buildJsonReport({
34
+ };
35
+ }
36
+
37
+ function buildOverallStatus({ blockers, warnings, coverageGaps, invalidExceptions, userDecisionCount }) {
38
+ if (blockers.length || invalidExceptions.length) return "FAIL";
39
+ if (coverageGaps.length || userDecisionCount > 0) return "PASS_WITH_GAPS";
40
+ if (warnings.length) return "PASS_WITH_WARNINGS";
41
+ return "PASS";
42
+ }
43
+
44
+ export function buildJsonReport({
38
45
  root,
39
46
  mode,
40
47
  probe,
@@ -44,19 +51,26 @@ export function buildJsonReport({
44
51
  invalidExceptions = [],
45
52
  generatedAt = new Date().toISOString(),
46
53
  }) {
47
- const blockers = checks.filter((check) => check.blocking);
48
- const warnings = checks.filter((check) => !check.blocking && ["fail", "error", "missing", "skipped", "gap", "user_decision"].includes(statusKey(check.status)));
49
- const coverageGaps = checks.filter((check) => check.coverageGap || ["missing", "skipped", "gap"].includes(statusKey(check.status)));
50
- const exceptionUsage = checks.filter((check) => check.exception).map((check) => ({
51
- check: check.name,
52
- exception: check.exception,
53
- }));
54
-
55
- return {
56
- schemaVersion: 1,
57
- root,
58
- mode,
59
- passed: blockers.length === 0 && invalidExceptions.length === 0,
54
+ const blockers = checks.filter((check) => check.blocking);
55
+ const warnings = checks.filter((check) => !check.blocking && ["fail", "error", "missing", "skipped", "gap", "user_decision"].includes(statusKey(check.status)));
56
+ const coverageGaps = checks.filter((check) => check.coverageGap || ["missing", "skipped", "gap"].includes(statusKey(check.status)));
57
+ const userDecisionCount = checks.filter((check) => statusKey(check.status) === "user_decision").length + (audit?.userDecisions || []).length;
58
+ const exceptionUsage = checks.filter((check) => check.exception).map((check) => ({
59
+ check: {
60
+ checkId: check.checkId || null,
61
+ name: check.name,
62
+ group: check.group,
63
+ },
64
+ exception: check.exception,
65
+ }));
66
+ const overallStatus = buildOverallStatus({ blockers, warnings, coverageGaps, invalidExceptions, userDecisionCount });
67
+
68
+ return {
69
+ schemaVersion: 1,
70
+ root,
71
+ mode,
72
+ overallStatus,
73
+ passed: blockers.length === 0 && invalidExceptions.length === 0,
60
74
  blockerCount: blockers.length + invalidExceptions.length,
61
75
  warningCount: warnings.length,
62
76
  coverageGapCount: coverageGaps.length,
@@ -76,9 +90,10 @@ export function buildJsonReport({
76
90
  };
77
91
  }
78
92
 
79
- export function toMarkdown(report) {
80
- const lines = [];
81
- lines.push(`# Local Security Gate: ${report.passed ? "PASS" : "FAIL"}`);
93
+ export function toMarkdown(report) {
94
+ const lines = [];
95
+ const overallStatus = report.overallStatus || (report.passed ? "PASS" : "FAIL");
96
+ lines.push(`# Local Security Gate: ${overallStatus}`);
82
97
  lines.push("");
83
98
  lines.push(`Root: ${report.root}`);
84
99
  lines.push(`Mode: strict=${Boolean(report.mode?.strict)}, release=${Boolean(report.mode?.release)}, production=${Boolean(report.mode?.production)}`);
@@ -154,20 +169,29 @@ export function toMarkdown(report) {
154
169
  }
155
170
  lines.push("");
156
171
 
157
- lines.push("## Exceptions");
158
- if (!report.exceptions.used.length && !report.exceptions.invalid.length) lines.push("- None");
159
- for (const item of report.exceptions.used) {
160
- lines.push(`- ${item.exception.id}: applied to ${item.check}, expires ${item.exception.expires}`);
161
- }
172
+ lines.push("## Exceptions");
173
+ if (!report.exceptions.used.length && !report.exceptions.invalid.length) lines.push("- None");
174
+ for (const item of report.exceptions.used) {
175
+ const checkName = typeof item.check === "string" ? item.check : `${item.check.checkId || item.check.name} (${item.check.group})`;
176
+ lines.push(`- ${item.exception.id}: applied to ${checkName}, expires ${item.exception.expires}`);
177
+ }
162
178
  for (const item of report.exceptions.invalid) {
163
179
  lines.push(`- ${item.id || "(missing id)"}: invalid, ${item.reason}`);
164
180
  }
165
- lines.push("");
166
-
167
- lines.push("## Next Step");
168
- lines.push(report.passed ? "- Gate passed. Keep this command in CI before release." : "- Fix blocking checks or add narrow, owner-approved exceptions, then rerun the gate.");
169
- return lines.join("\n");
170
- }
181
+ lines.push("");
182
+
183
+ lines.push("## Next Step");
184
+ if (!report.passed) {
185
+ lines.push("- Fix blocking checks or add narrow, owner-approved exceptions, then rerun the gate.");
186
+ } else if (overallStatus === "PASS_WITH_GAPS") {
187
+ lines.push("- No blocking checks failed, but release-readiness gaps or user decisions remain. Fill evidence, accept risk explicitly, or enable block_on_coverage_gaps before release.");
188
+ } else if (overallStatus === "PASS_WITH_WARNINGS") {
189
+ lines.push("- Gate has no blockers or release-readiness gaps. Review warnings, then keep this command in CI before release.");
190
+ } else {
191
+ lines.push("- Gate passed without blockers, warnings, or release-readiness gaps. Keep this command in CI before release.");
192
+ }
193
+ return lines.join("\n");
194
+ }
171
195
 
172
196
  export function toSarif(report) {
173
197
  const rules = new Map();
@@ -0,0 +1,98 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1280" height="720" viewBox="0 0 1280 720" role="img" aria-labelledby="title desc">
2
+ <title id="title">AI Project Maintainer 90-second demo storyboard</title>
3
+ <desc id="desc">Animated storyboard showing project profile, broken before state, fixed tests, production gate, evidence report, and security workflow.</desc>
4
+ <defs>
5
+ <linearGradient id="bg" x1="0" x2="1" y1="0" y2="1">
6
+ <stop offset="0" stop-color="#0f172a"/>
7
+ <stop offset="0.55" stop-color="#111827"/>
8
+ <stop offset="1" stop-color="#0f766e"/>
9
+ </linearGradient>
10
+ <style>
11
+ .label { font: 700 48px system-ui, -apple-system, Segoe UI, sans-serif; fill: #f8fafc; }
12
+ .subtitle { font: 600 25px system-ui, -apple-system, Segoe UI, sans-serif; fill: #bae6fd; }
13
+ .body { font: 600 27px ui-monospace, SFMono-Regular, Consolas, monospace; fill: #e5e7eb; }
14
+ .muted { font: 600 21px system-ui, -apple-system, Segoe UI, sans-serif; fill: #94a3b8; }
15
+ .pass { fill: #34d399; }
16
+ .fail { fill: #fb7185; }
17
+ .gap { fill: #fbbf24; }
18
+ .panel { opacity: 0; animation: reveal 90s linear infinite; }
19
+ #s1 { animation-delay: 0s; }
20
+ #s2 { animation-delay: 15s; }
21
+ #s3 { animation-delay: 30s; }
22
+ #s4 { animation-delay: 45s; }
23
+ #s5 { animation-delay: 60s; }
24
+ #s6 { animation-delay: 75s; }
25
+ @keyframes reveal {
26
+ 0%, 15% { opacity: 1; }
27
+ 16%, 100% { opacity: 0; }
28
+ }
29
+ .bar { animation: progress 90s linear infinite; transform-origin: 120px 642px; }
30
+ @keyframes progress {
31
+ from { transform: scaleX(0); }
32
+ to { transform: scaleX(1); }
33
+ }
34
+ </style>
35
+ </defs>
36
+
37
+ <rect width="1280" height="720" fill="url(#bg)"/>
38
+ <rect x="72" y="56" width="1136" height="560" rx="28" fill="#111827" opacity="0.93" stroke="#334155" stroke-width="2"/>
39
+ <text x="120" y="124" class="label">AI Project Maintainer</text>
40
+ <text x="120" y="168" class="subtitle">90-second production-readiness demo for AI-coded projects</text>
41
+
42
+ <g id="s1" class="panel">
43
+ <text x="120" y="245" class="body">1. Start with project profile</text>
44
+ <text x="120" y="304" class="body">npx ai-project-maintainer init-audit .\examples\demo-ai-app</text>
45
+ <text x="120" y="365" class="muted">The maintainer declares project facts, business flows, evidence sources, and risk policy.</text>
46
+ <rect x="120" y="420" width="210" height="56" rx="12" fill="#0f766e"/>
47
+ <text x="146" y="456" class="body">PROFILE</text>
48
+ <rect x="360" y="420" width="210" height="56" rx="12" fill="#1d4ed8"/>
49
+ <text x="386" y="456" class="body">EVIDENCE</text>
50
+ <rect x="600" y="420" width="210" height="56" rx="12" fill="#6d28d9"/>
51
+ <text x="626" y="456" class="body">POLICY</text>
52
+ </g>
53
+
54
+ <g id="s2" class="panel">
55
+ <text x="120" y="245" class="body">2. Before state: behavior is broken</text>
56
+ <text x="120" y="304" class="body">node .\examples\demo-ai-app\scripts\create-before-state.mjs</text>
57
+ <text x="120" y="365" class="body fail">FAIL expensive orders require manual review</text>
58
+ <text x="120" y="410" class="body fail">FAIL orders cannot release without stock</text>
59
+ <text x="120" y="470" class="muted">No fake secrets are committed. The bad copy lives only under the OS temp directory.</text>
60
+ </g>
61
+
62
+ <g id="s3" class="panel">
63
+ <text x="120" y="245" class="body">3. Fix deterministic blockers</text>
64
+ <text x="120" y="304" class="body">npm test --prefix .\examples\demo-ai-app</text>
65
+ <text x="120" y="365" class="body pass">PASS checkout quote preserves customer-visible total</text>
66
+ <text x="120" y="410" class="body pass">PASS expensive orders require manual review</text>
67
+ <text x="120" y="455" class="body pass">PASS paid order release respects payment, stock, and risk</text>
68
+ </g>
69
+
70
+ <g id="s4" class="panel">
71
+ <text x="120" y="245" class="body">4. Run production gate</text>
72
+ <text x="120" y="304" class="body">npx ai-project-maintainer gate . --production --strict --release</text>
73
+ <text x="120" y="365" class="body pass">PASS tests, build, secrets, dependencies, SAST, CI checks</text>
74
+ <text x="120" y="410" class="body gap">GAP release approval, monitoring, logs, metrics, alerts</text>
75
+ <text x="120" y="470" class="muted">Checked failures block. Missing production evidence stays visible by default.</text>
76
+ </g>
77
+
78
+ <g id="s5" class="panel">
79
+ <text x="120" y="245" class="body">5. Produce evidence report</text>
80
+ <text x="120" y="304" class="body">reports/security-report.json</text>
81
+ <text x="120" y="349" class="body">reports/security-report.md</text>
82
+ <text x="120" y="394" class="body">reports/security-report.sarif</text>
83
+ <text x="120" y="439" class="body">reports/sbom.cdx.json</text>
84
+ <text x="120" y="500" class="muted">Codex can fix blockers, rerun, and leave maintainer decisions explicit.</text>
85
+ </g>
86
+
87
+ <g id="s6" class="panel">
88
+ <text x="120" y="245" class="body">6. Dogfood in GitHub Actions</text>
89
+ <text x="120" y="304" class="body pass">CI: green</text>
90
+ <text x="120" y="349" class="body pass">Security: green</text>
91
+ <text x="120" y="394" class="body">Gitleaks / Trivy / Semgrep / OSV / Syft / Grype / actionlint / zizmor</text>
92
+ <text x="120" y="470" class="subtitle">Let AI write fast. Make release readiness explicit.</text>
93
+ </g>
94
+
95
+ <rect x="120" y="642" width="1040" height="12" rx="6" fill="#334155"/>
96
+ <rect class="bar" x="120" y="642" width="1040" height="12" rx="6" fill="#38bdf8"/>
97
+ <text x="120" y="684" class="muted">project profile -> before failure -> fixed tests -> production gate -> evidence report -> CI security</text>
98
+ </svg>
Binary file
Binary file
@@ -0,0 +1,55 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1280" height="640" viewBox="0 0 1280 640" role="img" aria-labelledby="title desc">
2
+ <title id="title">AI Project Maintainer</title>
3
+ <desc id="desc">Production-readiness gate for AI-coded projects</desc>
4
+ <defs>
5
+ <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
6
+ <stop offset="0%" stop-color="#0f172a"/>
7
+ <stop offset="58%" stop-color="#111827"/>
8
+ <stop offset="100%" stop-color="#0f766e"/>
9
+ </linearGradient>
10
+ <linearGradient id="accent" x1="0" y1="0" x2="1" y2="0">
11
+ <stop offset="0%" stop-color="#38bdf8"/>
12
+ <stop offset="55%" stop-color="#2dd4bf"/>
13
+ <stop offset="100%" stop-color="#a7f3d0"/>
14
+ </linearGradient>
15
+ <marker id="arrow" markerWidth="12" markerHeight="12" refX="9" refY="6" orient="auto" markerUnits="strokeWidth">
16
+ <path d="M2 2 L10 6 L2 10 Z" fill="#5eead4"/>
17
+ </marker>
18
+ <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
19
+ <feDropShadow dx="0" dy="20" stdDeviation="24" flood-color="#000000" flood-opacity="0.35"/>
20
+ </filter>
21
+ </defs>
22
+ <rect width="1280" height="640" fill="url(#bg)"/>
23
+ <path d="M0 514 C210 448 322 575 520 501 C768 408 882 521 1280 390 L1280 640 L0 640 Z" fill="#0b1220" opacity="0.52"/>
24
+ <rect x="72" y="70" width="1136" height="500" rx="34" fill="#0b1020" opacity="0.72" filter="url(#shadow)"/>
25
+ <rect x="100" y="98" width="1080" height="444" rx="24" fill="#111827" stroke="#334155" stroke-width="2"/>
26
+
27
+ <text x="152" y="178" fill="#e5f7ff" font-family="Inter, Segoe UI, Arial, sans-serif" font-size="64" font-weight="800" letter-spacing="0">AI Project Maintainer</text>
28
+ <text x="154" y="236" fill="#bae6fd" font-family="Inter, Segoe UI, Arial, sans-serif" font-size="33" font-weight="650" letter-spacing="0">Production-readiness gate for AI-coded projects</text>
29
+ <rect x="154" y="278" width="972" height="4" rx="2" fill="url(#accent)"/>
30
+
31
+ <g font-family="Inter, Segoe UI, Arial, sans-serif" font-size="27" font-weight="750" text-anchor="middle">
32
+ <rect x="154" y="336" width="208" height="76" rx="18" fill="#172554" stroke="#38bdf8" stroke-width="2"/>
33
+ <text x="258" y="383" fill="#dbeafe">Project profile</text>
34
+
35
+ <line x1="386" y1="374" x2="424" y2="374" stroke="#5eead4" stroke-width="4" stroke-linecap="round" marker-end="url(#arrow)"/>
36
+
37
+ <rect x="448" y="336" width="178" height="76" rx="18" fill="#134e4a" stroke="#2dd4bf" stroke-width="2"/>
38
+ <text x="537" y="383" fill="#ccfbf1">Audit plan</text>
39
+
40
+ <line x1="650" y1="374" x2="688" y2="374" stroke="#5eead4" stroke-width="4" stroke-linecap="round" marker-end="url(#arrow)"/>
41
+
42
+ <rect x="712" y="336" width="150" height="76" rx="18" fill="#1e293b" stroke="#94a3b8" stroke-width="2"/>
43
+ <text x="787" y="383" fill="#e2e8f0">CI gate</text>
44
+
45
+ <line x1="886" y1="374" x2="924" y2="374" stroke="#5eead4" stroke-width="4" stroke-linecap="round" marker-end="url(#arrow)"/>
46
+
47
+ <rect x="948" y="336" width="216" height="76" rx="18" fill="#064e3b" stroke="#34d399" stroke-width="2"/>
48
+ <text x="1056" y="383" fill="#d1fae5">Evidence report</text>
49
+ </g>
50
+
51
+ <g font-family="Inter, Segoe UI, Arial, sans-serif" font-weight="650">
52
+ <text x="154" y="472" fill="#cbd5e1" font-size="24" letter-spacing="0">PASS / FAIL / WARN / GAP / N/A / USER_DECISION</text>
53
+ <text x="154" y="510" fill="#94a3b8" font-size="23" letter-spacing="0">Let AI write fast. Make release readiness explicit.</text>
54
+ </g>
55
+ </svg>
package/docs/DEMO.md CHANGED
@@ -1,74 +1,69 @@
1
1
  # Demo: From AI-Coded Repo to Production Audit Report
2
2
 
3
- This demo shows the core workflow without requiring any paid account or external API.
3
+ This demo uses the runnable project in `examples/demo-ai-app`. It does not require any paid account or external API.
4
4
 
5
- ## 1. Initialize The Project
5
+ Visual materials:
6
+
7
+ - [90-second GIF storyboard](../assets/demo-90s.gif)
8
+ - [90-second browser demo](demo-output/90-second-demo.html)
9
+ - [Before/after case](demo-output/before-after-case.md)
10
+
11
+ ## 1. Run The Healthy Demo App
6
12
 
7
13
  ```powershell
8
- npx ai-project-maintainer init "E:\my-project" --profile oss --ci github
14
+ npm test --prefix .\examples\demo-ai-app
15
+ npm run build --prefix .\examples\demo-ai-app
9
16
  ```
10
17
 
11
- This creates the local policy, exceptions file, GitHub Actions workflow, Dependabot config, and report directory.
18
+ The app is intentionally small: it quotes orders and decides whether paid orders can be released. The tests protect the business behavior that must not break.
12
19
 
13
- ## 2. Create Production Audit Intake
20
+ ## 2. Generate A Broken Before State
14
21
 
15
22
  ```powershell
16
- npx ai-project-maintainer init-audit "E:\my-project"
23
+ node .\examples\demo-ai-app\scripts\create-before-state.mjs
17
24
  ```
18
25
 
19
- This creates:
26
+ The command prints a temporary directory. Run this in that copied project:
20
27
 
21
- ```text
22
- .ai-maintainer/project-profile.yml
23
- .ai-maintainer/evidence-sources.yml
24
- .ai-maintainer/business-flows.yml
25
- .ai-maintainer/risk-policy.yml
26
- .ai-maintainer/threat-model.md
27
- .ai-maintainer/release-checklist.yml
28
- .ai-maintainer/incident-runbook.md
29
- .ai-maintainer/db-migration-policy.yml
30
- .ai-maintainer/observability-checklist.yml
28
+ ```powershell
29
+ npm test
31
30
  ```
32
31
 
33
- These files record project facts and evidence locations. They should not contain tokens, DSNs, passwords, or production secrets.
32
+ You should see the business tests fail. This is the "AI-coded project looks complete, but behavior is broken" stage. The broken copy is created under the OS temp directory, so the repository does not commit fake secrets or intentionally bad source files.
34
33
 
35
- ## 3. Generate An Audit Plan
34
+ ## 3. Run The Reproducible Demo Gate
36
35
 
37
36
  ```powershell
38
- npx ai-project-maintainer audit-plan "E:\my-project" --output reports/audit-plan.json
37
+ node .\examples\demo-ai-app\scripts\run-demo-gate.mjs
39
38
  ```
40
39
 
41
- Example output:
40
+ This script runs the real AI Project Maintainer gate with temporary scanner shims, so the sample report is stable even on a machine that has not installed Gitleaks, Trivy, Semgrep, OSV-Scanner, Syft, Grype, actionlint, zizmor, or Scorecard yet.
42
41
 
43
- ```text
44
- PASS Production audit intake is present.
45
- USER_DECISION Critical business flows must be declared.
46
- GAP No GitHub Actions workflow evidence detected.
47
- GAP No production release approval evidence declared.
48
- GAP Error monitoring evidence is missing.
49
- N/A No database surface detected or declared.
50
- ```
42
+ Expected result:
51
43
 
52
- The point is not to pretend the project is safe. The point is to make missing production evidence visible.
44
+ ```text
45
+ Local Security Gate: PASS_WITH_GAPS
46
+ Blocking Checks: None
47
+ Coverage Gaps:
48
+ - Production release approval
49
+ - Error monitoring
50
+ - Production logs
51
+ - Production metrics
52
+ - Production alerts
53
+ ```
54
+
55
+ See the generated-style [sample report](demo-output/security-report.md).
56
+ `PASS_WITH_GAPS` means deterministic blockers are clear, but production evidence still needs to be filled in or explicitly accepted before release.
53
57
 
54
- ## 4. Run The Production Gate
58
+ ## 4. Run The Real Gate
55
59
 
56
- ```powershell
57
- npx ai-project-maintainer gate "E:\my-project" --production --strict --release --output reports/security-report.json
58
- ```
59
-
60
- The report combines deterministic scanner output with production-readiness evidence:
60
+ After installing scanner CLIs, use the same command a real project would use:
61
61
 
62
- ```text
63
- PASS gitleaks secret scan
64
- PASS trivy filesystem scan
65
- PASS semgrep static scan
66
- GAP Error monitoring evidence is missing.
67
- GAP Production logs evidence is missing.
68
- USER_DECISION Critical business flows must be declared.
62
+ ```powershell
63
+ npx ai-project-maintainer gate .\examples\demo-ai-app --production --strict --release --output reports/security-report.json
69
64
  ```
70
65
 
71
- See [sample report](demo-output/security-report.md).
66
+ The point is not to pretend the project is perfect. The point is to make the checked failures and missing production evidence explicit before release.
72
67
 
73
68
  ## 5. Let Codex Fix Blockers
74
69
 
@@ -1,81 +1,75 @@
1
- # 演示:从 AI coding 项目到生产审查报告
1
+ # 演示:从 AI 写出的项目到生产审查报告
2
2
 
3
- 这个 demo 不需要付费账号,也不需要外部 API。
3
+ 这个演示使用仓库里的真实项目:`examples/demo-ai-app`。不需要付费账号,也不需要外部 API。
4
4
 
5
- ## 1. 初始化项目门禁
5
+ 演示素材:
6
+
7
+ - [90 秒 GIF 故事板](../assets/demo-90s.gif)
8
+ - [90 秒浏览器演示页](demo-output/90-second-demo.html)
9
+ - [before/after 案例](demo-output/before-after-case.md)
10
+
11
+ ## 1. 跑健康态项目
6
12
 
7
13
  ```powershell
8
- npx ai-project-maintainer init "E:\我的项目" --profile oss --ci github
14
+ npm test --prefix .\examples\demo-ai-app
15
+ npm run build --prefix .\examples\demo-ai-app
9
16
  ```
10
17
 
11
- 这会生成本地策略、例外文件、GitHub Actions、Dependabot 配置和报告目录。
18
+ 这个项目很小:它负责订单报价和订单释放判断。测试覆盖的是不能被 AI 修改坏的核心业务行为。
12
19
 
13
- ## 2. 生成生产审查画像
20
+ ## 2. 生成坏掉的 before 状态
14
21
 
15
22
  ```powershell
16
- npx ai-project-maintainer init-audit "E:\我的项目"
23
+ node .\examples\demo-ai-app\scripts\create-before-state.mjs
17
24
  ```
18
25
 
19
- 这会生成:
26
+ 命令会输出一个临时目录。进入那个复制出来的项目后运行:
20
27
 
21
- ```text
22
- .ai-maintainer/project-profile.yml
23
- .ai-maintainer/evidence-sources.yml
24
- .ai-maintainer/business-flows.yml
25
- .ai-maintainer/risk-policy.yml
26
- .ai-maintainer/threat-model.md
27
- .ai-maintainer/release-checklist.yml
28
- .ai-maintainer/incident-runbook.md
29
- .ai-maintainer/db-migration-policy.yml
30
- .ai-maintainer/observability-checklist.yml
28
+ ```powershell
29
+ npm test
31
30
  ```
32
31
 
33
- 这些文件只记录项目事实和证据来源,不应该写 token、DSN、密码或生产 secret
32
+ 你会看到业务测试失败。这代表“AI 写出来看起来完整,但关键行为已经坏了”的阶段。坏代码只存在于系统临时目录,仓库不会提交假 secret 或故意脆弱的源码。
34
33
 
35
- ## 3. 生成审计计划
34
+ ## 3. 跑可复现的 demo gate
36
35
 
37
36
  ```powershell
38
- npx ai-project-maintainer audit-plan "E:\我的项目" --output reports/audit-plan.json
37
+ node .\examples\demo-ai-app\scripts\run-demo-gate.mjs
39
38
  ```
40
39
 
41
- 示例输出:
40
+ 这个脚本会运行真实的 AI Project Maintainer gate,但会临时创建扫描器 mock,所以即使本机还没安装 Gitleaks、Trivy、Semgrep、OSV-Scanner、Syft、Grype、actionlint、zizmor、Scorecard,也能稳定生成示例报告。
41
+
42
+ 预期结果:
42
43
 
43
44
  ```text
44
- PASS 生产审查画像已存在。
45
- USER_DECISION 需要项目负责人声明核心业务流程。
46
- GAP 没有 GitHub Actions 证据。
47
- GAP 没有生产发布审批证据。
48
- GAP 缺少错误监控证据。
49
- N/A 没有检测到数据库。
45
+ Local Security Gate: PASS_WITH_GAPS
46
+ Blocking Checks: None
47
+ Coverage Gaps:
48
+ - Production release approval
49
+ - Error monitoring
50
+ - Production logs
51
+ - Production metrics
52
+ - Production alerts
50
53
  ```
51
54
 
52
- 重点不是假装项目安全,而是把“缺少哪些生产证据”明确写出来。
55
+ 示例报告见:[sample report](demo-output/security-report.md)。
53
56
 
54
- ## 4. 运行生产级门禁
57
+ ## 4. 跑真实 gate
55
58
 
56
- ```powershell
57
- npx ai-project-maintainer gate "E:\我的项目" --production --strict --release --output reports/security-report.json
58
- ```
59
-
60
- 报告会把确定性扫描结果和生产准备度证据合在一起:
59
+ 安装扫描器 CLI 后,可以用真实项目同款命令:
61
60
 
62
- ```text
63
- PASS gitleaks secret scan
64
- PASS trivy filesystem scan
65
- PASS semgrep static scan
66
- GAP 缺少错误监控证据。
67
- GAP 缺少生产日志证据。
68
- USER_DECISION 需要声明核心业务流程。
61
+ ```powershell
62
+ npx ai-project-maintainer gate .\examples\demo-ai-app --production --strict --release --output reports/security-report.json
69
63
  ```
70
64
 
71
- 查看 [示例报告](demo-output/security-report.md)。
65
+ 这个工具不是为了假装项目完美,而是把已经检查失败的项和缺少的生产证据在发布前明确展示出来。
72
66
 
73
67
  ## 5. 让 Codex 修阻断项
74
68
 
75
- Codex 说:
69
+ 可以这样要求 Codex
76
70
 
77
71
  ```text
78
- $ai-project-maintainer 对这个项目运行生产级门禁,修复阻断项,然后重新运行直到通过。
72
+ $ai-project-maintainer run the production gate for this project, fix blockers, and rerun until it passes.
79
73
  ```
80
74
 
81
- Codex 可以处理确定性的阻断项。项目负责人仍然负责核心业务流程、风险接受和生产证据判断。
75
+ Codex 适合处理确定性的阻断项。维护者仍然负责业务决策、风险接受和生产证据确认。
@@ -31,17 +31,17 @@ ai-agents
31
31
 
32
32
  Upload a social preview image in repository settings.
33
33
 
34
- Recommended source:
35
-
36
- ```text
37
- assets/social-preview.png
38
- ```
39
-
40
- Editable source:
41
-
42
- ```text
43
- assets/social-preview.svg
44
- ```
34
+ Recommended source:
35
+
36
+ ```text
37
+ assets/social-preview.png
38
+ ```
39
+
40
+ Editable source:
41
+
42
+ ```text
43
+ assets/social-preview.svg
44
+ ```
45
45
 
46
46
  If GitHub asks for PNG/JPG, export the SVG to PNG at `1280x640`.
47
47
 
@@ -58,7 +58,7 @@ warn_on:
58
58
  ```yaml
59
59
  exceptions:
60
60
  - id: "example-dev-only-vuln"
61
- check: "npm audit"
61
+ check: "package-audit"
62
62
  reason: "dev-only transitive dependency, not shipped"
63
63
  expires: "2026-09-01"
64
64
  owner: "repo-owner"