shipproof 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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.es.md +107 -0
  3. package/README.md +128 -0
  4. package/dist/src/analyze.d.ts +4 -0
  5. package/dist/src/analyze.d.ts.map +1 -0
  6. package/dist/src/analyze.js +43 -0
  7. package/dist/src/analyze.js.map +1 -0
  8. package/dist/src/checks/readiness.d.ts +8 -0
  9. package/dist/src/checks/readiness.d.ts.map +1 -0
  10. package/dist/src/checks/readiness.js +147 -0
  11. package/dist/src/checks/readiness.js.map +1 -0
  12. package/dist/src/checks/secrets.d.ts +6 -0
  13. package/dist/src/checks/secrets.d.ts.map +1 -0
  14. package/dist/src/checks/secrets.js +49 -0
  15. package/dist/src/checks/secrets.js.map +1 -0
  16. package/dist/src/cli.d.ts +3 -0
  17. package/dist/src/cli.d.ts.map +1 -0
  18. package/dist/src/cli.js +97 -0
  19. package/dist/src/cli.js.map +1 -0
  20. package/dist/src/files.d.ts +9 -0
  21. package/dist/src/files.d.ts.map +1 -0
  22. package/dist/src/files.js +120 -0
  23. package/dist/src/files.js.map +1 -0
  24. package/dist/src/index.d.ts +5 -0
  25. package/dist/src/index.d.ts.map +1 -0
  26. package/dist/src/index.js +4 -0
  27. package/dist/src/index.js.map +1 -0
  28. package/dist/src/reporters/json.d.ts +3 -0
  29. package/dist/src/reporters/json.d.ts.map +1 -0
  30. package/dist/src/reporters/json.js +4 -0
  31. package/dist/src/reporters/json.js.map +1 -0
  32. package/dist/src/reporters/terminal.d.ts +3 -0
  33. package/dist/src/reporters/terminal.d.ts.map +1 -0
  34. package/dist/src/reporters/terminal.js +50 -0
  35. package/dist/src/reporters/terminal.js.map +1 -0
  36. package/dist/src/types.d.ts +32 -0
  37. package/dist/src/types.d.ts.map +1 -0
  38. package/dist/src/types.js +2 -0
  39. package/dist/src/types.js.map +1 -0
  40. package/docs/demo.svg +23 -0
  41. package/docs/shipproof.svg +15 -0
  42. package/package.json +51 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CalvaryBloom
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.es.md ADDED
@@ -0,0 +1,107 @@
1
+ <p align="center">
2
+ <img src="docs/shipproof.svg" alt="ShipProof — comprueba antes de publicar" width="620">
3
+ </p>
4
+
5
+ <p align="center">
6
+ Comprobaciones sin configuración para saber si un proyecto creado con ayuda de IA está listo para publicarse.
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="README.md">English</a> · Español
11
+ </p>
12
+
13
+ ShipProof da a tu proyecto una puntuación clara y explica qué debes corregir antes de hacerlo público. Funciona localmente, ofrece resultados deterministas y busca esos detalles poco vistosos que suelen quedar pendientes en el código generado con IA.
14
+
15
+ <p align="center">
16
+ <img src="docs/demo.svg" alt="Terminal de ShipProof mostrando una puntuación de preparación de 92 sobre 100" width="860">
17
+ </p>
18
+
19
+ ## ¿Por qué ShipProof?
20
+
21
+ La IA puede generar una aplicación convincente en pocos minutos. Eso no significa que esté lista para usuarios o colaboradores: las pruebas pueden ser simuladas, puede haber credenciales en un archivo de entorno, las instalaciones quizá no sean reproducibles y el repositorio puede carecer de licencia o política de seguridad.
22
+
23
+ ShipProof convierte esa revisión final imprecisa en un comando repetible:
24
+
25
+ ```bash
26
+ npx shipproof
27
+ ```
28
+
29
+ Actualmente reconoce proyectos Node.js, Python, Rust y Go. Nunca ejecuta comandos del proyecto inspeccionado ni sube su código fuente.
30
+
31
+ ## Qué comprueba
32
+
33
+ | Área | Ejemplos |
34
+ | --- | --- |
35
+ | Proyecto | Manifiestos reconocidos y metadatos válidos |
36
+ | Calidad | Comandos de pruebas, lint, tipos y compilación |
37
+ | Reproducibilidad | Archivos de bloqueo y dependencias fijadas |
38
+ | Seguridad | Nombres de archivo sensibles y patrones conservadores de credenciales |
39
+ | Documentación | README, licencia e instrucciones para colaborar |
40
+ | Automatización | Flujos de GitHub Actions |
41
+ | Comunidad | Normas de conducta, contribución y seguridad |
42
+
43
+ El resultado indica dónde está el posible problema sin mostrar el valor de una credencial. ShipProof es una comprobación previa, no sustituye a un escáner de seguridad especializado ni a la revisión humana.
44
+
45
+ ## Uso
46
+
47
+ Requiere Node.js 22.13 o posterior.
48
+
49
+ ```bash
50
+ # Analizar el directorio actual
51
+ npx shipproof
52
+
53
+ # Analizar otro directorio
54
+ npx shipproof ./mi-proyecto
55
+
56
+ # Generar un informe JSON
57
+ npx shipproof --json
58
+
59
+ # Informar sin devolver un código de error
60
+ npx shipproof --no-fail
61
+ ```
62
+
63
+ Por defecto, ShipProof termina con código `1` si encuentra al menos un problema bloqueante y con código `2` cuando la entrada no es válida. Los avisos reducen la puntuación, pero no cambian el código de salida.
64
+
65
+ ## Puntuación
66
+
67
+ Cada comprobación aplicable tiene un peso explícito. Un resultado correcto obtiene todo el peso, un aviso obtiene la mitad y un fallo no obtiene puntos.
68
+
69
+ | Puntuación | Significado |
70
+ | ---: | --- |
71
+ | 90–100 | Listo para publicar |
72
+ | 75–89 | Casi listo |
73
+ | 50–74 | Necesita trabajo |
74
+ | 0–49 | No está listo |
75
+
76
+ La puntuación es explicable, pero no garantiza que el software sea correcto o seguro.
77
+
78
+ ## Desarrollo local
79
+
80
+ ```bash
81
+ git clone https://github.com/CalvaryBloom/shipproof.git
82
+ cd shipproof
83
+ pnpm install
84
+ pnpm test
85
+ node dist/src/cli.js . --no-fail
86
+ ```
87
+
88
+ ShipProof no tiene dependencias en tiempo de ejecución. TypeScript y las declaraciones de Node.js solo se usan durante el desarrollo.
89
+
90
+ ## Próximos objetivos
91
+
92
+ - Acción de GitHub con un resumen compacto para cada pull request.
93
+ - Umbrales configurables mediante `shipproof.config.json`.
94
+ - Comprobaciones más profundas para Python, Rust y Go.
95
+ - Salida SARIF compatible con el análisis de código de GitHub.
96
+ - Catálogo público de comprobaciones y falsos positivos conocidos.
97
+ - Publicación automatizada y con procedencia verificable para las próximas versiones.
98
+
99
+ ## Colaborar
100
+
101
+ Las contribuciones son bienvenidas. Lee [CONTRIBUTING.md](CONTRIBUTING.md) antes de proponer una nueva comprobación. Los cambios deben ser deterministas, locales, seguros y transparentes acerca de sus posibles falsos positivos.
102
+
103
+ Comunica cualquier vulnerabilidad mediante el [sistema privado de GitHub](https://github.com/CalvaryBloom/shipproof/security/advisories/new), nunca en una incidencia pública.
104
+
105
+ ## Licencia
106
+
107
+ [MIT](LICENSE) © 2026 CalvaryBloom
package/README.md ADDED
@@ -0,0 +1,128 @@
1
+ <p align="center">
2
+ <img src="docs/shipproof.svg" alt="ShipProof — know before you ship" width="620">
3
+ </p>
4
+
5
+ <p align="center">
6
+ Zero-config release readiness checks for AI-assisted projects.
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://github.com/CalvaryBloom/shipproof/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/CalvaryBloom/shipproof/actions/workflows/ci.yml/badge.svg"></a>
11
+ <a href="LICENSE"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-22c55e"></a>
12
+ <img alt="Node 22.13+" src="https://img.shields.io/badge/node-%3E%3D22.13-339933">
13
+ </p>
14
+
15
+ <p align="center">
16
+ English · <a href="README.es.md">Español</a>
17
+ </p>
18
+
19
+ ShipProof gives a project one clear readiness score and explains what to fix before it becomes public. It is fast, local, deterministic, and designed to catch the unglamorous gaps that AI-generated code often leaves behind.
20
+
21
+ <p align="center">
22
+ <img src="docs/demo.svg" alt="ShipProof terminal output showing a 92 out of 100 readiness score" width="860">
23
+ </p>
24
+
25
+ ## Why ShipProof?
26
+
27
+ AI can create a convincing application in minutes. That does not mean the result is ready for users or contributors. Tests may be placeholders, credentials may be sitting in an environment file, builds may not be reproducible, and the repository may have no license or security policy.
28
+
29
+ ShipProof turns that vague final review into a repeatable command:
30
+
31
+ ```bash
32
+ npx shipproof
33
+ ```
34
+
35
+ It currently recognizes Node.js, Python, Rust, and Go projects. It never executes commands from the project being inspected and never uploads source code.
36
+
37
+ ## What it checks
38
+
39
+ | Area | Examples |
40
+ | --- | --- |
41
+ | Project | Recognized manifests and valid package metadata |
42
+ | Quality | Test, lint, type-check, and build commands |
43
+ | Reproducibility | Lockfiles and pinned dependency manifests |
44
+ | Security | Sensitive filenames and conservative credential patterns |
45
+ | Documentation | README depth, license, and contribution guidance |
46
+ | Automation | GitHub Actions workflows |
47
+ | Community | Conduct, contribution, and security policies |
48
+
49
+ The output includes suggestions rather than exposing any matched secret value. ShipProof is a preflight assistant, not a replacement for dedicated security scanners or human review.
50
+
51
+ ## Usage
52
+
53
+ Requires Node.js 22.13 or newer.
54
+
55
+ ```bash
56
+ # Inspect the current directory
57
+ npx shipproof
58
+
59
+ # Inspect another directory
60
+ npx shipproof ./my-project
61
+
62
+ # Produce machine-readable output
63
+ npx shipproof --json
64
+
65
+ # Report findings without a failing exit code
66
+ npx shipproof --no-fail
67
+ ```
68
+
69
+ ### Options
70
+
71
+ ```text
72
+ shipproof [path] [options]
73
+
74
+ --json Print machine-readable JSON
75
+ --no-color Disable ANSI colors
76
+ --no-fail Exit with code 0 even when blocking issues are found
77
+ -h, --help Show help
78
+ -v, --version
79
+ Show the version
80
+ ```
81
+
82
+ By default, ShipProof exits with code `1` when at least one blocking issue is found and `2` for invalid input. This makes it useful in continuous integration. Warnings lower the score but do not change the exit code.
83
+
84
+ ## Scoring
85
+
86
+ Each applicable check has an explicit weight. Passing earns the full weight, a warning earns half, and a failure earns none.
87
+
88
+ | Score | Meaning |
89
+ | ---: | --- |
90
+ | 90–100 | Ready to ship |
91
+ | 75–89 | Almost ready |
92
+ | 50–74 | Needs work |
93
+ | 0–49 | Not ready |
94
+
95
+ The score is intentionally explainable. It is not a promise that software is correct or secure.
96
+
97
+ ## Local development
98
+
99
+ ```bash
100
+ git clone https://github.com/CalvaryBloom/shipproof.git
101
+ cd shipproof
102
+ pnpm install
103
+ pnpm test
104
+ node dist/src/cli.js . --no-fail
105
+ ```
106
+
107
+ ShipProof has no runtime dependencies. TypeScript and its Node.js declarations are development-only dependencies.
108
+
109
+ ## Roadmap
110
+
111
+ - GitHub Action with a compact pull-request summary.
112
+ - Configurable thresholds through `shipproof.config.json`.
113
+ - Deeper Python, Rust, and Go checks.
114
+ - SARIF output for GitHub code scanning.
115
+ - A public check catalog with evidence and false-positive guidance.
116
+ - Automated trusted publishing with provenance for future releases.
117
+
118
+ The best roadmap item is the one backed by a real repository and a reproducible failure. Please use the feature request template to share one.
119
+
120
+ ## Contributing
121
+
122
+ Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) before proposing a check. New checks should remain deterministic, local, safe, and clear about false positives.
123
+
124
+ Please report vulnerabilities through [private vulnerability reporting](https://github.com/CalvaryBloom/shipproof/security/advisories/new), not a public issue.
125
+
126
+ ## License
127
+
128
+ [MIT](LICENSE) © 2026 CalvaryBloom
@@ -0,0 +1,4 @@
1
+ import type { AnalysisResult } from "./types.js";
2
+ export declare const SHIPPROOF_VERSION = "0.1.0";
3
+ export declare function analyzeProject(target: string): AnalysisResult;
4
+ //# sourceMappingURL=analyze.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/analyze.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAA0B,MAAM,YAAY,CAAC;AAEzE,eAAO,MAAM,iBAAiB,UAAU,CAAC;AAgBzC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CA2B7D"}
@@ -0,0 +1,43 @@
1
+ import { resolve } from "node:path";
2
+ import { runReadinessChecks } from "./checks/readiness.js";
3
+ export const SHIPPROOF_VERSION = "0.1.0";
4
+ const scoreFactors = {
5
+ pass: 1,
6
+ warn: 0.5,
7
+ fail: 0,
8
+ info: 1,
9
+ };
10
+ function readinessFor(score) {
11
+ if (score >= 90)
12
+ return "ready";
13
+ if (score >= 75)
14
+ return "close";
15
+ if (score >= 50)
16
+ return "work-needed";
17
+ return "not-ready";
18
+ }
19
+ export function analyzeProject(target) {
20
+ const startedAt = Date.now();
21
+ const root = resolve(target);
22
+ const { project, checks } = runReadinessChecks(root);
23
+ const scorable = checks.filter((check) => check.weight > 0);
24
+ const totalWeight = scorable.reduce((total, check) => total + check.weight, 0);
25
+ const earnedWeight = scorable.reduce((total, check) => total + check.weight * scoreFactors[check.status], 0);
26
+ const score = totalWeight === 0 ? 0 : Math.round((earnedWeight / totalWeight) * 100);
27
+ return {
28
+ version: SHIPPROOF_VERSION,
29
+ analyzedAt: new Date().toISOString(),
30
+ durationMs: Date.now() - startedAt,
31
+ project,
32
+ score,
33
+ readiness: readinessFor(score),
34
+ summary: {
35
+ passed: checks.filter((check) => check.status === "pass").length,
36
+ warnings: checks.filter((check) => check.status === "warn").length,
37
+ failed: checks.filter((check) => check.status === "fail").length,
38
+ informational: checks.filter((check) => check.status === "info").length,
39
+ },
40
+ checks,
41
+ };
42
+ }
43
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC;AAEzC,MAAM,YAAY,GAAgC;IAChD,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;CACR,CAAC;AAEF,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,OAAO,CAAC;IAChC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,OAAO,CAAC;IAChC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,aAAa,CAAC;IACtC,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/E,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAClC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,EACnE,CAAC,CACF,CAAC;IACF,MAAM,KAAK,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC;IAErF,OAAO;QACL,OAAO,EAAE,iBAAiB;QAC1B,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;QAClC,OAAO;QACP,KAAK;QACL,SAAS,EAAE,YAAY,CAAC,KAAK,CAAC;QAC9B,OAAO,EAAE;YACP,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM;YAChE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM;YAClE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM;YAChE,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM;SACxE;QACD,MAAM;KACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { CheckResult, ProjectInfo } from "../types.js";
2
+ interface ReadinessChecks {
3
+ project: ProjectInfo;
4
+ checks: CheckResult[];
5
+ }
6
+ export declare function runReadinessChecks(root: string): ReadinessChecks;
7
+ export {};
8
+ //# sourceMappingURL=readiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readiness.d.ts","sourceRoot":"","sources":["../../../src/checks/readiness.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAW5D,UAAU,eAAe;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AA+ID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CA6HhE"}
@@ -0,0 +1,147 @@
1
+ import { basename, join } from "node:path";
2
+ import { listFiles, pathExists, readJson, readUtf8 } from "../files.js";
3
+ import { findPotentialSecrets } from "./secrets.js";
4
+ function result(id, title, status, message, weight, suggestion) {
5
+ return suggestion === undefined
6
+ ? { id, title, status, message, weight }
7
+ : { id, title, status, message, weight, suggestion };
8
+ }
9
+ function findRootFile(files, names) {
10
+ const wanted = new Set(names.map((name) => name.toLowerCase()));
11
+ return files.find((file) => !file.includes("/") && wanted.has(file.toLowerCase()));
12
+ }
13
+ function detectEcosystems(root) {
14
+ const ecosystems = [];
15
+ if (pathExists(root, "package.json"))
16
+ ecosystems.push("Node.js");
17
+ if (pathExists(root, "pyproject.toml") ||
18
+ pathExists(root, "requirements.txt") ||
19
+ pathExists(root, "Pipfile")) {
20
+ ecosystems.push("Python");
21
+ }
22
+ if (pathExists(root, "Cargo.toml"))
23
+ ecosystems.push("Rust");
24
+ if (pathExists(root, "go.mod"))
25
+ ecosystems.push("Go");
26
+ return ecosystems;
27
+ }
28
+ function hasUsefulScript(scripts, names) {
29
+ if (!scripts)
30
+ return false;
31
+ return names.some((name) => {
32
+ const command = scripts[name]?.trim();
33
+ return command !== undefined && command.length > 0 && !/no tests?|not implemented/i.test(command);
34
+ });
35
+ }
36
+ function lockfileCheck(root, ecosystems) {
37
+ const expected = new Map([
38
+ ["Node.js", ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock", "bun.lockb"]],
39
+ ["Python", ["uv.lock", "poetry.lock", "Pipfile.lock", "requirements.txt"]],
40
+ ["Rust", ["Cargo.lock"]],
41
+ ["Go", ["go.sum"]],
42
+ ]);
43
+ if (ecosystems.length === 0) {
44
+ return result("lockfile", "Reproducible dependencies", "info", "No supported dependency ecosystem was detected.", 0);
45
+ }
46
+ const missing = ecosystems.filter((ecosystem) => {
47
+ const candidates = expected.get(ecosystem) ?? [];
48
+ return !candidates.some((file) => pathExists(root, file));
49
+ });
50
+ if (missing.length === 0) {
51
+ return result("lockfile", "Reproducible dependencies", "pass", "A dependency lock or pinned manifest is present.", 8);
52
+ }
53
+ return result("lockfile", "Reproducible dependencies", "warn", `Missing reproducibility files for: ${missing.join(", ")}.`, 8, "Commit the lockfile produced by your package manager.");
54
+ }
55
+ function scriptChecks(root, ecosystems, packageJson) {
56
+ if (!ecosystems.includes("Node.js")) {
57
+ if (ecosystems.includes("Rust") || ecosystems.includes("Go")) {
58
+ return [
59
+ result("test-command", "Test command", "pass", "The ecosystem provides a conventional test command.", 8),
60
+ result("quality-command", "Quality command", "pass", "The ecosystem provides conventional formatting and analysis commands.", 7),
61
+ ];
62
+ }
63
+ if (ecosystems.includes("Python")) {
64
+ const pyproject = readUtf8(join(root, "pyproject.toml")) ?? "";
65
+ const hasTest = /pytest|unittest/i.test(pyproject) || pathExists(root, "tests") || pathExists(root, "test");
66
+ const hasQuality = /ruff|mypy|pyright|flake8|black/i.test(pyproject);
67
+ return [
68
+ result("test-command", "Test setup", hasTest ? "pass" : "warn", hasTest ? "A Python test setup was detected." : "No Python test setup was detected.", 8, hasTest ? undefined : "Add a tests/ directory and configure pytest or unittest."),
69
+ result("quality-command", "Quality setup", hasQuality ? "pass" : "warn", hasQuality ? "A Python quality tool was detected." : "No Python formatter, linter, or type checker was detected.", 7, hasQuality ? undefined : "Configure a tool such as Ruff, mypy, or Pyright."),
70
+ ];
71
+ }
72
+ return [result("commands", "Project commands", "info", "Command checks are not available for this project type yet.", 0)];
73
+ }
74
+ const scripts = packageJson?.scripts;
75
+ const test = hasUsefulScript(scripts, ["test"]);
76
+ const quality = hasUsefulScript(scripts, ["lint", "check", "typecheck", "type-check"]);
77
+ const build = hasUsefulScript(scripts, ["build"]);
78
+ return [
79
+ result("test-command", "Test command", test ? "pass" : "fail", test ? "package.json defines a usable test script." : "package.json has no usable test script.", 8, test ? undefined : "Add a test script that runs your automated test suite."),
80
+ result("quality-command", "Quality command", quality ? "pass" : "warn", quality ? "A lint, check, or type-check script is available." : "No lint, check, or type-check script is available.", 7, quality ? undefined : "Add a lint or type-check script so contributors can verify changes."),
81
+ result("build-command", "Build command", build ? "pass" : "warn", build ? "package.json defines a build script." : "package.json has no build script.", 5, build ? undefined : "Add a build script when the project produces compiled output."),
82
+ ];
83
+ }
84
+ export function runReadinessChecks(root) {
85
+ const files = listFiles(root);
86
+ const ecosystems = detectEcosystems(root);
87
+ const packagePath = join(root, "package.json");
88
+ const hasPackageJson = pathExists(root, "package.json");
89
+ const packageJson = hasPackageJson ? readJson(packagePath) : undefined;
90
+ const project = {
91
+ name: packageJson?.name ?? basename(root),
92
+ path: root,
93
+ ecosystems,
94
+ };
95
+ const checks = [];
96
+ checks.push(ecosystems.length > 0
97
+ ? result("project-detected", "Project detected", "pass", `Detected: ${ecosystems.join(", ")}.`, 8)
98
+ : result("project-detected", "Project detected", "fail", "No supported project manifest was found.", 8, "Add package.json, pyproject.toml, Cargo.toml, or go.mod."));
99
+ if (hasPackageJson && packageJson === undefined) {
100
+ checks.push(result("package-json", "Valid package.json", "fail", "package.json could not be parsed as JSON.", 8, "Fix the JSON syntax before publishing."));
101
+ }
102
+ const readme = findRootFile(files, ["README.md", "README.mdx", "README.rst"]);
103
+ const readmeContent = readme ? readUtf8(join(root, readme)) ?? "" : "";
104
+ checks.push(!readme
105
+ ? result("readme", "README", "fail", "No root README was found.", 10, "Explain the problem, installation, usage, and contribution path.")
106
+ : readmeContent.trim().length < 400
107
+ ? result("readme", "README", "warn", `${readme} exists but is very short.`, 10, "Add installation, examples, limitations, and a roadmap.")
108
+ : result("readme", "README", "pass", `${readme} gives the project a useful front page.`, 10));
109
+ const license = findRootFile(files, ["LICENSE", "LICENSE.md", "LICENSE.txt", "COPYING"]);
110
+ checks.push(license
111
+ ? result("license", "License", "pass", `${license} is present.`, 7)
112
+ : result("license", "License", "fail", "No license file was found.", 7, "Choose an open-source license and add it at the repository root."));
113
+ checks.push(pathExists(root, ".gitignore")
114
+ ? result("gitignore", ".gitignore", "pass", "Generated files can be kept out of version control.", 5)
115
+ : result("gitignore", ".gitignore", "warn", "No .gitignore file was found.", 5, "Add ignores for dependencies, builds, secrets, and editor files."));
116
+ checks.push(lockfileCheck(root, ecosystems));
117
+ checks.push(...scriptChecks(root, ecosystems, packageJson));
118
+ const workflows = files.filter((file) => /^\.github\/workflows\/[^/]+\.ya?ml$/i.test(file));
119
+ checks.push(workflows.length > 0
120
+ ? result("ci", "Continuous integration", "pass", `Found ${workflows.length} GitHub Actions workflow${workflows.length === 1 ? "" : "s"}.`, 10)
121
+ : result("ci", "Continuous integration", "warn", "No GitHub Actions workflow was found.", 10, "Run tests and quality checks on pushes and pull requests."));
122
+ if (packageJson) {
123
+ const missingMetadata = [
124
+ packageJson.description?.trim() ? undefined : "description",
125
+ packageJson.license?.trim() ? undefined : "license",
126
+ packageJson.repository ? undefined : "repository",
127
+ ].filter((field) => field !== undefined);
128
+ checks.push(missingMetadata.length === 0
129
+ ? result("package-metadata", "Package metadata", "pass", "Description, license, and repository metadata are set.", 5)
130
+ : result("package-metadata", "Package metadata", "warn", `Missing package metadata: ${missingMetadata.join(", ")}.`, 5, "Complete the metadata so registries and tools can describe the project."));
131
+ }
132
+ const communityFiles = ["CONTRIBUTING.md", "CODE_OF_CONDUCT.md", "SECURITY.md"];
133
+ const missingCommunityFiles = communityFiles.filter((file) => !pathExists(root, file));
134
+ checks.push(missingCommunityFiles.length === 0
135
+ ? result("community", "Community health", "pass", "Contribution, conduct, and security guidance are present.", 5)
136
+ : result("community", "Community health", "warn", `Missing: ${missingCommunityFiles.join(", ")}.`, 5, "Add lightweight guidance before inviting contributors."));
137
+ const secretFindings = findPotentialSecrets(root);
138
+ if (secretFindings.length === 0) {
139
+ checks.push(result("secrets", "Secret exposure", "pass", "No common secret patterns or sensitive filenames were detected.", 14));
140
+ }
141
+ else {
142
+ const paths = [...new Set(secretFindings.map((finding) => finding.path))];
143
+ checks.push(result("secrets", "Secret exposure", "fail", `Potential secrets found in ${paths.length} file${paths.length === 1 ? "" : "s"}: ${paths.slice(0, 4).join(", ")}${paths.length > 4 ? ", …" : ""}.`, 14, "Remove the files from version control, rotate exposed credentials, and provide redacted examples instead."));
144
+ }
145
+ return { project, checks };
146
+ }
147
+ //# sourceMappingURL=readiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readiness.js","sourceRoot":"","sources":["../../../src/checks/readiness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface SecretFinding {
2
+ path: string;
3
+ kind: string;
4
+ }
5
+ export declare function findPotentialSecrets(root: string): SecretFinding[];
6
+ //# sourceMappingURL=secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../../src/checks/secrets.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAoCD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAqBlE"}
@@ -0,0 +1,49 @@
1
+ import { basename, join } from "node:path";
2
+ import { isSmallTextFile, listFiles, readUtf8 } from "../files.js";
3
+ const safeEnvironmentSuffixes = [".example", ".sample", ".template"];
4
+ function sensitiveFilename(path) {
5
+ const name = basename(path).toLowerCase();
6
+ if (name === ".env" ||
7
+ (name.startsWith(".env.") &&
8
+ !safeEnvironmentSuffixes.some((suffix) => name.endsWith(suffix)))) {
9
+ return "environment file";
10
+ }
11
+ if (["id_rsa", "id_ed25519", "credentials.json", "service-account.json"].includes(name)) {
12
+ return "credential file";
13
+ }
14
+ if ([".pem", ".p12", ".pfx"].some((extension) => name.endsWith(extension))) {
15
+ return "key or certificate file";
16
+ }
17
+ return undefined;
18
+ }
19
+ const contentPatterns = [
20
+ { kind: "GitHub token", pattern: /\bgh[pousr]_[A-Za-z0-9_]{20,}\b/ },
21
+ { kind: "OpenAI-style key", pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/ },
22
+ { kind: "AWS access key", pattern: /\bAKIA[0-9A-Z]{16}\b/ },
23
+ {
24
+ kind: "private key",
25
+ pattern: new RegExp(["-----BEGIN", "(?:RSA |EC |OPENSSH )?PRIVATE KEY-----"].join(" ")),
26
+ },
27
+ ];
28
+ export function findPotentialSecrets(root) {
29
+ const files = listFiles(root);
30
+ const findings = [];
31
+ for (const path of files) {
32
+ const fileKind = sensitiveFilename(path);
33
+ if (fileKind)
34
+ findings.push({ path, kind: fileKind });
35
+ if (!isSmallTextFile(root, path))
36
+ continue;
37
+ const content = readUtf8(join(root, path));
38
+ if (content === undefined)
39
+ continue;
40
+ for (const { kind, pattern } of contentPatterns) {
41
+ if (pattern.test(content)) {
42
+ findings.push({ path, kind });
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ return findings;
48
+ }
49
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../src/checks/secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAOnE,MAAM,uBAAuB,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AAErE,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAE1C,IACE,IAAI,KAAK,MAAM;QACf,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YACvB,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EACnE,CAAC;QACD,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxF,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QAC3E,OAAO,yBAAyB,CAAC;IACnC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,eAAe,GAA6C;IAChE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,iCAAiC,EAAE;IACpE,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,qCAAqC,EAAE;IAC5E,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,sBAAsB,EAAE;IAC3D;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,IAAI,MAAM,CAAC,CAAC,YAAY,EAAE,wCAAwC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;KACxF;CACF,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAoB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,QAAQ;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEtD,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC;YAAE,SAAS;QAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC3C,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QAEpC,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,eAAe,EAAE,CAAC;YAChD,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC9B,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ import { statSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ import { analyzeProject, SHIPPROOF_VERSION } from "./analyze.js";
5
+ import { renderJson } from "./reporters/json.js";
6
+ import { renderTerminal } from "./reporters/terminal.js";
7
+ const help = `ShipProof ${SHIPPROOF_VERSION}
8
+
9
+ Zero-config release readiness checks for AI-assisted projects.
10
+
11
+ Usage:
12
+ shipproof [path] [options]
13
+
14
+ Options:
15
+ --json Print machine-readable JSON
16
+ --no-color Disable ANSI colors
17
+ --no-fail Exit with code 0 even when blocking issues are found
18
+ -h, --help Show help
19
+ -v, --version
20
+ Show the version
21
+
22
+ Examples:
23
+ shipproof
24
+ shipproof ./my-project
25
+ shipproof --json > shipproof-report.json
26
+ `;
27
+ function parseArguments(arguments_) {
28
+ let target = ".";
29
+ let targetWasSet = false;
30
+ let json = false;
31
+ let color = process.stdout.isTTY && process.env.NO_COLOR === undefined;
32
+ let failOnIssues = true;
33
+ let showHelp = false;
34
+ let showVersion = false;
35
+ for (const argument of arguments_) {
36
+ if (argument === "--json")
37
+ json = true;
38
+ else if (argument === "--no-color")
39
+ color = false;
40
+ else if (argument === "--no-fail")
41
+ failOnIssues = false;
42
+ else if (argument === "--help" || argument === "-h")
43
+ showHelp = true;
44
+ else if (argument === "--version" || argument === "-v")
45
+ showVersion = true;
46
+ else if (argument.startsWith("-"))
47
+ throw new Error(`Unknown option: ${argument}`);
48
+ else if (targetWasSet)
49
+ throw new Error("Only one project path can be analyzed at a time.");
50
+ else {
51
+ target = argument;
52
+ targetWasSet = true;
53
+ }
54
+ }
55
+ return { target, json, color, failOnIssues, help: showHelp, version: showVersion };
56
+ }
57
+ function main() {
58
+ let options;
59
+ try {
60
+ options = parseArguments(process.argv.slice(2));
61
+ }
62
+ catch (error) {
63
+ const message = error instanceof Error ? error.message : "Invalid arguments.";
64
+ process.stderr.write(`shipproof: ${message}\nTry 'shipproof --help'.\n`);
65
+ process.exitCode = 2;
66
+ return;
67
+ }
68
+ if (options.help) {
69
+ process.stdout.write(help);
70
+ return;
71
+ }
72
+ if (options.version) {
73
+ process.stdout.write(`${SHIPPROOF_VERSION}\n`);
74
+ return;
75
+ }
76
+ const target = resolve(options.target);
77
+ try {
78
+ if (!statSync(target).isDirectory())
79
+ throw new Error("The target is not a directory.");
80
+ }
81
+ catch {
82
+ process.stderr.write(`shipproof: Cannot analyze '${options.target}': directory not found.\n`);
83
+ process.exitCode = 2;
84
+ return;
85
+ }
86
+ const result = analyzeProject(target);
87
+ process.stdout.write(options.json ? `${renderJson(result)}\n` : renderTerminal(result, options.color));
88
+ if (options.failOnIssues && result.summary.failed > 0)
89
+ process.exitCode = 1;
90
+ }
91
+ process.stdout.on("error", (error) => {
92
+ if (error.code === "EPIPE")
93
+ process.exit(0);
94
+ throw error;
95
+ });
96
+ main();
97
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare function pathExists(root: string, ...parts: string[]): boolean;
2
+ export declare function readUtf8(path: string): string | undefined;
3
+ export declare function readJson<T>(path: string): T | undefined;
4
+ export declare function listFiles(root: string, options?: {
5
+ maxFiles?: number;
6
+ maxDepth?: number;
7
+ }): string[];
8
+ export declare function isSmallTextFile(root: string, relativePath: string): boolean;
9
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/files.ts"],"names":[],"mappings":"AA4DA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAEpE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMzD;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CASvD;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACrD,MAAM,EAAE,CA+BV;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAY3E"}
@@ -0,0 +1,120 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync, } from "node:fs";
2
+ import { basename, extname, join, relative } from "node:path";
3
+ const ignoredDirectories = new Set([
4
+ ".git",
5
+ ".next",
6
+ ".turbo",
7
+ ".venv",
8
+ "build",
9
+ "coverage",
10
+ "dist",
11
+ "node_modules",
12
+ "target",
13
+ "vendor",
14
+ ]);
15
+ const textExtensions = new Set([
16
+ ".c",
17
+ ".cc",
18
+ ".conf",
19
+ ".cpp",
20
+ ".cs",
21
+ ".css",
22
+ ".env",
23
+ ".go",
24
+ ".h",
25
+ ".hpp",
26
+ ".html",
27
+ ".ini",
28
+ ".java",
29
+ ".js",
30
+ ".json",
31
+ ".jsx",
32
+ ".kt",
33
+ ".md",
34
+ ".mjs",
35
+ ".php",
36
+ ".properties",
37
+ ".py",
38
+ ".rb",
39
+ ".rs",
40
+ ".sh",
41
+ ".sql",
42
+ ".svelte",
43
+ ".swift",
44
+ ".toml",
45
+ ".ts",
46
+ ".tsx",
47
+ ".txt",
48
+ ".vue",
49
+ ".xml",
50
+ ".yaml",
51
+ ".yml",
52
+ ]);
53
+ export function pathExists(root, ...parts) {
54
+ return existsSync(join(root, ...parts));
55
+ }
56
+ export function readUtf8(path) {
57
+ try {
58
+ return readFileSync(path, "utf8");
59
+ }
60
+ catch {
61
+ return undefined;
62
+ }
63
+ }
64
+ export function readJson(path) {
65
+ const content = readUtf8(path);
66
+ if (content === undefined)
67
+ return undefined;
68
+ try {
69
+ return JSON.parse(content);
70
+ }
71
+ catch {
72
+ return undefined;
73
+ }
74
+ }
75
+ export function listFiles(root, options = {}) {
76
+ const maxFiles = options.maxFiles ?? 400;
77
+ const maxDepth = options.maxDepth ?? 7;
78
+ const files = [];
79
+ function visit(directory, depth) {
80
+ if (files.length >= maxFiles || depth > maxDepth)
81
+ return;
82
+ let entries;
83
+ try {
84
+ entries = readdirSync(directory, { withFileTypes: true });
85
+ }
86
+ catch {
87
+ return;
88
+ }
89
+ for (const entry of entries) {
90
+ if (files.length >= maxFiles)
91
+ return;
92
+ if (entry.isSymbolicLink())
93
+ continue;
94
+ const absolute = join(directory, entry.name);
95
+ if (entry.isDirectory()) {
96
+ if (!ignoredDirectories.has(entry.name))
97
+ visit(absolute, depth + 1);
98
+ continue;
99
+ }
100
+ if (entry.isFile())
101
+ files.push(relative(root, absolute).replaceAll("\\", "/"));
102
+ }
103
+ }
104
+ visit(root, 0);
105
+ return files;
106
+ }
107
+ export function isSmallTextFile(root, relativePath) {
108
+ const absolute = join(root, relativePath);
109
+ const name = basename(relativePath).toLowerCase();
110
+ const extension = extname(name);
111
+ if (!textExtensions.has(extension) && !name.startsWith(".env"))
112
+ return false;
113
+ try {
114
+ return statSync(absolute).size <= 1_000_000;
115
+ }
116
+ catch {
117
+ return false;
118
+ }
119
+ }
120
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,GACT,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE9D,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,MAAM;IACN,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,UAAU;IACV,MAAM;IACN,cAAc;IACd,QAAQ;IACR,QAAQ;CACT,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,IAAI;IACJ,KAAK;IACL,OAAO;IACP,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,KAAK;IACL,IAAI;IACJ,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,KAAK;IACL,OAAO;IACP,MAAM;IACN,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,aAAa;IACb,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,SAAS;IACT,QAAQ;IACR,OAAO;IACP,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,GAAG,KAAe;IACzD,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,IAAY;IACtC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE5C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,OAAO,GAA6C,EAAE;IAEtD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,GAAG,CAAC;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS,KAAK,CAAC,SAAiB,EAAE,KAAa;QAC7C,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,IAAI,KAAK,GAAG,QAAQ;YAAE,OAAO;QAEzD,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ;gBAAE,OAAO;YACrC,IAAI,KAAK,CAAC,cAAc,EAAE;gBAAE,SAAS;YAErC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;oBAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;gBACpE,SAAS;YACX,CAAC;YAED,IAAI,KAAK,CAAC,MAAM,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACf,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,YAAoB;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;IAClD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAE7E,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { analyzeProject, SHIPPROOF_VERSION } from "./analyze.js";
2
+ export { renderJson } from "./reporters/json.js";
3
+ export { renderTerminal } from "./reporters/terminal.js";
4
+ export type { AnalysisResult, AnalysisSummary, CheckResult, CheckStatus, ProjectInfo, Readiness, } from "./types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY,EACV,cAAc,EACd,eAAe,EACf,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,GACV,MAAM,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { analyzeProject, SHIPPROOF_VERSION } from "./analyze.js";
2
+ export { renderJson } from "./reporters/json.js";
3
+ export { renderTerminal } from "./reporters/terminal.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AnalysisResult } from "../types.js";
2
+ export declare function renderJson(result: AnalysisResult): string;
3
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../../src/reporters/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAEzD"}
@@ -0,0 +1,4 @@
1
+ export function renderJson(result) {
2
+ return JSON.stringify(result, null, 2);
3
+ }
4
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/reporters/json.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CAAC,MAAsB;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AnalysisResult } from "../types.js";
2
+ export declare function renderTerminal(result: AnalysisResult, color?: boolean): string;
3
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/reporters/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA0B,MAAM,aAAa,CAAC;AAmC1E,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,UAAO,GAAG,MAAM,CA8B3E"}
@@ -0,0 +1,50 @@
1
+ const symbols = {
2
+ pass: "✓",
3
+ warn: "!",
4
+ fail: "×",
5
+ info: "·",
6
+ };
7
+ const readinessLabels = {
8
+ ready: "Ready to ship",
9
+ close: "Almost ready",
10
+ "work-needed": "Needs work",
11
+ "not-ready": "Not ready",
12
+ };
13
+ function painter(enabled) {
14
+ const wrap = (code) => (value) => enabled ? `\u001B[${code}m${value}\u001B[0m` : value;
15
+ return {
16
+ pass: wrap(32),
17
+ warn: wrap(33),
18
+ fail: wrap(31),
19
+ info: wrap(36),
20
+ accent: wrap(35),
21
+ muted: wrap(90),
22
+ };
23
+ }
24
+ function scoreBar(score) {
25
+ const filled = Math.round(score / 5);
26
+ return `${"█".repeat(filled)}${"░".repeat(20 - filled)}`;
27
+ }
28
+ export function renderTerminal(result, color = true) {
29
+ const paint = painter(color);
30
+ const scoreStatus = result.score >= 90 ? "pass" : result.score >= 70 ? "warn" : "fail";
31
+ const ecosystem = result.project.ecosystems.length > 0 ? result.project.ecosystems.join(", ") : "unknown stack";
32
+ const lines = [
33
+ "",
34
+ paint.accent(" SHIPPROOF"),
35
+ paint.muted(` ${result.project.name} · ${ecosystem}`),
36
+ "",
37
+ ` ${paint[scoreStatus](`${result.score}/100`)} ${scoreBar(result.score)} ${readinessLabels[result.readiness]}`,
38
+ "",
39
+ ];
40
+ for (const check of result.checks) {
41
+ const marker = paint[check.status](symbols[check.status]);
42
+ lines.push(` ${marker} ${check.title}: ${check.message}`);
43
+ if (check.suggestion && check.status !== "pass") {
44
+ lines.push(paint.muted(` → ${check.suggestion}`));
45
+ }
46
+ }
47
+ lines.push("", paint.muted(` ${result.summary.passed} passed · ${result.summary.warnings} warnings · ${result.summary.failed} failed · ${result.durationMs}ms`), "");
48
+ return lines.join("\n");
49
+ }
50
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../../src/reporters/terminal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export type CheckStatus = "pass" | "warn" | "fail" | "info";
2
+ export interface CheckResult {
3
+ id: string;
4
+ title: string;
5
+ status: CheckStatus;
6
+ message: string;
7
+ suggestion?: string;
8
+ weight: number;
9
+ }
10
+ export interface ProjectInfo {
11
+ name: string;
12
+ path: string;
13
+ ecosystems: string[];
14
+ }
15
+ export interface AnalysisSummary {
16
+ passed: number;
17
+ warnings: number;
18
+ failed: number;
19
+ informational: number;
20
+ }
21
+ export type Readiness = "ready" | "close" | "work-needed" | "not-ready";
22
+ export interface AnalysisResult {
23
+ version: string;
24
+ analyzedAt: string;
25
+ durationMs: number;
26
+ project: ProjectInfo;
27
+ score: number;
28
+ readiness: Readiness;
29
+ summary: AnalysisSummary;
30
+ checks: CheckResult[];
31
+ }
32
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,aAAa,GAAG,WAAW,CAAC;AAExE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
package/docs/demo.svg ADDED
@@ -0,0 +1,23 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 920 500" role="img" aria-labelledby="title description">
2
+ <title id="title">ShipProof terminal demo</title>
3
+ <description id="description">A terminal showing a ShipProof project readiness score and checks.</description>
4
+ <rect width="920" height="500" rx="18" fill="#0f172a"/>
5
+ <circle cx="30" cy="28" r="7" fill="#fb7185"/>
6
+ <circle cx="54" cy="28" r="7" fill="#fbbf24"/>
7
+ <circle cx="78" cy="28" r="7" fill="#4ade80"/>
8
+ <g font-family="ui-monospace,SFMono-Regular,Consolas,monospace" font-size="18">
9
+ <text x="28" y="78" fill="#94a3b8">$ npx shipproof</text>
10
+ <text x="28" y="126" fill="#c084fc" font-weight="700">SHIPPROOF</text>
11
+ <text x="28" y="156" fill="#64748b">acme-app · Node.js</text>
12
+ <text x="28" y="204" fill="#4ade80" font-weight="700">92/100</text>
13
+ <text x="138" y="204" fill="#4ade80">██████████████████</text>
14
+ <text x="354" y="204" fill="#334155">██</text>
15
+ <text x="392" y="204" fill="#e2e8f0">Ready to ship</text>
16
+ <text x="28" y="252" fill="#4ade80">✓</text><text x="54" y="252" fill="#e2e8f0">README: Clear installation and usage guide.</text>
17
+ <text x="28" y="286" fill="#4ade80">✓</text><text x="54" y="286" fill="#e2e8f0">Secret exposure: No common patterns detected.</text>
18
+ <text x="28" y="320" fill="#4ade80">✓</text><text x="54" y="320" fill="#e2e8f0">Continuous integration: Found 1 workflow.</text>
19
+ <text x="28" y="354" fill="#fbbf24">!</text><text x="54" y="354" fill="#e2e8f0">Community health: Missing SECURITY.md.</text>
20
+ <text x="54" y="384" fill="#64748b">→ Add lightweight guidance before inviting contributors.</text>
21
+ <text x="28" y="438" fill="#64748b">10 passed · 1 warning · 0 failed · 31ms</text>
22
+ </g>
23
+ </svg>
@@ -0,0 +1,15 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 190" role="img" aria-labelledby="title description">
2
+ <title id="title">ShipProof</title>
3
+ <description id="description">A ship inside a shield beside the ShipProof wordmark.</description>
4
+ <defs>
5
+ <linearGradient id="shield" x1="0" y1="0" x2="1" y2="1">
6
+ <stop offset="0" stop-color="#8b5cf6"/>
7
+ <stop offset="1" stop-color="#06b6d4"/>
8
+ </linearGradient>
9
+ </defs>
10
+ <path fill="url(#shield)" d="M96 10 169 36v52c0 49-28 78-73 94-45-16-73-45-73-94V36z"/>
11
+ <path fill="#fff" d="m53 99 9 27c21 10 47 10 68 0l9-27-43 13zm29-47h28v46L96 93 82 98zm-20 55 34-16 34 16-7 11c-17 7-37 7-54 0z"/>
12
+ <path fill="#22d3ee" d="M56 132c26 11 54 11 80 0-7 15-20 26-40 35-20-9-33-20-40-35z"/>
13
+ <text x="205" y="112" fill="#111827" font-family="Inter,Segoe UI,Arial,sans-serif" font-size="72" font-weight="800" letter-spacing="-3">ShipProof</text>
14
+ <text x="210" y="150" fill="#64748b" font-family="Inter,Segoe UI,Arial,sans-serif" font-size="20" letter-spacing="2">KNOW BEFORE YOU SHIP</text>
15
+ </svg>
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "shipproof",
3
+ "version": "0.1.0",
4
+ "description": "Zero-config release readiness checks for AI-assisted projects.",
5
+ "type": "module",
6
+ "bin": {
7
+ "shipproof": "dist/src/cli.js"
8
+ },
9
+ "files": [
10
+ "dist/src",
11
+ "docs/*.svg",
12
+ "README.md",
13
+ "README.es.md",
14
+ "LICENSE"
15
+ ],
16
+ "keywords": [
17
+ "ai",
18
+ "cli",
19
+ "code-quality",
20
+ "developer-tools",
21
+ "release-readiness",
22
+ "security"
23
+ ],
24
+ "author": "CalvaryBloom",
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/CalvaryBloom/shipproof.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/CalvaryBloom/shipproof/issues"
32
+ },
33
+ "homepage": "https://github.com/CalvaryBloom/shipproof#readme",
34
+ "engines": {
35
+ "node": ">=22.13"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^26.1.1",
42
+ "typescript": "^7.0.2"
43
+ },
44
+ "scripts": {
45
+ "build": "tsc -p tsconfig.json",
46
+ "check": "tsc -p tsconfig.json --noEmit",
47
+ "lint": "tsc -p tsconfig.json --noEmit",
48
+ "test": "pnpm build && node --test dist/test/analyze.test.js",
49
+ "start": "node dist/src/cli.js"
50
+ }
51
+ }