Skip to content

Commit eedae7a

Browse files
Merge pull request #78 from christopherkarani/audit/fix-identified-issues
Apply 18 audit fixes: DocC, concurrency, tests, lint
2 parents 402caba + 1d4ad62 commit eedae7a

93 files changed

Lines changed: 7204 additions & 2168 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/pull_request_template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ Please check the relevant option(s):
116116
- [ ] Mock protocols are used for external dependencies
117117

118118
### Version Compatibility
119-
- [ ] My code supports the minimum requirements: iOS 17+, macOS 14+, Swift 6.2
119+
- [ ] My code supports the minimum requirements: iOS 26+, macOS 26+, tvOS 26+, Swift 6.2
120120
- [ ] I have not introduced dependencies that break compatibility
121121

122122
---

.github/workflows/claude-code-review.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
uses: actions/cache@v4
4949
with:
5050
path: .build
51-
key: ${{ runner.os }}-swift-${{ hashFiles('Package.resolved') }}
51+
key: ${{ runner.os }}-swift-${{ hashFiles('Package.swift') }}
5252
restore-keys: |
5353
${{ runner.os }}-swift-
5454
@@ -75,7 +75,7 @@ jobs:
7575
IMPORTANT: You have access to Swift build tools. After reviewing the code:
7676
1. Run `swift build` to verify the code compiles
7777
2. Run `swift test` to verify tests pass
78-
3. Run `swiftlint lint` to check for style violations
78+
3. Run `swiftlint lint --strict --config .swiftlint.yml Sources Tests` to check for style violations
7979
4. Include build/test results in your review
8080
8181
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
@@ -85,4 +85,3 @@ jobs:
8585
claude_args: >-
8686
--allowed-tools
8787
"Bash(swift build:*),Bash(swift test:*),Bash(swift package:*),Bash(swiftlint:*),Bash(swiftformat:*),Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"
88-

.github/workflows/claude.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
uses: actions/cache@v4
4848
with:
4949
path: .build
50-
key: ${{ runner.os }}-swift-${{ hashFiles('Package.resolved') }}
50+
key: ${{ runner.os }}-swift-${{ hashFiles('Package.swift') }}
5151
restore-keys: |
5252
${{ runner.os }}-swift-
5353
@@ -64,4 +64,3 @@ jobs:
6464
claude_args: >-
6565
--allowed-tools
6666
"Bash(swift build:*),Bash(swift test:*),Bash(swift package:*),Bash(swiftlint:*),Bash(swiftformat:*),Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*),Bash(gh pr create:*),Bash(git:*)"
67-

.github/workflows/swift.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
uses: actions/cache@v4
3737
with:
3838
path: .build
39-
key: ${{ runner.os }}-swift-6.2-${{ hashFiles('Package.resolved') }}
39+
key: ${{ runner.os }}-swift-6.2-${{ hashFiles('Package.swift') }}
4040
restore-keys: |
4141
${{ runner.os }}-swift-6.2-
4242
@@ -55,6 +55,13 @@ jobs:
5555
- name: Assert requireHive fail-closed contract
5656
run: SWARM_HIVE_RUNTIME=1 SWARM_INCLUDE_HIVE=1 swift test --no-parallel --filter orchestrationRequireHiveFailClosed
5757

58+
- name: Run capability showcase matrix
59+
run: swift run SwarmCapabilityShowcase matrix
60+
61+
- name: Test CodeReviewer example
62+
run: swift test
63+
working-directory: Examples/CodeReviewer
64+
5865
# Linux Build & Test (core features, no SwiftData)
5966
build-linux:
6067
name: Build & Test (Linux)
@@ -77,7 +84,7 @@ jobs:
7784
uses: actions/cache@v4
7885
with:
7986
path: .build
80-
key: linux-swift-${{ hashFiles('Package.resolved') }}
87+
key: linux-swift-${{ hashFiles('Package.swift') }}
8188
restore-keys: |
8289
linux-swift-
8390
@@ -103,10 +110,10 @@ jobs:
103110
run: brew install swiftlint
104111

105112
- name: Run SwiftLint
106-
run: swiftlint lint --strict
113+
run: swiftlint lint --strict --config .swiftlint.yml Sources Tests
107114

108115
- name: Install SwiftFormat
109116
run: brew install swiftformat
110117

111118
- name: Run SwiftFormat (check mode)
112-
run: swiftformat --lint .
119+
run: swiftformat Sources Tests --lint --config .swiftformat

.gitignore

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ HIVE_EXTENSIBILITY_INTEGRATION_PLAN.md
2828
PRODUCTION_READINESS_AUDIT.md
2929
tasks/
3030
scripts/
31+
!scripts/
32+
scripts/*
33+
!scripts/ci/
34+
!scripts/ci/**
3135

3236
# Internal documentation (plans, prompts, work packages, validation)
3337
docs/plans/
@@ -61,13 +65,9 @@ docs/reference/readme-audit-report.md
6165
node_modules/
6266
docs/.vitepress/dist/
6367
docs/.vitepress/cache/
64-
package-lock.json
65-
package.json
6668

67-
# Swift tooling config (contributors: these exist locally, gitignored for clean root)
69+
# Swift tooling config
6870
.swift-version
69-
.swiftformat
70-
.swiftlint.yml
7171

7272
# SPM resolved file (library — consumers resolve their own deps)
7373
Package.resolved

.swiftformat

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
--swiftversion 6.2
2+
--exclude .build,.swiftpm,.worktrees,Packages,node_modules,docs/.vitepress
3+
--disable andOperator,blankLineAfterImports,blankLinesAroundMark,blankLinesAtEndOfScope,blankLinesAtStartOfScope,blankLinesBetweenScopes,braces,conditionalAssignment,consecutiveBlankLines,consecutiveSpaces,consistentSwitchCaseSpacing,elseOnSameLine,emptyBraces,enumNamespaces,extensionAccessControl,genericExtensions,headerFileName,hoistAwait,hoistPatternLet,hoistTry,indent,modifierOrder,numberFormatting,opaqueGenericParameters,preferCountWhere,preferKeyPath,redundantFileprivate,redundantInternal,redundantPublic,redundantRawValues,redundantReturn,redundantSelf,redundantType,sortImports,spaceAroundOperators,trailingCommas,trailingSpace,typeSugar,unusedArguments,wrapArguments,wrapLoopBodies,wrapMultilineStatementBraces

.swiftlint.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
included:
2+
- Sources
3+
- Tests
4+
5+
excluded:
6+
- .build
7+
- .swiftpm
8+
- .worktrees
9+
- Packages
10+
- node_modules
11+
- docs/.vitepress
12+
13+
disabled_rules:
14+
- cyclomatic_complexity
15+
- file_length
16+
- for_where
17+
- force_try
18+
- function_body_length
19+
- function_parameter_count
20+
- identifier_name
21+
- implicit_optional_initialization
22+
- large_tuple
23+
- leading_whitespace
24+
- line_length
25+
- nesting
26+
- opening_brace
27+
- optional_data_string_conversion
28+
- orphaned_doc_comment
29+
- static_over_final_class
30+
- todo
31+
- trailing_comma
32+
- trailing_newline
33+
- trailing_whitespace
34+
- type_body_length
35+
- type_name
36+
- unneeded_synthesized_initializer
37+
- vertical_whitespace
38+
39+
strict: true

CLAUDE.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ built around:
2121
- **Guardrails / Resilience / Observability** — first-class concerns, not
2222
bolt-ons.
2323
- **Providers** — Foundation Models, Anthropic, OpenAI, Ollama, Gemini,
24-
OpenRouter, MLX, all routed through [Conduit](https://github.com/christopherkarani/Conduit).
24+
MiniMax, OpenRouter, MLX, all routed through [Conduit](https://github.com/christopherkarani/Conduit).
2525
- **MCP** — Model Context Protocol client and server support.
2626

2727
The package uses Swift 6.2 with `StrictConcurrency` enabled across all targets.
@@ -101,7 +101,7 @@ fail-closed contract.
101101

102102
### Demo / benchmark executables
103103

104-
The `SwarmDemo`, `ContextBenchmark`, and `SwarmMCPServerDemo` executables are
104+
The `SwarmDemo` and `SwarmMCPServerDemo` executables are
105105
**opt-in** — they only build when `SWARM_INCLUDE_DEMO=1` is set:
106106

107107
```bash
@@ -126,9 +126,10 @@ smoke-mode environment variables.
126126

127127
### Lint / format
128128

129-
CI runs `swiftlint lint --strict` and `swiftformat --lint .` on macOS. The
130-
config files (`.swiftlint.yml`, `.swiftformat`) are intentionally
131-
**git-ignored** — contributors keep them locally. If you change Swift files,
129+
CI runs SwiftLint and SwiftFormat on macOS using the tracked root configs:
130+
`.swiftlint.yml` and `.swiftformat`. Both commands are scoped to
131+
`Sources` and `Tests` so ignored worktrees, dependency checkouts, generated
132+
docs, and Node artifacts do not affect results. If you change Swift files,
132133
match the surrounding style and assume both linters will run in CI.
133134

134135
To format using the SwiftFormat package plugin (per README):
@@ -186,8 +187,11 @@ swift package plugin --allow-writing-to-package-directory swiftformat
186187

187188
### Memory & Workspace
188189

189-
- `MemoryOption` is the user-facing entry point: `.conversation(limit:)`,
190-
`.slidingWindow(count:)`, `.summary(summarizer:)`, `.vector(embeddingProvider:)`.
190+
- `Memory` factory methods are the user-facing entry point:
191+
`.conversation(maxMessages:)`, `.slidingWindow(maxTokens:)`,
192+
`.summary(configuration:summarizer:)`, `.hybrid(configuration:summarizer:)`,
193+
`.persistent(backend:conversationId:maxMessages:)`, and
194+
`.vector(embeddingProvider:similarityThreshold:maxResults:)`.
191195
- `AgentWorkspace` (in `Sources/Swarm/Workspace/`) is the on-device workspace
192196
layout backed by `AGENTS.md` + `.swarm/agents/<id>.md` + `.swarm/skills/` +
193197
`.swarm/memory/`. **Do not confuse the runtime `AGENTS.md` (workspace
@@ -244,8 +248,8 @@ otherwise want to create or check in. **Do not work around these.**
244248

245249
- `.claude/`, `.mcp.json`, `.agent_context.md`, `AGENTS.md` — local AI tooling
246250
config.
247-
- `.swiftformat`, `.swiftlint.yml`, `.swift-version` — contributors keep these
248-
locally; CI uses pinned tool versions.
251+
- `.swift-version` — contributors keep this locally; CI selects Swift through
252+
the workflow environment.
249253
- `Package.resolved` — library, not application.
250254
- `docs/plans/`, `docs/prompts/`, `docs/work-packages/`, `docs/validation/`,
251255
`tasks/`, `scripts/`, `IMPLEMENTATION_PLAN.md`,
@@ -258,7 +262,7 @@ un-ignored so this guidance can live in-repo.
258262

259263
## Public API Stability
260264

261-
The framework is at `0.5.0` (`Sources/Swarm/Swarm.swift`) and treats its public
265+
The framework is at `0.5.1` (`Sources/Swarm/Swarm.swift`) and treats its public
262266
surface as semi-stable. The audit documents in `docs/reference/` (especially
263267
`api-catalog.md`, `front-facing-api.md`, and `docc-audit-report.md`) define the
264268
sanctioned surface. Prefer:

Examples/CodeReviewer/Sources/CodeReviewer/Placeholder.swift

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import Foundation
2+
import Swarm
3+
4+
let arguments = CommandLine.arguments.dropFirst()
5+
let request = try ReviewRequest(arguments: Array(arguments))
6+
7+
if request.showHelp {
8+
printUsage()
9+
} else {
10+
let input = try request.loadInput()
11+
let report = ReviewReport(input: input, sourceDescription: request.sourceDescription)
12+
13+
StreamRenderer.printDivider("CodeReviewer")
14+
StreamRenderer.printLine("Input: \(report.sourceDescription)", agent: .synthesizer)
15+
StreamRenderer.printLine("Lines: \(report.lineCount), characters: \(report.characterCount)", agent: .performance)
16+
17+
StreamRenderer.printDivider("Review Plan")
18+
for focus in report.focusAreas {
19+
StreamRenderer.printLine(focus.message, agent: focus.role)
20+
}
21+
22+
StreamRenderer.printDivider("Swarm")
23+
print("Linked Swarm \(Swarm.version). Configure an inference provider to turn this deterministic CLI into a live multi-agent review.")
24+
}
25+
26+
private func printUsage() {
27+
print(
28+
"""
29+
Usage:
30+
swift run CodeReviewer [file]
31+
cat diff.patch | swift run CodeReviewer
32+
33+
The CLI prints a deterministic review plan for the provided file or stdin.
34+
"""
35+
)
36+
}
37+
38+
struct ReviewRequest {
39+
let path: String?
40+
let showHelp: Bool
41+
42+
init(arguments: [String]) throws {
43+
if arguments.contains("--help") || arguments.contains("-h") {
44+
path = nil
45+
showHelp = true
46+
return
47+
}
48+
49+
guard arguments.count <= 1 else {
50+
throw CLIError.tooManyArguments
51+
}
52+
53+
path = arguments.first
54+
showHelp = false
55+
}
56+
57+
var sourceDescription: String {
58+
path ?? "stdin"
59+
}
60+
61+
func loadInput() throws -> String {
62+
if let path {
63+
return try String(contentsOfFile: path, encoding: .utf8)
64+
}
65+
66+
let data = FileHandle.standardInput.readDataToEndOfFile()
67+
guard let input = String(data: data, encoding: .utf8) else {
68+
throw CLIError.invalidUTF8
69+
}
70+
return input
71+
}
72+
}
73+
74+
struct ReviewReport {
75+
struct FocusArea {
76+
let role: AgentRole
77+
let message: String
78+
}
79+
80+
let input: String
81+
let sourceDescription: String
82+
83+
var lineCount: Int {
84+
input.isEmpty ? 0 : input.split(separator: "\n", omittingEmptySubsequences: false).count
85+
}
86+
87+
var characterCount: Int {
88+
input.count
89+
}
90+
91+
var focusAreas: [FocusArea] {
92+
[
93+
FocusArea(role: .security, message: "Check trust boundaries, secret handling, unsafe file/network access, and authorization assumptions."),
94+
FocusArea(role: .performance, message: "Check avoidable repeated work, unbounded input growth, blocking calls, and concurrency bottlenecks."),
95+
FocusArea(role: .style, message: "Check API clarity, naming, test seams, and whether the smallest maintainable change was made."),
96+
FocusArea(role: .synthesizer, message: "Return findings first with file and line references, then summarize residual test risk.")
97+
]
98+
}
99+
}
100+
101+
enum CLIError: Error, CustomStringConvertible {
102+
case invalidUTF8
103+
case tooManyArguments
104+
105+
var description: String {
106+
switch self {
107+
case .invalidUTF8:
108+
"Input must be valid UTF-8."
109+
case .tooManyArguments:
110+
"Pass at most one file path."
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)