@metasession.co/devaudit-cli 0.1.58 → 0.1.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +68 -22
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/scripts/upload-evidence.sh +35 -4
- package/sdlc/ai-rules/INSTRUCTIONS-SDLC.md +9 -7
- package/sdlc/ai-rules/README.md +2 -1
- package/sdlc/files/_common/0-project-setup.md +1 -1
- package/sdlc/files/_common/2-implement-and-test.md +24 -14
- package/sdlc/files/_common/implementing-an-sdlc-issue.md +2 -2
- package/sdlc/files/_common/joining-an-existing-project.md +2 -2
package/dist/index.js
CHANGED
|
@@ -56,7 +56,7 @@ function emitJsonResult(payload) {
|
|
|
56
56
|
|
|
57
57
|
// package.json
|
|
58
58
|
var package_default = {
|
|
59
|
-
version: "0.1.
|
|
59
|
+
version: "0.1.59"};
|
|
60
60
|
|
|
61
61
|
// src/lib/version.ts
|
|
62
62
|
var CLI_VERSION = package_default.version;
|
|
@@ -521,6 +521,7 @@ async function runAuthStatus() {
|
|
|
521
521
|
}
|
|
522
522
|
var FRAMEWORK_FILES = [
|
|
523
523
|
"INSTRUCTIONS.md",
|
|
524
|
+
"AGENTS.md",
|
|
524
525
|
"CLAUDE.md",
|
|
525
526
|
".cursorrules",
|
|
526
527
|
".windsurfrules",
|
|
@@ -596,11 +597,16 @@ async function runStatus(options) {
|
|
|
596
597
|
}
|
|
597
598
|
var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
598
599
|
var DEFAULT_MAX_ATTEMPTS = 5;
|
|
600
|
+
var DEFAULT_UPLOAD_MAX_TIME_SECONDS = 120;
|
|
599
601
|
var INITIAL_BACKOFF_MS = 1e3;
|
|
600
602
|
function maxAttempts() {
|
|
601
603
|
const raw = Number.parseInt(process.env["UPLOAD_MAX_ATTEMPTS"] ?? "", 10);
|
|
602
604
|
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_MAX_ATTEMPTS;
|
|
603
605
|
}
|
|
606
|
+
function uploadMaxTimeSeconds() {
|
|
607
|
+
const raw = Number(process.env["UPLOAD_MAX_TIME_SECONDS"] ?? "");
|
|
608
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_UPLOAD_MAX_TIME_SECONDS;
|
|
609
|
+
}
|
|
604
610
|
async function collectFiles(filePath) {
|
|
605
611
|
const stat = await promises.stat(filePath);
|
|
606
612
|
if (stat.isFile()) return [filePath];
|
|
@@ -626,6 +632,30 @@ function isUneditedStub(buf) {
|
|
|
626
632
|
function delay(ms) {
|
|
627
633
|
return new Promise((res) => setTimeout(res, ms));
|
|
628
634
|
}
|
|
635
|
+
function buildUploadForm(file, buf, opts) {
|
|
636
|
+
const form = new FormData();
|
|
637
|
+
const blob = new Blob([new Uint8Array(buf)]);
|
|
638
|
+
form.set("file", blob, basename(file));
|
|
639
|
+
form.set("projectSlug", opts.projectSlug);
|
|
640
|
+
form.set("requirementId", opts.requirementId);
|
|
641
|
+
form.set("evidenceType", opts.evidenceType);
|
|
642
|
+
form.set("metadata", JSON.stringify(opts.metadata ?? {}));
|
|
643
|
+
if (opts.releaseVersion) form.set("releaseVersion", opts.releaseVersion);
|
|
644
|
+
if (opts.createReleaseIfMissing) form.set("createReleaseIfMissing", "true");
|
|
645
|
+
if (opts.environment) form.set("environment", opts.environment);
|
|
646
|
+
if (opts.evidenceCategory) form.set("evidenceCategory", opts.evidenceCategory);
|
|
647
|
+
if (opts.releaseBranch) form.set("releaseBranch", opts.releaseBranch);
|
|
648
|
+
if (opts.releaseTitle) form.set("releaseTitle", opts.releaseTitle);
|
|
649
|
+
if (opts.changeType) form.set("changeType", opts.changeType);
|
|
650
|
+
if (opts.gateStatus) form.set("gateStatus", opts.gateStatus);
|
|
651
|
+
return form;
|
|
652
|
+
}
|
|
653
|
+
function uploadFailureMessage(err, timeoutSeconds) {
|
|
654
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
655
|
+
return `upload timed out after ${timeoutSeconds}s`;
|
|
656
|
+
}
|
|
657
|
+
return err instanceof Error ? err.message : String(err);
|
|
658
|
+
}
|
|
629
659
|
async function probeBaseUrlDrift(baseUrl) {
|
|
630
660
|
try {
|
|
631
661
|
const probeUrl = `${baseUrl.replace(/\/$/, "")}/api/health`;
|
|
@@ -650,30 +680,33 @@ async function probeBaseUrlDrift(baseUrl) {
|
|
|
650
680
|
}
|
|
651
681
|
async function uploadOne(file, buf, opts) {
|
|
652
682
|
const attempts = maxAttempts();
|
|
653
|
-
const
|
|
654
|
-
const blob = new Blob([new Uint8Array(buf)]);
|
|
655
|
-
form.set("file", blob, basename(file));
|
|
656
|
-
form.set("projectSlug", opts.projectSlug);
|
|
657
|
-
form.set("requirementId", opts.requirementId);
|
|
658
|
-
form.set("evidenceType", opts.evidenceType);
|
|
659
|
-
form.set("metadata", JSON.stringify(opts.metadata ?? {}));
|
|
660
|
-
if (opts.releaseVersion) form.set("releaseVersion", opts.releaseVersion);
|
|
661
|
-
if (opts.createReleaseIfMissing) form.set("createReleaseIfMissing", "true");
|
|
662
|
-
if (opts.environment) form.set("environment", opts.environment);
|
|
663
|
-
if (opts.evidenceCategory) form.set("evidenceCategory", opts.evidenceCategory);
|
|
664
|
-
if (opts.releaseBranch) form.set("releaseBranch", opts.releaseBranch);
|
|
665
|
-
if (opts.releaseTitle) form.set("releaseTitle", opts.releaseTitle);
|
|
666
|
-
if (opts.changeType) form.set("changeType", opts.changeType);
|
|
667
|
-
if (opts.gateStatus) form.set("gateStatus", opts.gateStatus);
|
|
683
|
+
const timeoutSeconds = uploadMaxTimeSeconds();
|
|
668
684
|
const url = `${opts.baseUrl.replace(/\/$/, "")}/api/evidence/upload`;
|
|
669
685
|
let attempt = 1;
|
|
670
686
|
let backoff = INITIAL_BACKOFF_MS;
|
|
671
687
|
while (attempt <= attempts) {
|
|
672
|
-
const
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
688
|
+
const controller = new AbortController();
|
|
689
|
+
const timer = setTimeout(() => controller.abort(), timeoutSeconds * 1e3);
|
|
690
|
+
let res;
|
|
691
|
+
try {
|
|
692
|
+
res = await fetch(url, {
|
|
693
|
+
method: "POST",
|
|
694
|
+
headers: { authorization: `Bearer ${opts.apiKey}` },
|
|
695
|
+
body: buildUploadForm(file, buf, opts),
|
|
696
|
+
signal: controller.signal
|
|
697
|
+
});
|
|
698
|
+
} catch (err) {
|
|
699
|
+
const error = uploadFailureMessage(err, timeoutSeconds);
|
|
700
|
+
if (attempt < attempts) {
|
|
701
|
+
await delay(backoff);
|
|
702
|
+
backoff *= 2;
|
|
703
|
+
attempt += 1;
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
return { file, ok: false, status: 0, error };
|
|
707
|
+
} finally {
|
|
708
|
+
clearTimeout(timer);
|
|
709
|
+
}
|
|
677
710
|
if (res.ok) {
|
|
678
711
|
const body = await res.json().catch(() => null);
|
|
679
712
|
return { file, ok: true, status: res.status, body };
|
|
@@ -1694,6 +1727,18 @@ This file provides guidance to Gemini CLI when working in this repository.
|
|
|
1694
1727
|
|
|
1695
1728
|
Please adhere to the instructions in \`INSTRUCTIONS.md\` as the **Single Source of Truth**.
|
|
1696
1729
|
`;
|
|
1730
|
+
var AGENTS_POINTER = `# AGENTS.md
|
|
1731
|
+
|
|
1732
|
+
This file provides guidance to Codex and AGENTS-compatible coding agents when working in this repository.
|
|
1733
|
+
|
|
1734
|
+
## Project Standards
|
|
1735
|
+
|
|
1736
|
+
All project rules, architectural standards, and development workflows are consolidated in:
|
|
1737
|
+
|
|
1738
|
+
- [INSTRUCTIONS.md](./INSTRUCTIONS.md)
|
|
1739
|
+
|
|
1740
|
+
Read and follow \`INSTRUCTIONS.md\` as the single source of truth. When working through an SDLC stage, also read the relevant workflow file in \`SDLC/\`.
|
|
1741
|
+
`;
|
|
1697
1742
|
var CLAUDE_POINTER_TAIL = `
|
|
1698
1743
|
## Project Standards
|
|
1699
1744
|
|
|
@@ -1754,9 +1799,10 @@ async function syncAiRules(ctx) {
|
|
|
1754
1799
|
await writePointerFile(join(ctx.projectPath, ".cursorrules"), CURSOR_POINTER);
|
|
1755
1800
|
await writePointerFile(join(ctx.projectPath, ".windsurfrules"), WINDSURF_POINTER);
|
|
1756
1801
|
await writePointerFile(join(ctx.projectPath, "GEMINI.md"), GEMINI_POINTER);
|
|
1802
|
+
await writePointerFile(join(ctx.projectPath, "AGENTS.md"), AGENTS_POINTER);
|
|
1757
1803
|
await updateClaudeFile(join(ctx.projectPath, "CLAUDE.md"));
|
|
1758
1804
|
await updateInstructionsFile(join(ctx.projectPath, "INSTRUCTIONS.md"), sdlcContent);
|
|
1759
|
-
return { name: "AI rule pointers + INSTRUCTIONS.md", filesSynced:
|
|
1805
|
+
return { name: "AI rule pointers + INSTRUCTIONS.md", filesSynced: 6, message: "synced" };
|
|
1760
1806
|
}
|
|
1761
1807
|
async function syncStackHooks(ctx) {
|
|
1762
1808
|
const adapter = await loadStackAdapter(ctx.installerRoot, ctx.stack);
|