Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
e867303
#104 wip
bennobuilder May 17, 2026
71e8180
#104 fix typos
bennobuilder May 17, 2026
557eed6
#104 fixed typos
bennobuilder May 17, 2026
3f9f9d4
#104 fix typos
bennobuilder May 17, 2026
c01125a
#104 refactor feature-core to simpler TFeature shape
bennobuilder May 17, 2026
66b3d68
#104 fix typos
bennobuilder May 17, 2026
c14fa86
#104 refine feature-core types
bennobuilder May 18, 2026
d16e739
#104 fix typos
bennobuilder May 18, 2026
31d7c87
#104 migrate feature-state to feature-core
bennobuilder May 18, 2026
ebc8bac
#104 format
bennobuilder May 18, 2026
38a8293
#104 rework feature-state queues
bennobuilder May 18, 2026
d9f560b
#104 add feature overrides
bennobuilder May 18, 2026
074acd0
#104 rework feature-state queues as features
bennobuilder May 18, 2026
84b8a50
#104 fix typo
bennobuilder May 18, 2026
cf3e502
#104 fix typos
bennobuilder May 19, 2026
30cce55
#104 fix typos
bennobuilder May 19, 2026
423ddc4
#104 wip migrate feature-form to feature-core
bennobuilder May 19, 2026
f8636d4
#104 migrate feature-form to Standard Schema
bennobuilder May 19, 2026
aba9191
#104 add basic feature-form tests
bennobuilder May 19, 2026
01bef62
#104 fix typos
bennobuilder May 19, 2026
3d15ba8
#104 fix typo
bennobuilder May 19, 2026
8aaebdd
#104 fix typos
bennobuilder May 19, 2026
6dfd3b9
#104 fix typos
bennobuilder May 19, 2026
3589ef0
#104 fix typos
bennobuilder May 20, 2026
99ef7ac
#104 fix typos
bennobuilder May 20, 2026
b0fcf9c
#104 add basic dirty form feature
bennobuilder May 20, 2026
ed1bb7f
#104 migrate feature-react state features
bennobuilder May 20, 2026
8792443
#104 remove unused hooks
bennobuilder May 20, 2026
2a780bb
#104 fix typos
bennobuilder May 20, 2026
eee3de4
#104 infer form types from fields
bennobuilder May 20, 2026
eeb5bc9
#104 rework feature-form validation DX
bennobuilder May 20, 2026
874b037
#104 wip rework feature-react state hooks
bennobuilder May 20, 2026
b656897
#104 fix typos
bennobuilder May 20, 2026
4c6d887
#104 fix typo
bennobuilder May 21, 2026
d56a37b
#104 rework useFeatureState and useCompute with useSyncExternalStore
bennobuilder May 21, 2026
45ce844
#104 rework useForm and registerFormField
bennobuilder May 21, 2026
6de134e
#104 fix typos
bennobuilder May 21, 2026
9df0848
#104 fix typos
bennobuilder May 21, 2026
8f4485d
#104 rework basic React examples
bennobuilder May 21, 2026
0b6b247
#104 refine react form hooks
bennobuilder May 21, 2026
f92e88d
#104 fix typos
bennobuilder May 21, 2026
91bc858
#104 add isEqualFeature and validation status deduplication
bennobuilder May 21, 2026
dcb68f8
#104 fix typos
bennobuilder May 21, 2026
6282ef0
#104 add computed state
bennobuilder May 21, 2026
58ba9fd
#104 fix typos
bennobuilder May 21, 2026
ac0f184
#104 deprecate eprel-client & split-flap-board
bennobuilder May 21, 2026
0151226
#104 format
bennobuilder May 21, 2026
ac685b1
#104 improve ts docs
bennobuilder May 22, 2026
f5daf5a
#104 fix typos
bennobuilder May 22, 2026
4c885cf
#104 rework feature-logger
bennobuilder May 22, 2026
9e52622
#104 fix typos
bennobuilder May 22, 2026
5b15d5d
#104 format
bennobuilder May 22, 2026
5f06f2c
#104 rework tuple-result
bennobuilder May 22, 2026
46b54fe
#104 update deps
bennobuilder May 22, 2026
7b1c66c
#104 add package keywords
bennobuilder May 22, 2026
6b64858
#104 improve package readme's
bennobuilder May 22, 2026
39ab00f
#104 rework validatenv
bennobuilder May 22, 2026
51492a5
#104 refine tests
bennobuilder May 22, 2026
8a5e767
#104 format
bennobuilder May 22, 2026
8409e12
#104 add createEnv helper
bennobuilder May 23, 2026
08c2783
#104 wip rework feature-fetch headers
bennobuilder May 23, 2026
28d3136
#104 clean package internals
bennobuilder May 23, 2026
18f89b9
#104 rework feature-fetch lib
bennobuilder May 24, 2026
44c713d
#104 rework feature-fetch errors
bennobuilder May 24, 2026
eafd9fe
#104 wip rework create-fetch-client
bennobuilder May 24, 2026
4156eaf
#104 fix typos
bennobuilder May 24, 2026
8cb6d49
#104 fix tsdoc
bennobuilder May 24, 2026
a4fafd3
#104 fix typos
bennobuilder May 24, 2026
fab3451
#104 wip rework fetch api feature
bennobuilder May 24, 2026
8583df4
#104 refine OpenAPI fetch types
bennobuilder May 24, 2026
bbb6521
#104 extend tests
bennobuilder May 24, 2026
a8e4ad4
#104 fix typos
bennobuilder May 25, 2026
716a467
#104 rework cache feature
bennobuilder May 25, 2026
5764cd4
#104 rework delay feature
bennobuilder May 25, 2026
cb60150
#104 rework retry feature
bennobuilder May 25, 2026
2314045
#104 rework graphql feature
bennobuilder May 25, 2026
8a9e0a6
#104 remove old features
bennobuilder May 25, 2026
2015a1e
#104 rework fetch response shape
bennobuilder May 25, 2026
3abcb96
#104 wip update README
bennobuilder May 25, 2026
0b57987
Merge branch '104-rework-feature-fetch' into 104-with-chain-experiment
bennobuilder May 25, 2026
e0405f0
#104 fix typo
bennobuilder May 25, 2026
566ed9b
#104 fix typos
bennobuilder May 25, 2026
10ac24b
#104 update feature-fetch example
bennobuilder May 25, 2026
aa5b6f3
#104 add feature-fetch graphql example to basic
bennobuilder May 25, 2026
bed3bed
#104 polish feature fetch docs
bennobuilder May 25, 2026
92fcd82
#104 refine graphql response API
bennobuilder May 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 2 additions & 4 deletions .agent/rules/comments.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# Comment Rules

Add comments when they make the code easier to understand or maintain. Omit them when the code speaks for itself.
Add comments when they make the code easier to understand or maintain. Omit them when the code speaks for itself. For prose style within comments, see `writing.md`.

## Enforce

- Add regular comments to explain **why**, a constraint, domain behavior, or to orient the reader at the start of a non-obvious block
- Place the comment directly above the code it explains
- Omit the trailing period in a short single-line regular comment
- Use plain punctuation only
- Add doc comments to public and exported functions, methods, and types only when the name and signature alone do not make the behavior or contract clear; describe what it does first, then note constraints, side effects, or non-obvious return or error behavior when needed
- Start doc comments with a single sentence in active voice and end it with a period
- Use `// MARK: -` sparingly as a file-level or large-structure navigation aid, mainly in long files
Expand All @@ -16,7 +15,6 @@ Add comments when they make the code easier to understand or maintain. Omit them

## Avoid

- Do not use em dashes (—) in comments
- Do not restate what the code already says in regular comments
- Do not use comments as a substitute for good naming
- Do not add comments above a block when the intent is already obvious from the code
Expand Down Expand Up @@ -87,7 +85,7 @@ const sortedItems = items.slice().sort(compareItems);

```ts
/** Returns whether the user is authenticated. */
export function isAuthenticated(): boolean
export function isAuthenticated(): boolean;
```

```ts
Expand Down
8 changes: 3 additions & 5 deletions .agent/rules/feature-fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Use `feature-fetch` as the typed API layer. Prefer consistent client setup and e
- Compose only the features you need, in a clear order
- Handle `tuple-result` values explicitly; prefer the tuple pattern from `.agent/rules/tuple-result.md`
- Distinguish network failures from request failures when behavior differs
- Keep request configuration explicit: base URL, headers, timeout, auth
- Keep request configuration explicit: base URL, headers, and auth; use `signal` for cancellation
- Keep GraphQL operations in dedicated files and use `gql`

## Avoid
Expand All @@ -22,12 +22,10 @@ Use `feature-fetch` as the typed API layer. Prefer consistent client setup and e
## Example

```ts
const itemId = 'item-123';
const itemResult = await apiClient.get('/items/{itemId}', {
const [isItemOk, itemErr, item] = await api.get<Item>('/items/{itemId}', {
pathParams: { itemId }
});

const [isItemOk, itemErr, item] = itemResult;
if (!isItemOk) {
if (itemErr instanceof NetworkError) {
throw new AppError('Failed to connect', { cause: itemErr });
Expand All @@ -36,5 +34,5 @@ if (!isItemOk) {
throw itemErr;
}

return item.data;
return item;
```
10 changes: 5 additions & 5 deletions .agent/rules/feature-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ Use `feature-state` and `feature-react/state` as the default state pattern in pr
- Name states with a `$` prefix like `$count`, `$status`, or `$selectedId`
- Use `useFeatureState(state)` when the component needs the raw value and should re-render on changes
- Use `useCompute(state, compute)` when the component needs a derived value from one state
- Use `useCombinedCompute(states, compute)` when the view depends on multiple states together
- Use `useCompute(states, compute)` when the view depends on multiple states together
- Use `useListener(state, callback)` for side effects driven by state changes
- Keep state creation and state mutation helpers outside components unless the state is truly local to one component

## Avoid

- Do not put many unrelated fields into one state object when separate atoms would stay clearer
- Do not read `state._v` directly in app code when a hook or public API fits
- Do not use `useFeatureState` and then derive large computed values inline on every render when `useCompute` or `useCombinedCompute` would express the intent better
- Do not use `useFeatureState` and then derive large computed values inline on every render when `useCompute` would express the intent better
- Do not use `useListener` for simple rendering; keep it for effects and subscriptions
- Do not create ad-hoc React state when the feature already has a matching `feature-state` source of truth

Expand All @@ -25,10 +25,10 @@ Use `feature-state` and `feature-react/state` as the default state pattern in pr
### Good

```tsx
const label = useCompute($seconds, ({ value = 0 }) => formatSeconds(value));
const isDisabled = useCombinedCompute(
const label = useCompute($seconds, (seconds = 0) => formatSeconds(seconds));
const isDisabled = useCompute(
[$status, $selectedId] as const,
([{ value: status = 'idle' }, { value: selectedId = null }]) => {
([status = 'idle', selectedId = null]) => {
return status === 'loading' || selectedId == null;
}
);
Expand Down
2 changes: 1 addition & 1 deletion .agent/rules/tuple-result.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Use `tuple-result` as the default Result pattern when working with repo code tha
- Treat the first slot as the primary branch condition
- Handle the error branch explicitly before using the value
- Use `Ok(...)` and `Err(...)` to construct results
- Use helpers like `mapOk`, `mapErr`, `match`, `unwrapOr`, and `tAsync` when they make the code simpler
- Use helpers like `t`, `tAsync`, `mapOk`, `mapErr`, `match`, and `unwrapOr` when they make the code simpler

## Avoid

Expand Down
58 changes: 48 additions & 10 deletions .agent/rules/vitest.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ Write tests so they read like small specifications.
## Enforce

- Place tests next to the source file they cover
- Use `.test.ts` or `.test.tsx`
- Use `.test.ts`, `.test.tsx`, or `.test-d.ts` for type tests
- Group tests with `describe`
- Use one top-level `describe` for the unit under test
- Add nested `describe` blocks only for public members or meaningful behavior categories
- Include the subject kind in concrete `describe` names, such as `createForm function`, `FlatQueue class`, `listen method`, or `value property`
- Omit the subject kind from category `describe` names, such as `types`, `validation`, or `dirty tracking`
- Start `it(...)` descriptions with `should`
- Keep each test focused on one behavior
- Prefer 80/20 coverage by default: cover the core contract, important edge cases, and regressions without exhaustive case matrices unless explicitly requested
- Use Prepare / Act / Assert structure when the test has more than a couple of steps
- Use `async` / `await` for async tests
- Cover both success and error paths where behavior matters
Expand All @@ -19,20 +24,53 @@ Write tests so they read like small specifications.
- Do not rely on implicit promises or `.then(...)` chains in tests
- Do not hide setup inside vague helper names
- Do not use unclear test names like `works` or `test x`
- Do not add a kind suffix to category describes that are not testing a concrete package, function, class, method, or property

## Example
## Examples

### Good

```ts
describe('parseInput', () => {
it('should parse valid JSON', () => {
// Prepare
const input = '{"key":"value"}';
describe('createStore function', () => {
describe('types', () => {
it('should infer value types', () => {
const store = createStore('value');

expectTypeOf(store.get()).toEqualTypeOf<string>();
});
});

describe('set method', () => {
it('should notify listeners when the value changes', () => {
// Prepare
const store = createStore(0);
const listener = vi.fn();
store.listen(listener);

// Act
store.set(1);

// Act
const result = parseInput(input);
// Assert
expect(listener).toHaveBeenCalledWith({ value: 1 });
});
});
});
```

// Assert
expect(result).toEqual({ key: 'value' });
### Avoid

```ts
describe('store', () => {
describe('set method edge cases and notification behavior', () => {
it('works', () => {
const store = createStore(0);
const listener = vi.fn();
store.listen(listener);
store.set(1);
store.set(1);
expect(store.get()).toBe(1);
expect(listener).toHaveBeenCalledTimes(1);
});
});
});
```
52 changes: 52 additions & 0 deletions .agent/rules/writing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Writing Rules

Apply these rules to all prose: comments, READMEs, doc strings, PR descriptions, and commit messages.

## Enforce

- Use a colon to introduce an explanation, elaboration, or list that follows naturally from the preceding clause
- Use a comma or split into two sentences when an em dash would otherwise bridge two independent thoughts
- Use parentheses for brief asides that do not need to interrupt the sentence rhythm
- Write in active voice
- Keep sentences short and direct; one idea per sentence is the default
- End full sentences with a period; omit the period on short fragments used as labels or list items

## Avoid

- Do not use em dashes (—); replace with a colon, comma, parentheses, or a restructured sentence depending on context
- Do not use filler phrases ("it is worth noting that", "in order to", "as mentioned above")
- Do not pad sentences with hedges that add no information ("basically", "essentially", "simply")

## Examples

### Good

```
This function has two phases: validation and persistence.
```

```
Mutable values (arrays, objects) are copied before storing.
```

```
Eager validation can feel intrusive before the user has finished filling in the form.
```

```
The library works directly without an adapter.
```

### Avoid

```
This function has two phases — validation and persistence.
```

```
Mutable values — arrays, objects — are copied before storing.
```

```
Eager validation can feel intrusive — the user hasn't finished yet.
```
Loading
Loading