Skip to content

Commit e7b6ad8

Browse files
Merge pull request #88 from Corvidae-Coding-Projects/develop
release: promote develop to main
2 parents 26ee188 + 98085fe commit e7b6ad8

623 files changed

Lines changed: 27568 additions & 39738 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.

.claude/hooks/work-check.py

Lines changed: 95 additions & 95 deletions
Large diffs are not rendered by default.

.claude/mcp/agent-prompt-server.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
11
#!/usr/bin/env python3
2-
# /// script
3-
# requires-python = ">=3.10"
4-
# dependencies = []
5-
# ///
6-
"""
7-
Crosslink Agent Prompt MCP Server
82

9-
An MCP server that provides reliable prompt delivery to tmux-based agent sessions.
10-
Wraps `crosslink agent prompt` to avoid the pitfalls of raw `tmux send-keys`.
113

12-
Usage:
13-
Registered in .claude/settings.json as an MCP server.
14-
Claude calls mcp__crosslink-agent-prompt__agent_prompt(session, prompt) to send prompts.
15-
"""
4+
5+
6+
7+
8+
9+
10+
11+
12+
13+
14+
15+
1616

1717
import json
1818
import sys
1919
import io
2020
import subprocess
2121
from typing import Any
2222

23-
# Fix Windows encoding issues
23+
2424
sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8')
2525
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', line_buffering=True)
2626
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
2727

2828

2929
def log(message: str) -> None:
30-
"""Log to stderr (visible in MCP server logs)."""
30+
3131
print(f"[agent-prompt] {message}", file=sys.stderr)
3232

3333

@@ -62,7 +62,7 @@ def log(message: str) -> None:
6262

6363

6464
def handle_agent_prompt(arguments: dict[str, Any]) -> dict[str, Any]:
65-
"""Handle the agent_prompt tool call by delegating to crosslink CLI."""
65+
6666
session = arguments.get('session', '').strip()
6767
prompt = arguments.get('prompt', '')
6868
submit = arguments.get('submit', True)
@@ -116,7 +116,7 @@ def handle_agent_prompt(arguments: dict[str, Any]) -> dict[str, Any]:
116116

117117

118118
def handle_request(request: dict[str, Any]) -> dict[str, Any] | None:
119-
"""Handle an MCP JSON-RPC request."""
119+
120120
method = request.get('method', '')
121121
request_id = request.get('id')
122122
params = request.get('params', {})
@@ -182,7 +182,7 @@ def handle_request(request: dict[str, Any]) -> dict[str, Any] | None:
182182

183183

184184
def main():
185-
"""Main MCP server loop - reads JSON-RPC from stdin, writes to stdout."""
185+
186186
log("Starting agent-prompt MCP server")
187187

188188
while True:

.crosslink/.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
# Multi-agent collaboration (machine-local)
21
agent.json
32
.hub-cache/
43
.knowledge-cache/
54
keys/
65
integrations/
76

8-
# Machine-local overrides
97
hook-config.local.json
108
rules.local/
119

12-
# Machine-local runtime state (never commit — regenerated per machine)
1310
.active-issue
1411
.last-hydrated-ref
1512
.promoted-uuids

.crosslink/knowledge/forecast-visual-design-system.md renamed to .crosslink/knowledge/crosslink-visual-design-system.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Forecast Visual Design System
1+
# Crosslink Visual Design System
22

3-
Reference for the Forecast brand visual language as implemented in crosslink docs and reusable across projects.
3+
Reference for the Crosslink brand visual language as implemented in crosslink docs and reusable across projects.
44

55
## Brand Palette (from `_brand.yml`)
66

@@ -25,13 +25,13 @@ Reference for the Forecast brand visual language as implemented in crosslink doc
2525

2626
Shapes use only: ellipses, circles, rounded rectangles. No triangles or crescents.
2727

28-
All shapes use `mix-blend-mode: multiply` — no alpha transparency on shapes. This creates the layered, overlapping Forecast look where colors interact.
28+
All shapes use `mix-blend-mode: multiply` — no alpha transparency on shapes. This creates the layered, overlapping Crosslink look where colors interact.
2929

3030
## Confetti Dots
3131

3232
Small colored circles scattered as decorative accents, always with `mix-blend-mode: multiply`.
3333

34-
### Color distribution (from forecast.bio homepage)
34+
### Color distribution (from Crosslink visual palette)
3535

3636
Weighted random sampling matching the original site's `kConfetti` array:
3737

@@ -54,7 +54,7 @@ Grey-dominant with colored accents. This keeps confetti subtle while the colored
5454
### Animated confetti (footer JS)
5555

5656
- 14 dots, 11px diameter
57-
- Positioned in a **cone shape** emanating up-right from the Forecast wordmark
57+
- Positioned in a **cone shape** emanating up-right from the Crosslink wordmark
5858
- Cone origin at logo baseline, slope drifts upward (-0.28 rise per px)
5959
- Spread grows with distance (cone half-angle 0.22)
6060
- Extra noise (±10px) on both axes for fuzzy edges
@@ -98,10 +98,10 @@ Small 2-4 shape compositions for feature cards, each evocative of the feature:
9898

9999
## Footer
100100

101-
Matches forecast.bio card pages:
101+
Matches Crosslink documentation pages:
102102
1. Thin rule (`#ede3e3`, 220px)
103103
2. Wordmark + animated confetti cone (same row, flex, aligned to baseline)
104-
3. Copyright notice (`© 2026 Forecast Bio, Inc. · Built with Quarto`)
104+
3. Copyright notice (`© 2026 Crosslink contributors · Built with Quarto`)
105105

106106
Footer is injected via `include-after-body` and JS-relocated into Quarto's `<main class="content">` for proper content-column alignment.
107107

.crosslink/rules/c.md

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +0,0 @@
1-
### C Best Practices
2-
3-
#### Memory Safety
4-
- Always check return values of malloc/calloc
5-
- Free all allocated memory (use tools like valgrind)
6-
- Initialize all variables before use
7-
- Use sizeof() with the variable, not the type
8-
9-
```c
10-
// GOOD: Safe memory allocation
11-
int *arr = malloc(n * sizeof(*arr));
12-
if (arr == NULL) {
13-
return -1; // Handle allocation failure
14-
}
15-
// ... use arr ...
16-
free(arr);
17-
18-
// BAD: Unchecked allocation
19-
int *arr = malloc(n * sizeof(int));
20-
arr[0] = 1; // Crash if malloc failed
21-
```
22-
23-
#### Buffer Safety
24-
- Always bounds-check array access
25-
- Use `strncpy`/`snprintf` instead of `strcpy`/`sprintf`
26-
- Validate string lengths before copying
27-
28-
```c
29-
// GOOD: Safe string copy
30-
char dest[64];
31-
strncpy(dest, src, sizeof(dest) - 1);
32-
dest[sizeof(dest) - 1] = '\0';
33-
34-
// BAD: Buffer overflow risk
35-
char dest[64];
36-
strcpy(dest, src); // No bounds check
37-
```
38-
39-
#### Security
40-
- Never use `gets()` (use `fgets()`)
41-
- Validate all external input
42-
- Use constant-time comparison for secrets
43-
- Avoid integer overflow in size calculations

.crosslink/rules/cpp.md

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +0,0 @@
1-
### C++ Best Practices
2-
3-
#### Modern C++ (C++17+)
4-
- Use smart pointers (`unique_ptr`, `shared_ptr`) over raw pointers
5-
- Use RAII for resource management
6-
- Prefer `std::string` and `std::vector` over C arrays
7-
- Use `auto` for complex types, explicit types for clarity
8-
9-
```cpp
10-
// GOOD: Modern C++ with smart pointers
11-
auto config = std::make_unique<Config>();
12-
auto users = std::vector<User>{};
13-
14-
// BAD: Manual memory management
15-
Config* config = new Config();
16-
// ... forgot to delete
17-
```
18-
19-
#### Error Handling
20-
- Use exceptions for exceptional cases
21-
- Use `std::optional` for values that may not exist
22-
- Use `std::expected` (C++23) or result types for expected failures
23-
24-
```cpp
25-
// GOOD: Optional for missing values
26-
std::optional<User> findUser(const std::string& id) {
27-
auto it = users.find(id);
28-
if (it == users.end()) {
29-
return std::nullopt;
30-
}
31-
return it->second;
32-
}
33-
```
34-
35-
#### Security
36-
- Validate all input boundaries
37-
- Use `std::string_view` for non-owning string references
38-
- Avoid C-style casts; use `static_cast`, `dynamic_cast`
39-
- Never use `sprintf`; use `std::format` or streams

.crosslink/rules/csharp.md

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +0,0 @@
1-
### C# Best Practices
2-
3-
#### Code Style
4-
- Follow .NET naming conventions (PascalCase for public, camelCase for private)
5-
- Use `var` when type is obvious from right side
6-
- Use expression-bodied members for simple methods
7-
- Enable nullable reference types
8-
9-
```csharp
10-
// GOOD: Modern C# style
11-
public class UserService
12-
{
13-
private readonly IUserRepository _repository;
14-
15-
public UserService(IUserRepository repository)
16-
=> _repository = repository;
17-
18-
public async Task<User?> GetUserAsync(string id)
19-
=> await _repository.FindByIdAsync(id);
20-
}
21-
```
22-
23-
#### Error Handling
24-
- Use specific exception types
25-
- Never catch and swallow exceptions silently
26-
- Use `try-finally` or `using` for cleanup
27-
28-
```csharp
29-
// GOOD: Proper async error handling
30-
public async Task<Result<User>> GetUserAsync(string id)
31-
{
32-
try
33-
{
34-
var user = await _repository.FindByIdAsync(id);
35-
return user is null
36-
? Result<User>.NotFound()
37-
: Result<User>.Ok(user);
38-
}
39-
catch (DbException ex)
40-
{
41-
_logger.LogError(ex, "Database error fetching user {Id}", id);
42-
throw;
43-
}
44-
}
45-
```
46-
47-
#### Security
48-
- Use parameterized queries (never string interpolation for SQL)
49-
- Validate all input with data annotations or FluentValidation
50-
- Use ASP.NET's built-in anti-forgery tokens
51-
- Store secrets in Azure Key Vault or similar

.crosslink/rules/elixir-phoenix.md

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +0,0 @@
1-
# Phoenix & LiveView Rules
2-
3-
## HEEx Template Syntax (Critical)
4-
- **Attributes use `{}`**: `<div id={@id}>` — never `<%= %>` in attributes
5-
- **Body values use `{}`**: `{@value}` — use `<%= %>` only for blocks (if/for/cond)
6-
- **Class lists require `[]`**: `class={["base", @flag && "active"]}` — bare `{}` is invalid
7-
- **No `else if`**: Use `cond` for multiple conditions
8-
- **Comments**: `<%!-- comment --%>`
9-
- **Literal curlies**: Use `phx-no-curly-interpolation` on parent tag
10-
11-
## Phoenix v1.8
12-
- Wrap templates with `<Layouts.app flash={@flash}>` (already aliased)
13-
- `current_scope` errors → move routes to proper `live_session`, pass to Layouts.app
14-
- `<.flash_group>` only in layouts.ex
15-
- Use `<.icon name="hero-x-mark">` for icons, `<.input>` for form fields
16-
17-
## LiveView
18-
- Use `<.link navigate={}>` / `push_navigate`, not deprecated `live_redirect`
19-
- Hooks with own DOM need `phx-update="ignore"`
20-
- Avoid LiveComponents unless necessary
21-
- No inline `<script>` tags — use assets/js/app.js
22-
23-
## Streams (Always use for collections)
24-
```elixir
25-
stream(socket, :items, items) # append
26-
stream(socket, :items, items, at: -1) # prepend
27-
stream(socket, :items, items, reset: true) # filter/refresh
28-
```
29-
Template: `<div id="items" phx-update="stream">` with `:for={{id, item} <- @streams.items}`
30-
- Streams aren't enumerable — refetch + reset to filter
31-
- Empty states: `<div class="hidden only:block">Empty</div>` as sibling
32-
33-
## Forms
34-
```elixir
35-
# LiveView: always use to_form
36-
assign(socket, form: to_form(changeset))
37-
```
38-
```heex
39-
<%!-- Template: always @form, never @changeset --%>
40-
<.form for={@form} id="my-form" phx-submit="save">
41-
<.input field={@form[:name]} type="text" />
42-
</.form>
43-
```
44-
- Never `<.form let={f}>` or `<.form for={@changeset}>`
45-
46-
## Router
47-
- Scope alias is auto-prefixed: `scope "/", AppWeb do``live "/users", UserLive` = `AppWeb.UserLive`
48-
49-
## Ecto
50-
- Preload associations accessed in templates
51-
- Use `Ecto.Changeset.get_field/2` to read changeset fields
52-
- Don't cast programmatic fields (user_id) — set explicitly
53-
54-
## Testing
55-
- Use `has_element?(view, "#my-id")`, not raw HTML matching
56-
- Debug selectors: `LazyHTML.filter(LazyHTML.from_fragment(render(view)), "selector")`
57-

.crosslink/rules/elixir.md

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +0,0 @@
1-
# Elixir Core Rules
2-
3-
## Critical Mistakes to Avoid
4-
- **No early returns**: Last expression in a block is always returned
5-
- **No list indexing with brackets**: Use `Enum.at(list, i)`, not `list[i]`
6-
- **No struct access syntax**: Use `struct.field`, not `struct[:field]` (structs don't implement Access)
7-
- **Rebinding in blocks doesn't work**: `socket = if cond, do: assign(socket, :k, v)` - bind the result, not inside
8-
- **`%{}` matches ANY map**: Use `map_size(map) == 0` guard for empty maps
9-
- **No `String.to_atom/1` on user input**: Memory leak risk
10-
- **No nested modules in same file**: Causes cyclic dependencies
11-
12-
## Pattern Matching & Functions
13-
- Match on function heads over `if`/`case` in bodies
14-
- Use guards: `when is_binary(name) and byte_size(name) > 0`
15-
- Use `with` for chaining `{:ok, _}` / `{:error, _}` operations
16-
- Predicates end with `?` (not `is_`): `valid?/1` not `is_valid/1`
17-
- Reserve `is_thing` names for guard macros
18-
19-
## Data Structures
20-
- Prepend to lists: `[new | list]` not `list ++ [new]`
21-
- Structs for known shapes, maps for dynamic data, keyword lists for options
22-
- Use `Enum` over recursion; use `Stream` for large collections
23-
24-
## OTP
25-
- `GenServer.call/3` for sync (prefer for back-pressure), `cast/2` for fire-and-forget
26-
- DynamicSupervisor/Registry require names: `{DynamicSupervisor, name: MyApp.MySup}`
27-
- `Task.async_stream(coll, fn, timeout: :infinity)` for concurrent enumeration
28-
29-
## Testing & Debugging
30-
- `mix test path/to/test.exs:123` - run specific test
31-
- `mix test --failed` - rerun failures
32-
- `dbg/1` for debugging output
33-
34-
## Documentation Lookup
35-
```bash
36-
mix usage_rules.docs Enum.zip/1 # Function docs
37-
mix usage_rules.search_docs "query" -p pkg # Search package docs
38-
```
39-

0 commit comments

Comments
 (0)