@afokapu/atdd-bun 0.10.52 → 0.10.53
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 +10 -0
- package/integrity.json +4 -4
- package/package.json +1 -1
- package/src/cli.ts +9 -4
- package/src/ratchet.ts +11 -0
package/README.md
CHANGED
|
@@ -143,6 +143,16 @@ The command runs the same installed detectors against an isolated exact base and
|
|
|
143
143
|
|
|
144
144
|
Fingerprints are SHA-256 of a versioned rule, normalized repository-relative path, and semantic subject where supplied; line/column, rendered evidence, source text, absolute paths, and runtime data are excluded. Ratchet findings are unrelated to Bun `test.failing()` or JUnit/behavioral-test baselines.
|
|
145
145
|
|
|
146
|
+
### One-time explicit profile activation
|
|
147
|
+
|
|
148
|
+
When an existing exact main has debt under a smaller explicit profile list, a separately governed adoption commit may expand that list without accepting the debt. The base and candidate are both judged with the candidate's newly selected profile set, so old findings are `carried`, candidate-only findings remain `new` and reject `reject-new`, and removals are reported as `resolved`:
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
bun run atdd-bun --profile flow,traceability --ratchet --ratchet-activate-profiles --base <40-character-reviewed-main-sha>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
This is an activation-only exception to the ordinary equal-context rule, not a baseline migration. It requires an explicit candidate `profiles:` list, an explicit base list that is a strict subset of it, and identical non-profile policy/configuration. A removal, implicit/default-list adoption, unrelated configuration change, dirty tree, unavailable/non-ancestor base, or omission of `--ratchet-activate-profiles` fails closed. The command stores no activation state or accepted findings; after the governed expansion lands, use ordinary `--ratchet` with exact matching context. Strict non-ratchet enforcement remains unchanged.
|
|
155
|
+
|
|
146
156
|
## Docs-site theme
|
|
147
157
|
|
|
148
158
|
A repository that publishes its AsciiDoc docs as a site does not need its own theme.
|
package/integrity.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.10.
|
|
2
|
+
"version": "0.10.53",
|
|
3
3
|
"files": {
|
|
4
4
|
"HOOK_AUDIT.md": "5329d840db37671b1918f688ead26865473b87db73dbc75f7c8b2a8bbe8d6d43",
|
|
5
5
|
"PLANNER_PORT.md": "fb5935bac8b7ac18994de21e43ace3a5ef8cd55f85b0e3349fca261280054f11",
|
|
6
|
-
"README.md": "
|
|
6
|
+
"README.md": "e3d4858a387637e74294f5e249ab2c377a57912363136c3e19dc3c1c3f3b3c4c",
|
|
7
7
|
"bunfig.toml": "b9fc65eca9014c5179380259d70e76385a6a80788fa9a2df5fb3eaa5554fd2fe",
|
|
8
8
|
"conventions/_profiles/architecture.yaml": "f1808768b720a4e476047e4a0912002ca673946562cea9aeef5d0c214828d93a",
|
|
9
9
|
"conventions/_profiles/coder.yaml": "3fb191556a64c9ebcf249516afa189afca24da9b22fd40b2fc66908196cdfb78",
|
|
@@ -1195,7 +1195,7 @@
|
|
|
1195
1195
|
"relationships.yaml": "5860a308ebc3ee7fa8172fc2c6633984000ab3003f0ae4b6fa28db48879eda22",
|
|
1196
1196
|
"src/agent.ts": "6d6c6e75908af8fbab13432f0001b0374bb25cf3dee46ba218dfd67e0090cb56",
|
|
1197
1197
|
"src/ci.ts": "67e54d2cbfc44a9e42837d5e750af526d6255c539d3c452a4d5fca3226c0d9ac",
|
|
1198
|
-
"src/cli.ts": "
|
|
1198
|
+
"src/cli.ts": "c4ede85983445a6388bf74bbccf1251dd45df2788a699f1bf2250fa0fda3c516",
|
|
1199
1199
|
"src/docs-capability.ts": "bdeeb414649049b1cd4fa8008cada3a576318be51c43bec91bfa46a8e250c270",
|
|
1200
1200
|
"src/enforce.ts": "7e6b3a1fc7c90f8e1836ab3e4655778fb569a63be5e7c199de44024fc003e6be",
|
|
1201
1201
|
"src/hooks.ts": "0b4ca8c857e637bbd144e737e78eda924e3cba7b038c0abe5e6916d200d73068",
|
|
@@ -1206,7 +1206,7 @@
|
|
|
1206
1206
|
"src/planner-schema-validator.ts": "ce529c0936171075e93c7539b3655fe895a98dd2973ebda5775958e6ebc316d9",
|
|
1207
1207
|
"src/planner-validators.ts": "99adeb65f579af923c11f21a8f55cfb9993b007fd8df59c5f764696b55379cfc",
|
|
1208
1208
|
"src/profile-registry.ts": "5a7761d324181ae27deb51f198d63648a4c99e858b4de98b54d35e6cf8a39fe7",
|
|
1209
|
-
"src/ratchet.ts": "
|
|
1209
|
+
"src/ratchet.ts": "1e90fba040fd90437cd9d0300bcd2dc575a3952a7e5919cc2d5c8ff59814f1f1",
|
|
1210
1210
|
"src/register.ts": "6a2f1c6b8df0dc9c8f45df8ec9fac2be29044e048b08c8ffe423410e94dadedd",
|
|
1211
1211
|
"src/release.ts": "7b0fe444ee81f476f53b9c21b6c347ef588ee616c60211419cf984132be768ba",
|
|
1212
1212
|
"src/setup.ts": "38233265afedc63499bbef3b5403889651add335a70efd3813254ba53f4fc4fe",
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { enforce, enabledProfiles, flowCompatibilityDiagnostic, normalizeProfileName, profileNames, type Profile } from "./enforce";
|
|
3
|
-
import { compareFindings, contextDigest, parseRatchetPolicy } from "./ratchet";
|
|
3
|
+
import { activationContextDigest, compareFindings, contextDigest, isStrictProfileExpansion, parseRatchetPolicy } from "./ratchet";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
@@ -19,7 +19,7 @@ const args = process.argv.slice(2);
|
|
|
19
19
|
const usage = {
|
|
20
20
|
command: "atdd-bun",
|
|
21
21
|
usage: [
|
|
22
|
-
"atdd-bun [profile ...] [--root <path>] [--ratchet --base <full-sha>]",
|
|
22
|
+
"atdd-bun [profile ...] [--root <path>] [--ratchet --base <full-sha> [--ratchet-activate-profiles]]",
|
|
23
23
|
"atdd-bun init [--replace]",
|
|
24
24
|
"atdd-bun hooks <install|uninstall|status> [--replace]",
|
|
25
25
|
"atdd-bun worktree <start|finish|status>",
|
|
@@ -140,6 +140,8 @@ const git = async (directory: string, gitArgs: string[]) => {
|
|
|
140
140
|
return { code: await child.exited, out: (await new Response(child.stdout).text()).trim(), err: (await new Response(child.stderr).text()).trim() };
|
|
141
141
|
};
|
|
142
142
|
const stable = (items: string[]) => [...new Set(items)].sort();
|
|
143
|
+
const profileActivation = args.includes("--ratchet-activate-profiles");
|
|
144
|
+
if (profileActivation && !args.includes("--ratchet")) fail("--ratchet-activate-profiles requires --ratchet");
|
|
143
145
|
if (!args.includes("--ratchet")) {
|
|
144
146
|
const violations = await enforce({ root, profiles: normalizedRequested as Profile[] });
|
|
145
147
|
printViolations(violations);
|
|
@@ -152,6 +154,7 @@ if (!args.includes("--ratchet")) {
|
|
|
152
154
|
if (!policy) fail("--ratchet requires an explicit atdd-bun.yaml ratchet policy");
|
|
153
155
|
const candidateProfiles = normalizedRequested.includes("all") ? await enabledProfiles(candidateRoot) : normalizedRequested;
|
|
154
156
|
if (stable(policy.profiles).join(",") !== stable(candidateProfiles).join(",")) fail("ratchet.profiles must exactly equal the selected profiles");
|
|
157
|
+
if (profileActivation && (!Array.isArray(candidateConfig.profiles) || stable(await enabledProfiles(candidateRoot)).join(",") !== stable(candidateProfiles).join(","))) fail("profile activation requires the explicitly configured candidate profile set to be selected");
|
|
155
158
|
if ((await git(candidateRoot, ["status", "--porcelain"])).out) fail("--ratchet requires a porcelain-clean candidate worktree");
|
|
156
159
|
const resolved = await git(candidateRoot, ["rev-parse", "--verify", `${base}^{commit}`]);
|
|
157
160
|
if (resolved.code || resolved.out.toLowerCase() !== base.toLowerCase()) fail(`ratchet base ${base} is unavailable or not a full exact commit`);
|
|
@@ -164,8 +167,10 @@ if (!args.includes("--ratchet")) {
|
|
|
164
167
|
const checkedOut = await git(scratch, ["checkout", "--detach", base]);
|
|
165
168
|
if (checkedOut.code) { console.error(`could not checkout ratchet base: ${checkedOut.err || checkedOut.out}`); process.exitCode = 1; }
|
|
166
169
|
else {
|
|
167
|
-
const baseConfig = await configAt(scratch), baseProfiles = normalizedRequested.includes("all") ? await enabledProfiles(scratch) : normalizedRequested;
|
|
168
|
-
|
|
170
|
+
const baseConfig = await configAt(scratch), baseProfiles = profileActivation ? await enabledProfiles(scratch) : normalizedRequested.includes("all") ? await enabledProfiles(scratch) : normalizedRequested;
|
|
171
|
+
const ordinaryContextMatches = stable(baseProfiles).join(",") === stable(candidateProfiles).join(",") && contextDigest(baseConfig, baseProfiles) === contextDigest(candidateConfig, candidateProfiles);
|
|
172
|
+
const activationIsValid = Array.isArray(baseConfig.profiles) && isStrictProfileExpansion(baseProfiles, candidateProfiles) && activationContextDigest(baseConfig) === activationContextDigest(candidateConfig);
|
|
173
|
+
if (!(profileActivation ? activationIsValid : ordinaryContextMatches)) { console.error(profileActivation ? "ratchet profile activation requires an explicit monotonic profile expansion and identical non-profile context" : "ratchet base and candidate profile/context differ; use a separately governed adoption path"); process.exitCode = 1; }
|
|
169
174
|
else {
|
|
170
175
|
const [baseFindings, candidateFindings] = await Promise.all([enforce({ root: scratch, profiles: candidateProfiles as Profile[] }), enforce({ root: candidateRoot, profiles: candidateProfiles as Profile[] })]);
|
|
171
176
|
const normalize = (findings: Awaited<ReturnType<typeof enforce>>, directory: string) => findings.map(finding => ({ ...finding, file: relative(directory, finding.file).replaceAll("\\", "/") }));
|
package/src/ratchet.ts
CHANGED
|
@@ -37,6 +37,17 @@ export function contextDigest(config: Record<string, unknown>, profiles: string[
|
|
|
37
37
|
return sha256({ format: "atdd-bun.ratchet-context/v1", profiles: [...profiles].sort(), policy });
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/** Activation is a one-time, explicitly requested profile-list expansion; every other policy input remains identical. */
|
|
41
|
+
export function activationContextDigest(config: Record<string, unknown>): string {
|
|
42
|
+
const { ratchet: _ratchet, profiles: _profiles, ...policy } = config;
|
|
43
|
+
return sha256({ format: "atdd-bun.ratchet-activation-context/v1", policy });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function isStrictProfileExpansion(base: string[], candidate: string[]): boolean {
|
|
47
|
+
const before = new Set(base), after = new Set(candidate);
|
|
48
|
+
return before.size < after.size && [...before].every(profile => after.has(profile));
|
|
49
|
+
}
|
|
50
|
+
|
|
40
51
|
export function parseRatchetPolicy(config: Record<string, unknown>): RatchetPolicy | null {
|
|
41
52
|
if (config.ratchet === undefined) return null;
|
|
42
53
|
const value = config.ratchet;
|