tend-cli 0.1.1 → 0.2.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.
- package/README.md +11 -4
- package/dist/bin.js +15 -7
- package/dist/{config-B5rO-fvz.js → config-DMOjMbMD.js} +37 -6
- package/dist/index.d.ts +15 -1
- package/dist/index.js +1 -1
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
# tend
|
|
2
2
|
|
|
3
|
+
[](https://github.com/Njunge11/tend/actions/workflows/ci.yml)
|
|
4
|
+
[](https://sonarcloud.io/summary/new_code?id=Njunge11_tend)
|
|
5
|
+
[](https://sonarcloud.io/summary/new_code?id=Njunge11_tend)
|
|
6
|
+
[](https://sonarcloud.io/summary/new_code?id=Njunge11_tend)
|
|
7
|
+
[](https://www.npmjs.com/package/tend-cli)
|
|
3
8
|

|
|
4
9
|
|
|
5
10
|
*Tend your code now so it never becomes an overgrown mess.*
|
|
6
11
|
|
|
7
12
|
> [!NOTE]
|
|
8
13
|
> **Early days (v0.x).** tend works, but it's young — flags and config may still
|
|
9
|
-
> change before 1.0.
|
|
10
|
-
>
|
|
14
|
+
> change before 1.0. The fix sessions run on Claude via [Claude Code](https://www.anthropic.com/claude-code)
|
|
15
|
+
> for now; support for other models is planned. As with any tool that edits code, run it on a
|
|
16
|
+
> committed repo and review the changes. Feedback and issues are very welcome.
|
|
11
17
|
|
|
12
18
|
An open-source CLI that audits a JS/TS repo with standard scanners, then fixes the findings
|
|
13
19
|
with parallel AI sessions in a safe **scan → fix → re-scan** loop. It never commits — fixes
|
|
@@ -21,8 +27,9 @@ npx tend-cli src/app lib/ # only findings under these paths
|
|
|
21
27
|
npx tend-cli --all # the entire backlog, repo-wide
|
|
22
28
|
```
|
|
23
29
|
|
|
24
|
-
Requires **Node ≥ 20
|
|
25
|
-
|
|
30
|
+
Requires **Node ≥ 20**, a git repo, and the [Claude Code](https://www.anthropic.com/claude-code)
|
|
31
|
+
CLI (`claude`) installed and signed in — tend drives it to make the fixes. Review the edits with
|
|
32
|
+
`tend diff`; undo the whole run with `tend undo`.
|
|
26
33
|
|
|
27
34
|
## What it does
|
|
28
35
|
|
package/dist/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { ClaudeSession, EFFORT_LEVELS, EventBus, ReportBuilder, ReportSchema, Snapshot, addUsage, applyCliOverrides, assertGitRepo, buildProgram, changedVsHead, createGit, detectPackageManager, filesUnder, filterToChanged, formatClock, loadConfig, makeTheme, normalize, orchestrate, planWork, reasonLabel, renderSummary, resolveRetryTarget, retryCommand, runScanner, scannerStatus, showCommand, zeroUsage } from "./config-
|
|
2
|
+
import { ClaudeSession, EFFORT_LEVELS, EventBus, ReportBuilder, ReportSchema, Snapshot, addUsage, applyCliOverrides, assertGitRepo, buildProgram, changedVsHead, createGit, detectPackageManager, filesUnder, filterToChanged, formatClock, loadConfig, makeTheme, normalize, orchestrate, planWork, reasonLabel, renderSummary, resolveRetryTarget, retryCommand, runScanner, scannerStatus, showCommand, zeroUsage } from "./config-DMOjMbMD.js";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { execa } from "execa";
|
|
@@ -1053,25 +1053,28 @@ function makeFixUnit(deps) {
|
|
|
1053
1053
|
prompt: renderPrompt(unit)
|
|
1054
1054
|
});
|
|
1055
1055
|
if (res.usage) usage = addUsage(usage, res.usage);
|
|
1056
|
-
if (!changedOnDisk()) return {
|
|
1057
|
-
kept: false,
|
|
1058
|
-
reason: "session-error",
|
|
1059
|
-
usage
|
|
1060
|
-
};
|
|
1061
1056
|
if (!res.ok) {
|
|
1062
|
-
restore();
|
|
1057
|
+
if (changedOnDisk()) restore();
|
|
1063
1058
|
return {
|
|
1064
1059
|
kept: false,
|
|
1065
1060
|
reason: "session-error",
|
|
1061
|
+
detail: res.error,
|
|
1066
1062
|
usage
|
|
1067
1063
|
};
|
|
1068
1064
|
}
|
|
1065
|
+
if (!changedOnDisk()) return {
|
|
1066
|
+
kept: false,
|
|
1067
|
+
reason: "session-error",
|
|
1068
|
+
detail: "Session completed without changing owned files",
|
|
1069
|
+
usage
|
|
1070
|
+
};
|
|
1069
1071
|
const supp = antiSuppression(buildDiff(before, diskNow()));
|
|
1070
1072
|
if (!supp.ok) {
|
|
1071
1073
|
restore();
|
|
1072
1074
|
return {
|
|
1073
1075
|
kept: false,
|
|
1074
1076
|
reason: supp.reason,
|
|
1077
|
+
detail: supp.detail,
|
|
1075
1078
|
usage
|
|
1076
1079
|
};
|
|
1077
1080
|
}
|
|
@@ -1084,9 +1087,11 @@ function makeFixUnit(deps) {
|
|
|
1084
1087
|
return {
|
|
1085
1088
|
kept: false,
|
|
1086
1089
|
reason: tc.reason,
|
|
1090
|
+
detail: tc.detail,
|
|
1087
1091
|
usage
|
|
1088
1092
|
};
|
|
1089
1093
|
}
|
|
1094
|
+
let repairFailureDetail;
|
|
1090
1095
|
const phase = await runTestPhase({
|
|
1091
1096
|
baseline: deps.baseline,
|
|
1092
1097
|
runRelated: () => deps.runRelated(unit.files),
|
|
@@ -1097,6 +1102,7 @@ function makeFixUnit(deps) {
|
|
|
1097
1102
|
prompt: `${renderPrompt(unit)}\n\nThe previous edit left a test red — diagnose and fix.`
|
|
1098
1103
|
});
|
|
1099
1104
|
if (repair.usage) usage = addUsage(usage, repair.usage);
|
|
1105
|
+
if (!repair.ok) repairFailureDetail = `Repair session failed: ${repair.error}`;
|
|
1100
1106
|
},
|
|
1101
1107
|
maxRepairs: deps.maxRepairs,
|
|
1102
1108
|
hasTestRunner: deps.hasTestRunner
|
|
@@ -1106,6 +1112,7 @@ function makeFixUnit(deps) {
|
|
|
1106
1112
|
return {
|
|
1107
1113
|
kept: false,
|
|
1108
1114
|
reason: phase.reason,
|
|
1115
|
+
detail: repairFailureDetail ?? phase.detail,
|
|
1109
1116
|
usage
|
|
1110
1117
|
};
|
|
1111
1118
|
}
|
|
@@ -1116,6 +1123,7 @@ function makeFixUnit(deps) {
|
|
|
1116
1123
|
return {
|
|
1117
1124
|
kept: false,
|
|
1118
1125
|
reason: regression.reason,
|
|
1126
|
+
detail: regression.detail,
|
|
1119
1127
|
usage
|
|
1120
1128
|
};
|
|
1121
1129
|
}
|
|
@@ -126,6 +126,7 @@ const FindingSchema = z.object({
|
|
|
126
126
|
"typecheck",
|
|
127
127
|
"session-error"
|
|
128
128
|
]).optional(),
|
|
129
|
+
revertDetail: z.string().optional(),
|
|
129
130
|
firstSeenLoop: z.number(),
|
|
130
131
|
lastSeenLoop: z.number(),
|
|
131
132
|
inScope: z.boolean().optional()
|
|
@@ -705,6 +706,17 @@ var ClaudeSession = class {
|
|
|
705
706
|
}
|
|
706
707
|
};
|
|
707
708
|
|
|
709
|
+
//#endregion
|
|
710
|
+
//#region src/findings/revert-detail.ts
|
|
711
|
+
const MAX_REVERT_DETAIL_LENGTH = 500;
|
|
712
|
+
/** Keep persisted diagnostics readable and bounded for report.json. */
|
|
713
|
+
function normalizeRevertDetail(detail) {
|
|
714
|
+
const trimmed = detail?.replace(/\s+/g, " ").trim();
|
|
715
|
+
if (!trimmed) return void 0;
|
|
716
|
+
if (trimmed.length <= MAX_REVERT_DETAIL_LENGTH) return trimmed;
|
|
717
|
+
return `${trimmed.slice(0, MAX_REVERT_DETAIL_LENGTH - 3)}...`;
|
|
718
|
+
}
|
|
719
|
+
|
|
708
720
|
//#endregion
|
|
709
721
|
//#region src/findings/store.ts
|
|
710
722
|
const StoreSchema = z.array(FindingSchema);
|
|
@@ -728,7 +740,11 @@ var FindingStore = class FindingStore {
|
|
|
728
740
|
*/
|
|
729
741
|
reconcile(fresh, loop) {
|
|
730
742
|
const freshIds = new Set(fresh.map((f) => f.id));
|
|
731
|
-
for (const known of this.findings.values()) if (!freshIds.has(known.id))
|
|
743
|
+
for (const known of this.findings.values()) if (!freshIds.has(known.id)) {
|
|
744
|
+
known.status = "fixed";
|
|
745
|
+
delete known.revertReason;
|
|
746
|
+
delete known.revertDetail;
|
|
747
|
+
}
|
|
732
748
|
for (const incoming of fresh) {
|
|
733
749
|
const known = this.findings.get(incoming.id);
|
|
734
750
|
if (known) {
|
|
@@ -746,11 +762,14 @@ var FindingStore = class FindingStore {
|
|
|
746
762
|
return this.all().filter((f) => (filter.track === void 0 || f.track === filter.track) && (filter.status === void 0 || f.status === filter.status) && (filter.file === void 0 || f.file === filter.file));
|
|
747
763
|
}
|
|
748
764
|
/** Record a failed fix attempt against a finding's fingerprint. */
|
|
749
|
-
recordFailedAttempt(id, reason) {
|
|
765
|
+
recordFailedAttempt(id, reason, detail) {
|
|
750
766
|
const finding = this.findings.get(id);
|
|
751
767
|
if (!finding) return;
|
|
752
768
|
finding.attempts += 1;
|
|
753
769
|
finding.revertReason = reason;
|
|
770
|
+
const normalizedDetail = normalizeRevertDetail(detail);
|
|
771
|
+
if (normalizedDetail) finding.revertDetail = normalizedDetail;
|
|
772
|
+
else delete finding.revertDetail;
|
|
754
773
|
}
|
|
755
774
|
/** A finding's per-issue budget is exhausted once it has used `budget` attempts. */
|
|
756
775
|
isBudgetExhausted(id, budget) {
|
|
@@ -838,9 +857,12 @@ function statusAttemptSnapshot(store) {
|
|
|
838
857
|
return store.all().map((f) => `${f.id}:${f.status}:${f.attempts}`).sort().join("|");
|
|
839
858
|
}
|
|
840
859
|
function applyOutcome(store, unit, outcome, budget) {
|
|
841
|
-
for (const finding of unit.findings) if (outcome.kept)
|
|
842
|
-
|
|
843
|
-
|
|
860
|
+
for (const finding of unit.findings) if (outcome.kept) {
|
|
861
|
+
finding.status = "fixed";
|
|
862
|
+
delete finding.revertReason;
|
|
863
|
+
delete finding.revertDetail;
|
|
864
|
+
} else {
|
|
865
|
+
store.recordFailedAttempt(finding.id, outcome.reason ?? "session-error", outcome.detail);
|
|
844
866
|
if (store.isBudgetExhausted(finding.id, budget)) finding.status = "unfixable";
|
|
845
867
|
}
|
|
846
868
|
}
|
|
@@ -1081,7 +1103,11 @@ var ReportBuilder = class {
|
|
|
1081
1103
|
}
|
|
1082
1104
|
/** Record (or update) a finding's final outcome by fingerprint. */
|
|
1083
1105
|
recordOutcome(finding) {
|
|
1084
|
-
|
|
1106
|
+
const normalized = normalizeRevertDetail(finding.revertDetail);
|
|
1107
|
+
const outcome = { ...finding };
|
|
1108
|
+
if (normalized) outcome.revertDetail = normalized;
|
|
1109
|
+
else delete outcome.revertDetail;
|
|
1110
|
+
this.outcomes.set(finding.id, outcome);
|
|
1085
1111
|
}
|
|
1086
1112
|
recordOutcomes(findings) {
|
|
1087
1113
|
for (const f of findings) this.recordOutcome(f);
|
|
@@ -1636,6 +1662,7 @@ function showCommand(id, findings) {
|
|
|
1636
1662
|
`attempts: ${finding.attempts}`
|
|
1637
1663
|
];
|
|
1638
1664
|
if (finding.revertReason) lines$1.push(`last revert reason: ${finding.revertReason}`);
|
|
1665
|
+
if (finding.revertDetail) lines$1.push(`last revert detail: ${finding.revertDetail}`);
|
|
1639
1666
|
if (finding.flowPath?.length) {
|
|
1640
1667
|
lines$1.push("flow path:");
|
|
1641
1668
|
for (const step of finding.flowPath) lines$1.push(` → ${step.file}:${step.line}`);
|
|
@@ -1675,6 +1702,7 @@ async function retryCommand(id, deps) {
|
|
|
1675
1702
|
if (outcome.kept) {
|
|
1676
1703
|
finding.status = "fixed";
|
|
1677
1704
|
delete finding.revertReason;
|
|
1705
|
+
delete finding.revertDetail;
|
|
1678
1706
|
if (deps.report) syncDerivedReportFields(deps.report);
|
|
1679
1707
|
return {
|
|
1680
1708
|
outcome: "fixed",
|
|
@@ -1685,6 +1713,9 @@ async function retryCommand(id, deps) {
|
|
|
1685
1713
|
const reason = outcome.reason ?? "session-error";
|
|
1686
1714
|
finding.attempts += 1;
|
|
1687
1715
|
finding.revertReason = reason;
|
|
1716
|
+
const detail = normalizeRevertDetail(outcome.detail);
|
|
1717
|
+
if (detail) finding.revertDetail = detail;
|
|
1718
|
+
else delete finding.revertDetail;
|
|
1688
1719
|
finding.status = finding.attempts >= largerBudget ? "unfixable" : "reverted";
|
|
1689
1720
|
if (deps.report) syncDerivedReportFields(deps.report);
|
|
1690
1721
|
return {
|
package/dist/index.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ declare const FindingSchema: z.ZodObject<{
|
|
|
45
45
|
status: z.ZodEnum<["pending", "fixing", "fixed", "reverted", "unfixable", "skipped"]>;
|
|
46
46
|
attempts: z.ZodNumber;
|
|
47
47
|
revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error"]>>;
|
|
48
|
+
revertDetail: z.ZodOptional<z.ZodString>;
|
|
48
49
|
firstSeenLoop: z.ZodNumber;
|
|
49
50
|
lastSeenLoop: z.ZodNumber;
|
|
50
51
|
inScope: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -75,6 +76,7 @@ declare const FindingSchema: z.ZodObject<{
|
|
|
75
76
|
}[] | undefined;
|
|
76
77
|
remediation?: string | undefined;
|
|
77
78
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
79
|
+
revertDetail?: string | undefined;
|
|
78
80
|
inScope?: boolean | undefined;
|
|
79
81
|
}, {
|
|
80
82
|
id: string;
|
|
@@ -103,6 +105,7 @@ declare const FindingSchema: z.ZodObject<{
|
|
|
103
105
|
}[] | undefined;
|
|
104
106
|
remediation?: string | undefined;
|
|
105
107
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
108
|
+
revertDetail?: string | undefined;
|
|
106
109
|
inScope?: boolean | undefined;
|
|
107
110
|
}>;
|
|
108
111
|
type Finding = z.infer<typeof FindingSchema>;
|
|
@@ -163,7 +166,7 @@ declare class FindingStore {
|
|
|
163
166
|
file?: string;
|
|
164
167
|
}): Finding[];
|
|
165
168
|
/** Record a failed fix attempt against a finding's fingerprint. */
|
|
166
|
-
recordFailedAttempt(id: string, reason: RevertReason$1): void;
|
|
169
|
+
recordFailedAttempt(id: string, reason: RevertReason$1, detail?: string): void;
|
|
167
170
|
/** A finding's per-issue budget is exhausted once it has used `budget` attempts. */
|
|
168
171
|
isBudgetExhausted(id: string, budget: number): boolean;
|
|
169
172
|
/** Serialize to a plain array — `report.json`'s findings section. */
|
|
@@ -611,6 +614,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
611
614
|
status: z.ZodEnum<["pending", "fixing", "fixed", "reverted", "unfixable", "skipped"]>;
|
|
612
615
|
attempts: z.ZodNumber;
|
|
613
616
|
revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error"]>>;
|
|
617
|
+
revertDetail: z.ZodOptional<z.ZodString>;
|
|
614
618
|
firstSeenLoop: z.ZodNumber;
|
|
615
619
|
lastSeenLoop: z.ZodNumber;
|
|
616
620
|
inScope: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -641,6 +645,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
641
645
|
}[] | undefined;
|
|
642
646
|
remediation?: string | undefined;
|
|
643
647
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
648
|
+
revertDetail?: string | undefined;
|
|
644
649
|
inScope?: boolean | undefined;
|
|
645
650
|
}, {
|
|
646
651
|
id: string;
|
|
@@ -669,6 +674,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
669
674
|
}[] | undefined;
|
|
670
675
|
remediation?: string | undefined;
|
|
671
676
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
677
|
+
revertDetail?: string | undefined;
|
|
672
678
|
inScope?: boolean | undefined;
|
|
673
679
|
}>, "many">;
|
|
674
680
|
secrets: z.ZodArray<z.ZodObject<{
|
|
@@ -712,6 +718,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
712
718
|
status: z.ZodEnum<["pending", "fixing", "fixed", "reverted", "unfixable", "skipped"]>;
|
|
713
719
|
attempts: z.ZodNumber;
|
|
714
720
|
revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error"]>>;
|
|
721
|
+
revertDetail: z.ZodOptional<z.ZodString>;
|
|
715
722
|
firstSeenLoop: z.ZodNumber;
|
|
716
723
|
lastSeenLoop: z.ZodNumber;
|
|
717
724
|
inScope: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -742,6 +749,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
742
749
|
}[] | undefined;
|
|
743
750
|
remediation?: string | undefined;
|
|
744
751
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
752
|
+
revertDetail?: string | undefined;
|
|
745
753
|
inScope?: boolean | undefined;
|
|
746
754
|
}, {
|
|
747
755
|
id: string;
|
|
@@ -770,6 +778,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
770
778
|
}[] | undefined;
|
|
771
779
|
remediation?: string | undefined;
|
|
772
780
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
781
|
+
revertDetail?: string | undefined;
|
|
773
782
|
inScope?: boolean | undefined;
|
|
774
783
|
}>, "many">;
|
|
775
784
|
depBumps: z.ZodArray<z.ZodObject<{
|
|
@@ -861,6 +870,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
861
870
|
}[] | undefined;
|
|
862
871
|
remediation?: string | undefined;
|
|
863
872
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
873
|
+
revertDetail?: string | undefined;
|
|
864
874
|
inScope?: boolean | undefined;
|
|
865
875
|
}[];
|
|
866
876
|
secrets: {
|
|
@@ -890,6 +900,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
890
900
|
}[] | undefined;
|
|
891
901
|
remediation?: string | undefined;
|
|
892
902
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
903
|
+
revertDetail?: string | undefined;
|
|
893
904
|
inScope?: boolean | undefined;
|
|
894
905
|
}[];
|
|
895
906
|
depBumps: {
|
|
@@ -945,6 +956,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
945
956
|
}[] | undefined;
|
|
946
957
|
remediation?: string | undefined;
|
|
947
958
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
959
|
+
revertDetail?: string | undefined;
|
|
948
960
|
inScope?: boolean | undefined;
|
|
949
961
|
}[];
|
|
950
962
|
secrets: {
|
|
@@ -974,6 +986,7 @@ declare const ReportSchema: z.ZodObject<{
|
|
|
974
986
|
}[] | undefined;
|
|
975
987
|
remediation?: string | undefined;
|
|
976
988
|
revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
|
|
989
|
+
revertDetail?: string | undefined;
|
|
977
990
|
inScope?: boolean | undefined;
|
|
978
991
|
}[];
|
|
979
992
|
depBumps: {
|
|
@@ -1155,6 +1168,7 @@ type AuditResult = {
|
|
|
1155
1168
|
type FixOutcome = {
|
|
1156
1169
|
kept: boolean;
|
|
1157
1170
|
reason?: RevertReason;
|
|
1171
|
+
detail?: string;
|
|
1158
1172
|
usage?: AiUsage;
|
|
1159
1173
|
};
|
|
1160
1174
|
type OrchestrateDeps = {
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClaudeSession, ConfigSchema, EventBus, FindingSchema, FindingStore, ReportBuilder, ReportSchema, Snapshot, addUsage, applyCliOverrides, assertGitRepo, buildProgram, changedFiles, changedVsHead, detectPackageManager, dispatch, filterToChanged, fingerprint, groupRemaining, isAvailable, loadConfig, normalize, orchestrate, planWork, renderSummary, retryCommand, revertFile, route, runScanner, scopeFindings, showCommand, trackForTool, zeroUsage } from "./config-
|
|
1
|
+
import { ClaudeSession, ConfigSchema, EventBus, FindingSchema, FindingStore, ReportBuilder, ReportSchema, Snapshot, addUsage, applyCliOverrides, assertGitRepo, buildProgram, changedFiles, changedVsHead, detectPackageManager, dispatch, filterToChanged, fingerprint, groupRemaining, isAvailable, loadConfig, normalize, orchestrate, planWork, renderSummary, retryCommand, revertFile, route, runScanner, scopeFindings, showCommand, trackForTool, zeroUsage } from "./config-DMOjMbMD.js";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname } from "node:path";
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tend-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Audit a JS/TS repo with established scanners, then fix the findings with parallel AI sessions in a safe scan-fix-rescan loop.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lint",
|
|
@@ -11,7 +11,16 @@
|
|
|
11
11
|
"static-analysis"
|
|
12
12
|
],
|
|
13
13
|
"license": "MIT",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/Njunge11/tend.git"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/Njunge11/tend/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/Njunge11/tend#readme",
|
|
14
22
|
"type": "module",
|
|
23
|
+
"packageManager": "pnpm@10.33.0",
|
|
15
24
|
"engines": {
|
|
16
25
|
"node": ">=20"
|
|
17
26
|
},
|
|
@@ -33,6 +42,7 @@
|
|
|
33
42
|
"prepublishOnly": "tsdown",
|
|
34
43
|
"test": "vitest run",
|
|
35
44
|
"test:watch": "vitest",
|
|
45
|
+
"test:coverage": "vitest run --coverage",
|
|
36
46
|
"typecheck": "tsc --noEmit"
|
|
37
47
|
},
|
|
38
48
|
"dependencies": {
|