@savvy-web/silk-effects 10.2.0 → 11.0.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.
@@ -1,9 +1,9 @@
1
- import { parseKitMarkdownBody } from "../utils/markdown-emit.js";
2
1
  import { contentStructure } from "../rules/content-structure.js";
3
2
  import { dependencyTableFormat } from "../rules/dependency-table-format.js";
4
3
  import { headingHierarchy } from "../rules/heading-hierarchy.js";
5
4
  import { requiredSections } from "../rules/required-sections.js";
6
5
  import { uncategorizedContent } from "../rules/uncategorized-content.js";
6
+ import { parseKitMarkdownBody } from "../utils/markdown-emit.js";
7
7
  import { readFileSync, readdirSync } from "node:fs";
8
8
  import { join } from "node:path";
9
9
 
@@ -1,4 +1,3 @@
1
- import { emitKitMarkdown, parseKitMarkdown } from "../utils/markdown-emit.js";
2
1
  import { aggregateDependencyTables } from "../transforms/aggregate-dependency-tables.js";
3
2
  import { contributorFootnotes } from "../transforms/contributor-footnotes.js";
4
3
  import { deduplicateItems } from "../transforms/deduplicate-items.js";
@@ -7,6 +6,7 @@ import { maintenanceNote } from "../transforms/maintenance-note.js";
7
6
  import { mergeSections } from "../transforms/merge-sections.js";
8
7
  import { normalizeFormat } from "../transforms/normalize-format.js";
9
8
  import { reorderSections } from "../transforms/reorder-sections.js";
9
+ import { emitKitMarkdown, parseKitMarkdown } from "../utils/markdown-emit.js";
10
10
  import { readFileSync, writeFileSync } from "node:fs";
11
11
 
12
12
  // src/changesets/api/transformer.ts
@@ -1,10 +1,10 @@
1
1
  import { resolveCommitType } from "../categories/index.js";
2
- import { GitHubService } from "../services/github.js";
3
- import { logWarning } from "../utils/logger.js";
4
- import { emitKitMarkdown, parseKitMarkdown } from "../utils/markdown-emit.js";
5
2
  import { GitHubInfoSchema } from "../schemas/github.js";
3
+ import { GitHubService } from "../services/github.js";
6
4
  import { parseCommitMessage } from "../utils/commit-parser.js";
7
5
  import { parseIssueReferences } from "../utils/issue-refs.js";
6
+ import { logWarning } from "../utils/logger.js";
7
+ import { emitKitMarkdown, parseKitMarkdown } from "../utils/markdown-emit.js";
8
8
  import { sectionsOf } from "../utils/section-parser.js";
9
9
  import { formatChangelogEntry, formatPRAndUserAttribution } from "./formatting.js";
10
10
  import { Effect, Result, Schema } from "effect";
@@ -1,36 +1,36 @@
1
1
  import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
2
  import { Categories } from "./api/categories.js";
3
- import { ChangesetIOError, ChangesetValidationError, ConfigurationError, GitError, GitHubApiError, HookReplayError, MarkdownParseError, ReleasePlanError, VersionFileError } from "./errors.js";
4
- import { JsonPathSchema, LegacyVersionFileConfigSchema, LegacyVersionFilesSchema, VersionFileConfigSchema, VersionFilesSchema } from "./schemas/version-files.js";
5
- import { GlobSchema, PackageScopeSchema, PackagesRecordSchema } from "./schemas/package-scope.js";
6
- import { ChangesetOptionsSchema, RepoSchema } from "./schemas/options.js";
7
- import { GitHubService, makeGitHubTest } from "./services/github.js";
8
- import { ChangesetLogMode } from "./utils/logger.js";
9
- import { NonEmptyString, PositiveInteger } from "./schemas/primitives.js";
10
- import { DependencyActionSchema, DependencyTableRowSchema, DependencyTableSchema, DependencyTableTypeSchema, VERSION_RE, VersionOrEmptySchema } from "./schemas/dependency-table.js";
11
- import { serializeDependencyTableToMarkdown } from "./utils/dependency-table.js";
12
- import { GitHubInfoSchema, IssueNumberSchema, UrlOrMarkdownLinkSchema, UsernameSchema } from "./schemas/github.js";
13
- import changelogFunctions, { makeChangelogFunctions } from "./changelog/index.js";
14
3
  import { Changelog } from "./api/changelog.js";
15
4
  import { DependencyTable } from "./api/dependency-table.js";
16
5
  import { ChangesetLinter } from "./api/linter.js";
17
6
  import { ChangelogTransformer } from "./api/transformer.js";
7
+ import changelogFunctions, { makeChangelogFunctions } from "./changelog/index.js";
18
8
  import { vanillaChangelogFunctions } from "./changelog/vanilla.js";
19
- import { ClassificationReasonSchema, ClassificationSchema, ConfigInspector, InspectedConfigSchema, ResolvedPackageScopeSchema, ResolvedVersionFileSchema, makeConfigInspectorTest } from "./services/config-inspector.js";
20
9
  import { BranchAnalysisSchema, BranchAnalyzer, BranchFileEntrySchema, FileStatusSchema, makeBranchAnalyzerTest } from "./services/branch-analyzer.js";
21
10
  import { ChangelogService } from "./services/changelog.js";
22
- import { computeWorkspaceDependencyDiffs } from "./utils/dep-diff.js";
23
- import { gitMergeBase } from "./utils/git.js";
24
- import { listPublishablePackageNames } from "./utils/publishability.js";
11
+ import { ClassificationReasonSchema, ClassificationSchema, ConfigInspector, InspectedConfigSchema, ResolvedPackageScopeSchema, ResolvedVersionFileSchema, makeConfigInspectorTest } from "./services/config-inspector.js";
25
12
  import { DepsRegen, DepsRegenDefault, isPureDependencyChangeset, makeDepsRegenDefault, parseChangesetPackages } from "./services/deps-regen.js";
13
+ import { GitHubService, makeGitHubTest } from "./services/github.js";
26
14
  import { MaintenanceReasonSchema, MaintenanceTriggerSchema, deriveMaintenanceReason } from "./services/maintenance-reason.js";
27
- import { VersionFiles } from "./utils/version-files.js";
28
15
  import { ReleasePlanner, makeReleasePlannerTest } from "./services/release-planner.js";
16
+ import { ChangesetIOError, ChangesetValidationError, ConfigurationError, GitError, GitHubApiError, HookReplayError, MarkdownParseError, ReleasePlanError, VersionFileError } from "./errors.js";
29
17
  import { SectionCategorySchema } from "./categories/types.js";
30
- import { CommitHashSchema, VersionTypeSchema } from "./schemas/git.js";
31
18
  import { ChangesetSchema, ChangesetSummarySchema, DependencyTypeSchema, DependencyUpdateSchema } from "./schemas/changeset.js";
19
+ import { DependencyActionSchema, DependencyTableRowSchema, DependencyTableSchema, DependencyTableTypeSchema, VERSION_RE, VersionOrEmptySchema } from "./schemas/dependency-table.js";
32
20
  import { CoexistingChangesetSchema, RegenDiffRowSchema, RegenPlanSchema, RegenResultSchema } from "./schemas/deps-regen.js";
21
+ import { CommitHashSchema, VersionTypeSchema } from "./schemas/git.js";
22
+ import { GitHubInfoSchema, IssueNumberSchema, UrlOrMarkdownLinkSchema, UsernameSchema } from "./schemas/github.js";
23
+ import { ChangesetOptionsSchema, RepoSchema } from "./schemas/options.js";
24
+ import { GlobSchema, PackageScopeSchema, PackagesRecordSchema } from "./schemas/package-scope.js";
25
+ import { NonEmptyString, PositiveInteger } from "./schemas/primitives.js";
33
26
  import { AppliedReleaseEntrySchema, AppliedReleaseSchema, BumpTypeSchema, ChangesetPreviewSchema, PendingChangesetSchema, PreviewReleaseSchema, VersionFileUpdateRecordSchema } from "./schemas/release-plan.js";
27
+ import { JsonPathSchema, LegacyVersionFileConfigSchema, LegacyVersionFilesSchema, VersionFileConfigSchema, VersionFilesSchema } from "./schemas/version-files.js";
28
+ import { computeWorkspaceDependencyDiffs } from "./utils/dep-diff.js";
29
+ import { serializeDependencyTableToMarkdown } from "./utils/dependency-table.js";
30
+ import { gitMergeBase } from "./utils/git.js";
31
+ import { ChangesetLogMode } from "./utils/logger.js";
32
+ import { listPublishablePackageNames } from "./utils/publishability.js";
33
+ import { VersionFiles } from "./utils/version-files.js";
34
34
  import { ContentStructureRule } from "./markdownlint/rules/content-structure.js";
35
35
  import { DependencyTableFormatRule } from "./markdownlint/rules/dependency-table-format.js";
36
36
  import { HeadingHierarchyRule } from "./markdownlint/rules/heading-hierarchy.js";
@@ -1,7 +1,7 @@
1
- import { parseDependencyTable } from "../utils/dependency-table.js";
2
1
  import { RULE_DOCS } from "../constants.js";
3
- import { finding } from "./types.js";
4
2
  import { scanDependencySection } from "../utils/dependency-section.js";
3
+ import { parseDependencyTable } from "../utils/dependency-table.js";
4
+ import { finding } from "./types.js";
5
5
  import { Mdast } from "@effected/markdown";
6
6
 
7
7
  // src/changesets/rules/dependency-table-format.ts
@@ -1,5 +1,5 @@
1
- import { NonEmptyString } from "./primitives.js";
2
1
  import { DependencyActionSchema, DependencyTableTypeSchema } from "./dependency-table.js";
2
+ import { NonEmptyString } from "./primitives.js";
3
3
  import { Schema } from "effect";
4
4
 
5
5
  // src/changesets/schemas/deps-regen.ts
@@ -1,5 +1,5 @@
1
- import { PositiveInteger } from "./primitives.js";
2
1
  import { MARKDOWN_LINK_PATTERN } from "../utils/markdown-link.js";
2
+ import { PositiveInteger } from "./primitives.js";
3
3
  import { Schema } from "effect";
4
4
 
5
5
  // src/changesets/schemas/github.ts
@@ -1,6 +1,6 @@
1
1
  import { ConfigurationError } from "../errors.js";
2
- import { LegacyVersionFilesSchema } from "./version-files.js";
3
2
  import { PackagesRecordSchema } from "./package-scope.js";
3
+ import { LegacyVersionFilesSchema } from "./version-files.js";
4
4
  import { Effect, Schema } from "effect";
5
5
 
6
6
  // src/changesets/schemas/options.ts
@@ -1,8 +1,8 @@
1
- import { ConfigurationError } from "../errors.js";
2
- import { ChangesetOptionsSchema } from "../schemas/options.js";
3
1
  import { MARKDOWNLINT_CONFIG_PATH } from "../../lint/cli/sections.js";
4
2
  import { ChangesetConfigReader } from "../../services/ChangesetConfigReader.js";
5
3
  import { SilkPublishability, readTargetsBinding } from "../../services/SilkPublishability.js";
4
+ import { ConfigurationError } from "../errors.js";
5
+ import { ChangesetOptionsSchema } from "../schemas/options.js";
6
6
  import { Context, Effect, FileSystem, Layer, Path, Result, Schema } from "effect";
7
7
  import { isAbsolute, join, relative, resolve, sep } from "node:path";
8
8
  import { GlobPattern, GlobPatternOptions } from "@effected/glob";
@@ -1,12 +1,12 @@
1
- import { ChangesetIOError, HookReplayError } from "../errors.js";
2
- import { serializeDependencyTableToMarkdown, sortDependencyRows } from "../utils/dependency-table.js";
3
- import { ChangesetConfigReader } from "../../services/ChangesetConfigReader.js";
4
1
  import { ChangesetConfig } from "../../services/ChangesetConfig.js";
2
+ import { ChangesetConfigReader } from "../../services/ChangesetConfigReader.js";
5
3
  import { SilkPublishability } from "../../services/SilkPublishability.js";
6
- import { ConfigInspector } from "./config-inspector.js";
4
+ import { ChangesetIOError, HookReplayError } from "../errors.js";
7
5
  import { computeWorkspaceDependencyDiffs } from "../utils/dep-diff.js";
6
+ import { serializeDependencyTableToMarkdown, sortDependencyRows } from "../utils/dependency-table.js";
8
7
  import { gitListChangesetFilesAtRef, gitMergeBase, gitResolveRef, gitShowFileAtRef } from "../utils/git.js";
9
8
  import { listPublishablePackageNames } from "../utils/publishability.js";
9
+ import { ConfigInspector } from "./config-inspector.js";
10
10
  import { Context, Data, Effect, FileSystem, Layer, Option } from "effect";
11
11
  import { basename, join, resolve } from "node:path";
12
12
  import { Git } from "@effected/git";
@@ -1,8 +1,8 @@
1
- import { ReleasePlanError } from "../errors.js";
2
1
  import { ChangelogTransformer } from "../api/transformer.js";
2
+ import { ReleasePlanError } from "../errors.js";
3
+ import { VersionFiles } from "../utils/version-files.js";
3
4
  import { ConfigInspector } from "./config-inspector.js";
4
5
  import { deriveMaintenanceReason } from "./maintenance-reason.js";
5
- import { VersionFiles } from "../utils/version-files.js";
6
6
  import { Context, Data, Effect, FileSystem, Layer } from "effect";
7
7
  import { dirname, isAbsolute, join, relative } from "node:path";
8
8
  import { applyReleasePlan } from "@changesets/apply-release-plan";
@@ -1,5 +1,5 @@
1
- import { collapseDependencyRows, parseDependencyTable, serializeDependencyTable, sortDependencyRows } from "../utils/dependency-table.js";
2
1
  import { getBlockSections, getHeadingText, getVersionBlocks } from "../utils/blocks.js";
2
+ import { collapseDependencyRows, parseDependencyTable, serializeDependencyTable, sortDependencyRows } from "../utils/dependency-table.js";
3
3
  import { Heading, List, ListItem, Root, Text } from "@effected/markdown";
4
4
 
5
5
  // src/changesets/transforms/aggregate-dependency-tables.ts
@@ -46,7 +46,7 @@ const DEP_TYPE_MAP = [
46
46
  * @remarks
47
47
  * Uses `resolveIn` rather than the workspace-wide `resolve`. Both consult the
48
48
  * ref's own lockfile importer entries when a `catalog:` specifier is not in the
49
- * catalog set — which is what makes hook-injected catalogs (`catalog:effect:peers`,
49
+ * catalog set — which is what makes hook-injected catalogs (`catalog:effected`,
50
50
  * injected by a config-dependency pnpmfile and recorded in neither
51
51
  * `pnpm-workspace.yaml` nor the lockfile's `catalogs:` block) resolvable at all.
52
52
  * The workspace-wide form abstains whenever two importers disagree on a
@@ -1,7 +1,7 @@
1
1
  import { detectDCO } from "../detection/dco.js";
2
- import { COMMIT_TYPES } from "./rules.js";
3
2
  import { createPromptConfig } from "../prompt/config.js";
4
3
  import { createScopeEnumRule, silkPlugin } from "./plugins.js";
4
+ import { COMMIT_TYPES } from "./rules.js";
5
5
 
6
6
  // src/commitlint/config/factory.ts
7
7
  /**
@@ -1,5 +1,8 @@
1
+ import { Option } from "effect";
1
2
  import { existsSync } from "node:fs";
2
3
  import { dirname, join, resolve } from "node:path";
4
+ import { Walker } from "@effected/walker";
5
+ import { nodeWalkerSyncOps } from "@effected/walker/node-sync";
3
6
 
4
7
  // src/commitlint/detection/dco.ts
5
8
  /**
@@ -24,13 +27,12 @@ const ROOT_MARKERS = [
24
27
  * @internal
25
28
  */
26
29
  function findProjectRoot(cwd) {
27
- let dir = resolve(cwd);
28
- while (true) {
29
- for (const marker of ROOT_MARKERS) if (existsSync(join(dir, marker))) return dir;
30
- const parent = dirname(dir);
31
- if (parent === dir) return null;
32
- dir = parent;
33
- }
30
+ const dirs = Walker.ascendSync(resolve(cwd), { path: nodeWalkerSyncOps.path });
31
+ const marker = Walker.findUpwardSync(dirs, (dir) => ROOT_MARKERS.map((name) => join(dir, name)), nodeWalkerSyncOps);
32
+ return Option.match(marker, {
33
+ onNone: () => null,
34
+ onSome: dirname
35
+ });
34
36
  }
35
37
  /**
36
38
  * Detect if DCO signoff should be required.
@@ -10,12 +10,23 @@ import { parse } from "shell-quote";
10
10
  * Heredocs surface as already-substituted strings inside Claude's tool
11
11
  * envelope, so we don't need full shell semantics — just argv tokenization.
12
12
  *
13
- * Operators (`&&`, `||`, `|`, `;`) are filtered out by `shell-quote`. The
14
- * parser inspects only `tokens[0]` and `tokens[1]`, so a compound command
15
- * like `true && git commit -m "x"` will be classified as `unknown` rather
16
- * than recursed into. That is the intended behaviour for the scaffold:
17
- * compound shapes are uncommon in agent-emitted commands, and silently
18
- * dropping them is safer than misattributing extracted state.
13
+ * `shell-quote` returns control operators (`&&`, `||`, `;`, `|`, `&`, and
14
+ * the subshell parentheses) as `{ op }` objects. The command is split on them
15
+ * into simple commands, leading `NAME=value` assignments are dropped from each,
16
+ * and the FIRST simple command that is a `git commit` or `gh pr create`/`edit`
17
+ * is classified. Splitting is what keeps attribution exact: a chained
18
+ * `git add -A && git commit …` is still checked, and a later command's flags
19
+ * (`… && git push --no-verify`) never leak into the commit's. An operator
20
+ * inside quotes is part of a word, never a split point (#856).
21
+ *
22
+ * `shell-quote` reads an unquoted newline as plain whitespace, but to the shell
23
+ * it ends a command just like `;`. {@link separateLines} therefore rewrites
24
+ * each unquoted, unescaped newline outside a `$(…)` to `;` first, joins
25
+ * backslash-continued lines, and drops heredoc bodies, which are input text
26
+ * and never commands.
27
+ *
28
+ * Interim: spencerbeggs/effected#1204 proposes a kit shell-syntax segmenter
29
+ * that would replace `shell-quote` here.
19
30
  *
20
31
  * @internal
21
32
  */
@@ -26,8 +37,158 @@ function emptyFlags() {
26
37
  amend: false
27
38
  };
28
39
  }
40
+ /** Control operators that end one simple command and start the next. */
41
+ const CONTROL_OPERATORS = /* @__PURE__ */ new Set([
42
+ "&&",
43
+ "||",
44
+ ";",
45
+ ";;",
46
+ "|",
47
+ "|&",
48
+ "&",
49
+ "(",
50
+ ")"
51
+ ]);
52
+ /** A leading shell variable assignment (`NAME=value`), which is not the command name. */
53
+ const ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=/;
54
+ /** A heredoc redirect: `<<` or `<<-`, then an optionally quoted delimiter word. */
55
+ const HEREDOC = /^<<(-?)[ \t]*(['"]?)([A-Za-z0-9_.-]+)\2/;
56
+ /**
57
+ * Rewrite unquoted newlines to `;` so `shell-quote` sees them as separators.
58
+ *
59
+ * Tracks single quotes, double quotes (with backslash escapes) and `$(…)`
60
+ * nesting outside quotes, and leaves newlines inside any of them alone. A
61
+ * backslash-newline outside quotes is a line continuation and is removed. A
62
+ * heredoc's body, everything after the line that opened it up to its
63
+ * delimiter line, is dropped. Unterminated quotes or heredocs simply run to
64
+ * the end of the string.
65
+ */
66
+ function separateLines(command) {
67
+ let out = "";
68
+ let quote = null;
69
+ let depth = 0;
70
+ const pending = [];
71
+ let i = 0;
72
+ while (i < command.length) {
73
+ const ch = command[i];
74
+ if (quote === "'") {
75
+ out += ch;
76
+ if (ch === "'") quote = null;
77
+ i += 1;
78
+ continue;
79
+ }
80
+ if (quote === "\"") {
81
+ if (ch === "\\" && i + 1 < command.length) {
82
+ out += ch + command[i + 1];
83
+ i += 2;
84
+ continue;
85
+ }
86
+ out += ch;
87
+ if (ch === "\"") quote = null;
88
+ i += 1;
89
+ continue;
90
+ }
91
+ if (ch === "\\" && command[i + 1] === "\n") {
92
+ i += 2;
93
+ continue;
94
+ }
95
+ if (ch === "\\" && i + 1 < command.length) {
96
+ out += ch + command[i + 1];
97
+ i += 2;
98
+ continue;
99
+ }
100
+ if (ch === "#" && (out === "" || /[\s;&|(]$/.test(out))) {
101
+ while (i < command.length && command[i] !== "\n") i += 1;
102
+ continue;
103
+ }
104
+ if (ch === "'" || ch === "\"") {
105
+ quote = ch;
106
+ out += ch;
107
+ i += 1;
108
+ continue;
109
+ }
110
+ if (ch === "$" && command[i + 1] === "(") {
111
+ depth += 1;
112
+ out += "$(";
113
+ i += 2;
114
+ continue;
115
+ }
116
+ if (ch === ")" && depth > 0) {
117
+ depth -= 1;
118
+ out += ch;
119
+ i += 1;
120
+ continue;
121
+ }
122
+ if (ch === "<" && command[i + 1] === "<" && command[i + 2] !== "<") {
123
+ const match = HEREDOC.exec(command.slice(i));
124
+ if (match !== null) {
125
+ pending.push({
126
+ delimiter: match[3],
127
+ stripTabs: match[1] === "-"
128
+ });
129
+ out += match[0];
130
+ i += match[0].length;
131
+ continue;
132
+ }
133
+ }
134
+ if (ch === "\n") {
135
+ if (pending.length > 0) {
136
+ let lineStart = i + 1;
137
+ for (const { delimiter, stripTabs } of pending) while (lineStart <= command.length) {
138
+ const lineEnd = command.indexOf("\n", lineStart);
139
+ const end = lineEnd === -1 ? command.length : lineEnd;
140
+ const line = command.slice(lineStart, end);
141
+ lineStart = end + 1;
142
+ if ((stripTabs ? line.replace(/^\t+/, "") : line) === delimiter) break;
143
+ }
144
+ pending.length = 0;
145
+ out += depth > 0 ? "\n" : " ; ";
146
+ i = lineStart - 1;
147
+ if (i >= command.length) break;
148
+ i += 1;
149
+ continue;
150
+ }
151
+ out += depth > 0 ? ch : " ; ";
152
+ i += 1;
153
+ continue;
154
+ }
155
+ out += ch;
156
+ i += 1;
157
+ }
158
+ return out;
159
+ }
160
+ /**
161
+ * Split a command string into its simple commands' word lists. Non-control
162
+ * operator objects (redirections, globs, comments) are dropped, as before.
163
+ */
164
+ function simpleCommands(command) {
165
+ const segments = [];
166
+ let current = [];
167
+ for (const entry of parse(separateLines(command))) if (typeof entry === "string") current.push(entry);
168
+ else if ("op" in entry && CONTROL_OPERATORS.has(entry.op)) {
169
+ if (current.length > 0) segments.push(current);
170
+ current = [];
171
+ }
172
+ if (current.length > 0) segments.push(current);
173
+ return segments.map((words) => {
174
+ let start = 0;
175
+ while (start < words.length && ASSIGNMENT.test(words[start] ?? "")) start += 1;
176
+ return words.slice(start);
177
+ });
178
+ }
29
179
  function parseBashCommand(command) {
30
- const tokens = parse(command).filter((t) => typeof t === "string");
180
+ for (const tokens of simpleCommands(command)) {
181
+ const parsed = classify(tokens);
182
+ if (parsed.kind !== "unknown") return parsed;
183
+ }
184
+ return {
185
+ kind: "unknown",
186
+ message: null,
187
+ flags: emptyFlags(),
188
+ source: "none"
189
+ };
190
+ }
191
+ function classify(tokens) {
31
192
  if (tokens.length === 0) return {
32
193
  kind: "unknown",
33
194
  message: null,
@@ -1,14 +1,14 @@
1
1
  import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
- import { detectDCO } from "./detection/dco.js";
3
- import { COMMIT_TYPES, COMMIT_TYPE_DEFINITIONS, DCO_SIGNOFF_TEXT, TDD_SCOPE_PATTERN, TDD_STATES } from "./config/rules.js";
4
- import { TYPE_EMOJIS, TYPE_EMOJIS_UNICODE, getTypeEmoji } from "./prompt/emojis.js";
5
- import { createPromptConfig, createTypeEnum, defaultPromptConfig, emojiPromptConfig } from "./prompt/config.js";
6
2
  import { createConfig } from "./config/factory.js";
7
3
  import { decodeConfigOptions } from "./config/schema.js";
4
+ import { COMMIT_TYPES, COMMIT_TYPE_DEFINITIONS, DCO_SIGNOFF_TEXT, TDD_SCOPE_PATTERN, TDD_STATES } from "./config/rules.js";
8
5
  import staticConfig from "./static.js";
9
- import { ERROR_EXPLANATIONS, ERROR_SUGGESTIONS, getExplanation, getSuggestion } from "./formatter/messages.js";
10
6
  import { format } from "./formatter/format.js";
7
+ import { ERROR_EXPLANATIONS, ERROR_SUGGESTIONS, getExplanation, getSuggestion } from "./formatter/messages.js";
8
+ import { createPromptConfig, createTypeEnum, defaultPromptConfig, emojiPromptConfig } from "./prompt/config.js";
9
+ import { TYPE_EMOJIS, TYPE_EMOJIS_UNICODE, getTypeEmoji } from "./prompt/emojis.js";
11
10
  import { prompter } from "./prompt/prompter.js";
11
+ import { detectDCO } from "./detection/dco.js";
12
12
  import { detectScopes } from "./detection/scopes.js";
13
13
  import { PostToolUseEnvelope, PreToolUseEnvelope, SessionStartEnvelope } from "./hook/envelope.js";
14
14
  import { postToolUseAdvise, preToolUseAdvise, preToolUseAllow, preToolUseDeny, preToolUseSilent, sessionStartContext } from "./hook/output.js";
@@ -1,5 +1,5 @@
1
- import { COMMIT_TYPES, COMMIT_TYPE_DEFINITIONS, DCO_SIGNOFF_TEXT, TDD_SCOPE_PATTERN, TDD_STATES } from "./config/rules.js";
2
1
  import { silkPlugin } from "./config/plugins.js";
2
+ import { COMMIT_TYPES, COMMIT_TYPE_DEFINITIONS, DCO_SIGNOFF_TEXT, TDD_SCOPE_PATTERN, TDD_STATES } from "./config/rules.js";
3
3
 
4
4
  // src/commitlint/static.ts
5
5
  /**
package/index.js CHANGED
@@ -1,12 +1,12 @@
1
- import { ChangesetConfigReader } from "./services/ChangesetConfigReader.js";
2
- import { ChangesetConfig } from "./services/ChangesetConfig.js";
3
- import { SilkPublishability, readTargetsBinding } from "./services/SilkPublishability.js";
4
1
  import { changesets_exports } from "./changesets/index.js";
5
2
  import { commitlint_exports } from "./commitlint/index.js";
6
3
  import { lint_exports } from "./lint/index.js";
7
4
  import { repos_exports } from "./repos/index.js";
8
5
  import { BiomeSchemaSync, buildSchemaUrl, extractSemver } from "./services/BiomeSchemaSync.js";
6
+ import { ChangesetConfig } from "./services/ChangesetConfig.js";
7
+ import { ChangesetConfigReader } from "./services/ChangesetConfigReader.js";
9
8
  import { ConfigDiscovery } from "./services/ConfigDiscovery.js";
9
+ import { SilkPublishability, readTargetsBinding } from "./services/SilkPublishability.js";
10
10
  import { SilkWorkspaceAnalyzer } from "./services/SilkWorkspaceAnalyzer.js";
11
11
  import { turbo_exports } from "./turbo/index.js";
12
12
  import { AnalyzedWorkspace, BiomeSyncError, ChangesetConfigError, ConfigNotFoundError, LIFECYCLE_SCRIPTS_CONFIG_KEY, PrBody, PublishTargetBindingError, ReleaseChannelError, SavvyBaseSection, SavvyHooksSection, SavvyInstallSection, SavvyOkfSection, SavvyToolchainSection, SilkPublishConfig, WorkspaceAnalysis, WorkspaceAnalysisError, publishesBuiltLinkDirectory, savvyBasePreamble, savvyHooksHygiene, savvyInstallBlock, savvyInstallDeps, savvyOkfBlock, savvyOkfSync, savvyToolSection, savvyToolchainCheck } from "@savvy-web/silk-core";
package/lint/index.js CHANGED
@@ -1,9 +1,5 @@
1
1
  import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
- import { DEFAULT_CONFIG_PATH, HUSKY_HOOK_PATH, LegacySavvyLintHygieneDef, MARKDOWNLINT_CONFIG_PATH, POST_CHECKOUT_HOOK_PATH, POST_COMMIT_HOOK_PATH, POST_MERGE_HOOK_PATH, SavvyLintSectionDef, generateManagedContent, savvyLintBlock } from "./cli/sections.js";
3
2
  import { Handler } from "./Handler.js";
4
- import { Command } from "./utils/Command.js";
5
- import { Filter } from "./utils/Filter.js";
6
- import { getWorkspacePackagePaths, getWorkspacePackages, getWorkspaceRoot, isWorkspacePackagePath, resetWorkspaceCache } from "./utils/Workspace.js";
7
3
  import { Biome } from "./handlers/Biome.js";
8
4
  import { Markdown } from "./handlers/Markdown.js";
9
5
  import { PackageJson } from "./handlers/PackageJson.js";
@@ -14,6 +10,10 @@ import { TypeScript } from "./handlers/TypeScript.js";
14
10
  import { Yaml } from "./handlers/Yaml.js";
15
11
  import { createConfig } from "./config/createConfig.js";
16
12
  import { Preset } from "./config/Preset.js";
13
+ import { Command } from "./utils/Command.js";
14
+ import { Filter } from "./utils/Filter.js";
15
+ import { getWorkspacePackagePaths, getWorkspacePackages, getWorkspaceRoot, isWorkspacePackagePath, resetWorkspaceCache } from "./utils/Workspace.js";
16
+ import { DEFAULT_CONFIG_PATH, HUSKY_HOOK_PATH, LegacySavvyLintHygieneDef, MARKDOWNLINT_CONFIG_PATH, POST_CHECKOUT_HOOK_PATH, POST_COMMIT_HOOK_PATH, POST_MERGE_HOOK_PATH, SavvyLintSectionDef, generateManagedContent, savvyLintBlock } from "./cli/sections.js";
17
17
  import { MARKDOWNLINT_CONFIG, MARKDOWNLINT_SCHEMA, MARKDOWNLINT_TEMPLATE } from "./cli/templates/markdownlint.gen.js";
18
18
 
19
19
  // src/lint/index.ts
@@ -1,7 +1,8 @@
1
- import { Result } from "effect";
2
- import { existsSync } from "node:fs";
1
+ import { Option, Result } from "effect";
3
2
  import { dirname, join, resolve } from "node:path";
3
+ import { Walker } from "@effected/walker";
4
4
  import { detectPackageManagerSync } from "@effected/workspaces";
5
+ import { nodeWalkerSyncOps } from "@effected/walker/node-sync";
5
6
  import { LocalExec, Tool, makeToolDiscoverySync } from "@effected/commands";
6
7
  import { nodeSyncOps } from "@effected/workspaces/node-sync";
7
8
  import { execSync } from "node:child_process";
@@ -84,18 +85,13 @@ var Command = class Command {
84
85
  */
85
86
  static findRoot(cwd = process.cwd()) {
86
87
  if (Command.cachedRoot !== null) return Command.cachedRoot;
87
- let dir = resolve(cwd);
88
- while (true) {
89
- if (existsSync(join(dir, "package.json"))) {
90
- Command.cachedRoot = dir;
91
- return dir;
92
- }
93
- const parent = dirname(dir);
94
- if (parent === dir) break;
95
- dir = parent;
96
- }
97
- Command.cachedRoot = cwd;
98
- return cwd;
88
+ const dirs = Walker.ascendSync(resolve(cwd), { path: nodeWalkerSyncOps.path });
89
+ const manifest = Walker.findUpwardSync(dirs, (dir) => [join(dir, "package.json")], nodeWalkerSyncOps);
90
+ Command.cachedRoot = Option.match(manifest, {
91
+ onNone: () => cwd,
92
+ onSome: dirname
93
+ });
94
+ return Command.cachedRoot;
99
95
  }
100
96
  /**
101
97
  * Detect the package manager declared by the root package.json.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/silk-effects",
3
- "version": "10.2.0",
3
+ "version": "11.0.0",
4
4
  "private": false,
5
5
  "description": "Shared Effect library for Silk Suite conventions",
6
6
  "homepage": "https://github.com/savvy-web/systems/tree/main/packages/silk-effects",
@@ -37,23 +37,23 @@
37
37
  "@changesets/get-release-plan": "^5.0.2",
38
38
  "@changesets/pre": "^3.0.0",
39
39
  "@changesets/read": "^1.0.1",
40
- "@effected/github-references": "^0.11.0",
41
- "@effected/glob": "^0.15.0",
42
- "@effected/jsonc": "^0.20.1",
43
- "@effected/markdown": "^0.23.0",
44
- "@effected/package-json": "^0.26.1",
45
- "@effected/toml": "^0.16.0",
46
- "@effected/walker": "^0.21.0",
47
- "@effected/yaml": "^0.25.1",
40
+ "@effected/github-references": "^0.13.0",
41
+ "@effected/glob": "^0.17.0",
42
+ "@effected/jsonc": "^0.22.0",
43
+ "@effected/markdown": "^0.25.0",
44
+ "@effected/package-json": "^0.28.0",
45
+ "@effected/toml": "^0.18.0",
46
+ "@effected/walker": "^0.24.0",
47
+ "@effected/yaml": "^0.27.0",
48
48
  "@manypkg/get-packages": "^3.1.0",
49
- "@savvy-web/silk-core": "^0.5.2",
49
+ "@savvy-web/silk-core": "^0.6.0",
50
50
  "shell-quote": "^1.12.0"
51
51
  },
52
52
  "peerDependencies": {
53
- "@effected/commands": "^0.17.0",
54
- "@effected/git": "^0.26.0",
55
- "@effected/templates": "^0.14.0",
56
- "@effected/workspaces": "^0.39.0",
57
- "effect": "^4.0.0"
53
+ "@effected/commands": "^0.19.0",
54
+ "@effected/git": "^0.29.0",
55
+ "@effected/templates": "^0.16.0",
56
+ "@effected/workspaces": "^0.41.0",
57
+ "effect": "~4.1.1"
58
58
  }
59
59
  }
package/repos/index.js CHANGED
@@ -5,8 +5,8 @@ import { DriftKind, RepoDrift, ReposDriftReport } from "./schemas/drift.js";
5
5
  import { RepoEntry, RepoName, RepoNote, RepoOrientation, ReposManifestFile } from "./schemas/manifest.js";
6
6
  import { RepoStatusEntry, ReposAddResult, ReposDeregisterResult, ReposNoteResult, ReposPinResult, ReposRemoveResult, ReposRenameResult, ReposRestoreResult, ReposStatusReport, ReposSyncReport } from "./schemas/reports.js";
7
7
  import { ReposConfigStore } from "./services/config-store.js";
8
- import { ReposLockdown, resolveModuleDir } from "./services/lockdown.js";
9
8
  import { ReposDrift, submoduleNameFromKey } from "./services/drift.js";
9
+ import { ReposLockdown, resolveModuleDir } from "./services/lockdown.js";
10
10
  import { ReposManager, STALE_LOCK_MAX_AGE_MS, repoSlug } from "./services/manager.js";
11
11
 
12
12
  // src/repos/index.ts
@@ -1,6 +1,7 @@
1
1
  import { REPOS_DIR } from "../constants.js";
2
2
  import { ReposLockdownError } from "../errors.js";
3
- import { Context, Effect, Exit, FileSystem, Layer, Option, Path } from "effect";
3
+ import { Context, Effect, Exit, FileSystem, Layer, Option, Path, Result } from "effect";
4
+ import { GitFile } from "@effected/git";
4
5
 
5
6
  // src/repos/services/lockdown.ts
6
7
  const FILE_LOCKED_BASE_MODE = 292;
@@ -47,9 +48,9 @@ const resolveModuleDir = (fs, path, root, name) => Effect.gen(function* () {
47
48
  if (info.value.type === "Directory") return dotGit;
48
49
  const content = yield* fs.readFileString(dotGit).pipe(Effect.option);
49
50
  if (Option.isNone(content)) return fallback;
50
- const match = /^gitdir:\s*(.+)$/m.exec(content.value);
51
- if (!match?.[1]) return fallback;
52
- const pointer = match[1].trim();
51
+ const gitFile = GitFile.parseResult(content.value);
52
+ if (Result.isFailure(gitFile)) return fallback;
53
+ const pointer = gitFile.success.gitdir;
53
54
  const resolved = path.isAbsolute(pointer) ? pointer : path.resolve(path.dirname(dotGit), pointer);
54
55
  const relative = path.relative(root, resolved);
55
56
  if (relative.startsWith("..") || path.isAbsolute(relative)) return fallback;
@@ -2,11 +2,11 @@ import { MANIFEST_PATH, REPOS_DIR } from "../constants.js";
2
2
  import { GitSubmoduleError, NoteNotFoundError, RepoNotFoundError, ReposConfigError } from "../errors.js";
3
3
  import { RepoName } from "../schemas/manifest.js";
4
4
  import { ReposConfigStore } from "./config-store.js";
5
- import { ReposLockdown, resolveModuleDir } from "./lockdown.js";
6
5
  import { submoduleNameFromKey } from "./drift.js";
6
+ import { ReposLockdown, resolveModuleDir } from "./lockdown.js";
7
7
  import { Clock, Context, Effect, Exit, FileSystem, Layer, Option, Path, Result, Schema } from "effect";
8
- import { Git, GitConfig, GitRemote, Gitmodules, LsRemoteEntry } from "@effected/git";
9
- import { createHash } from "node:crypto";
8
+ import { Git, GitConfig, GitFile, GitRemote, Gitmodules, LsRemoteEntry } from "@effected/git";
9
+ import { Digest } from "effect/crypto";
10
10
 
11
11
  // src/repos/services/manager.ts
12
12
  /**
@@ -72,6 +72,7 @@ var ReposManager = class extends Context.Service()("@savvy-web/silk-effects/Repo
72
72
  const path = yield* Path.Path;
73
73
  const git = yield* Git;
74
74
  const lockdown = yield* ReposLockdown;
75
+ const digest = yield* Digest.Digest;
75
76
  /** Map any typed `@effected/git` failure onto this module's `GitSubmoduleError`. */
76
77
  const asSubmoduleError = (command, cwd) => (error) => new GitSubmoduleError({
77
78
  command,
@@ -388,7 +389,7 @@ var ReposManager = class extends Context.Service()("@savvy-web/silk-effects/Repo
388
389
  kind: "invalid"
389
390
  }));
390
391
  const existingIds = new Set(notes.map((existing) => existing.id));
391
- const hash = createHash("sha256").update(op.note).digest("hex");
392
+ const hash = yield* digest.digestHex(Digest.sha256, new TextEncoder().encode(op.note));
392
393
  let id;
393
394
  for (let len = 4; len <= hash.length; len += 4) {
394
395
  const candidate = `n-${hash.slice(0, len)}`;
@@ -678,9 +679,9 @@ var ReposManager = class extends Context.Service()("@savvy-web/silk-effects/Repo
678
679
  if (Option.isNone(info) || info.value.type === "Directory") return fallback;
679
680
  const content = yield* fs.readFileString(dotGit).pipe(Effect.option);
680
681
  if (Option.isNone(content)) return fallback;
681
- const match = /^gitdir:\s*(.+)$/m.exec(content.value);
682
- if (!match?.[1]) return fallback;
683
- const pointer = match[1].trim();
682
+ const gitFile = GitFile.parseResult(content.value);
683
+ if (Result.isFailure(gitFile)) return fallback;
684
+ const pointer = gitFile.success.gitdir;
684
685
  const gitdir = path.isAbsolute(pointer) ? pointer : path.resolve(root, pointer);
685
686
  const commondir = yield* fs.readFileString(path.join(gitdir, "commondir")).pipe(Effect.option);
686
687
  if (Option.isSome(commondir)) {
@@ -736,7 +737,7 @@ var ReposManager = class extends Context.Service()("@savvy-web/silk-effects/Repo
736
737
  restore,
737
738
  deregister
738
739
  };
739
- }));
740
+ })).pipe(Layer.provide(Digest.layerWebCrypto));
740
741
  };
741
742
 
742
743
  export { ReposManager, STALE_LOCK_MAX_AGE_MS, repoSlug };
@@ -1,5 +1,5 @@
1
- import { ChangesetConfigReader } from "./ChangesetConfigReader.js";
2
1
  import { ChangesetConfig } from "./ChangesetConfig.js";
2
+ import { ChangesetConfigReader } from "./ChangesetConfigReader.js";
3
3
  import { SilkPublishability, readTargetsBinding } from "./SilkPublishability.js";
4
4
  import { AnalyzedWorkspace, WorkspaceAnalysis, WorkspaceAnalysisError } from "@savvy-web/silk-core";
5
5
  import { Context, Effect, FileSystem, Layer, Option } from "effect";
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.59.4"
8
+ "packageVersion": "7.60.1"
9
9
  }
10
10
  ]
11
11
  }