Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Questions and integration help
url: https://github.com/kevindechang/affect-kernel/discussions
about: Ask usage questions and discuss adapter or domain design.
- name: Report a security vulnerability
url: https://github.com/kevindechang/affect-kernel/security/advisories/new
about: Report vulnerabilities privately; do not open a public issue.
23 changes: 21 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: Release

# Publishes both runtimes from one tag. The full check suite must pass first, so
# a tag can never publish something CI would have rejected.
# Publishes both runtimes and GitHub release notes from one tag. The full check
# suite must pass first, so a tag can never publish something CI would have
# rejected.
on:
push:
tags: ["v*"]
Expand Down Expand Up @@ -96,3 +97,21 @@ jobs:
- run: npm publish ./typescript --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

github-release:
needs: [pypi, npm]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: write
steps:
- name: Publish generated release notes
env:
GH_TOKEN: ${{ github.token }}
run: >-
gh release create "$GITHUB_REF_NAME"
--repo "$GITHUB_REPOSITORY"
--verify-tag
--generate-notes
--title "$GITHUB_REF_NAME"
32 changes: 17 additions & 15 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,19 @@ to a pinned vector is called out here.

## [Unreleased]

### Added
No changes yet.

## [0.1.0] - 2026-08-21

First public release: the deterministic kernel extracted from
[Anjo](https://anjo.love) and generalized beyond conversation.

The repository was briefly public as `anjo-core` before this release and was
renamed to `affect-kernel` to name the library by what it does rather than by
the application it came from. No version was ever tagged or published under the
old name, so no installed artifact is affected.

### Evaluation and hardening

- `AffectDynamics` and `RetrievalWeights`: the numeric coefficients are now
caller-owned data, on the same principle that already made stage names,
Expand Down Expand Up @@ -41,14 +53,14 @@ to a pinned vector is called out here.
carries signal and that mood congruence is worth +0.012 MRR in a regime built
to favour it.

### Fixed
### Corrected claims

- Retracted a claim in `docs/foundations.md` and in the `recency_weight`
docstring that linear-to-a-floor recency was "the least defensible" curve in
the module. At a matched 30-day half-life it out-ranks both the exponential
and the power-law curve.

### Changed
### Breaking pre-release changes

- **Breaking (pre-release):** `CompanionState` is now `AffectState` and
`CompanionEngine` is `AffectEngine`, in both runtimes, along with
Expand All @@ -69,17 +81,7 @@ to a pinned vector is called out here.
(`x1.10` negative, `x1.04` positive above `|v| >= 0.20`), which was
implemented but undocumented.

## [0.1.0]

First public release: the deterministic kernel extracted from
[Anjo](https://anjo.love) and generalized beyond conversation.

The repository was briefly public as `anjo-core` before this release and was
renamed to `affect-kernel` to name the library by what it does rather than by
the application it came from. No version was ever tagged or published under the
old name, so no installed artifact is affected.

### Added
### Initial public surface

- Behaviorally aligned Python and TypeScript kernels with no runtime
dependencies, both published as `affect-kernel`.
Expand Down Expand Up @@ -108,7 +110,7 @@ old name, so no installed artifact is affected.
- Public-boundary verification, pinned Gitleaks history scan, and reproducible
packaging checks.

### Fixed
### Pre-release fixes

- `FrozenMapping` is picklable. The default `dict` pickle protocol restores
items by mutating a fresh instance, which the class refuses, so every state
Expand Down
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Affect Kernel

[![CI](https://github.com/kevindechang/affect-kernel/actions/workflows/ci.yml/badge.svg)](https://github.com/kevindechang/affect-kernel/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/affect-kernel.svg)](https://pypi.org/project/affect-kernel/)
[![npm](https://img.shields.io/npm/v/affect-kernel.svg)](https://www.npmjs.com/package/affect-kernel)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](python/)
[![Node](https://img.shields.io/badge/node-20%2B-blue.svg)](typescript/)
Expand Down Expand Up @@ -119,22 +121,21 @@ before quoting any of this.

## Install

Neither runtime has a production dependency. Install from a checkout:
Both packages have zero runtime dependencies:

```bash
# Python 3.11+
python -m venv .venv && source .venv/bin/activate
python -m pip install -e "./python[dev]"
pytest python/tests

# Node.js 20+
npm ci --prefix typescript
npm test --prefix typescript
python -m pip install affect-kernel # import affect_kernel
npm install affect-kernel
```

> Registry releases are not published yet. Once `v0.1.0` is tagged, the
> [release workflow](.github/workflows/release.yml) publishes `affect-kernel` to PyPI
> via trusted publishing and `affect-kernel` to npm with provenance.
For a contributor checkout:

```bash
git clone https://github.com/kevindechang/affect-kernel.git
cd affect-kernel
./scripts/setup.sh
./scripts/check.sh
```

## Core contracts

Expand Down
9 changes: 6 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

## Supported versions

Until the first stable release, security fixes are applied to the latest commit
on `main`.
Security fixes are applied to the latest `0.1.x` release and to `main`.

| Version | Supported |
|---|---|
| `0.1.x` | Yes |
| `< 0.1` | No |

## Reporting a vulnerability

Expand All @@ -29,4 +33,3 @@ adapters belong to the application integrating them. This project will still
accept reports about unsafe defaults, state-boundary violations, prompt injection
across adapter boundaries, data leakage in examples/tests, and dependency or
packaging vulnerabilities.

23 changes: 23 additions & 0 deletions SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Support

## Questions and integration help

Use [GitHub Discussions](https://github.com/kevindechang/affect-kernel/discussions)
for usage questions, adapter design, and ideas that are not yet concrete feature
requests. Include your runtime and package version, and reduce examples to
synthetic data.

## Bugs and feature proposals

Use the repository's structured issue forms for reproducible bugs and broadly
reusable feature proposals. Search existing issues first. Real conversation
data, credentials, proprietary prompts, and production configuration do not
belong in an issue or discussion.

## Security reports

Follow [SECURITY.md](SECURITY.md) and use GitHub private vulnerability reporting.
Do not disclose a vulnerability in a public issue or discussion.

This is a single-maintainer project. Expect a first response within about a
week; changes to the parity contract can take longer to review.
20 changes: 18 additions & 2 deletions python/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
# affect-kernel for Python

This directory contains the zero-runtime-dependency Python implementation of the
deterministic affect-state kernel for long-lived AI characters. Install it with
`python -m pip install -e .`; run its tests with `python -m pytest`.
deterministic affect-state kernel for long-lived AI characters.

```bash
python -m pip install affect-kernel
```

```python
from affect_kernel import AffectState, appraise_turn

state = AffectState()
result = appraise_turn(state, "CURIOSITY")
print(result.state.mood)
```

The [repository README](https://github.com/kevindechang/affect-kernel#readme)
contains runnable headless examples, benchmark results, limitations, and the
cross-runtime contract. From a source checkout, run `./scripts/setup.sh` and
`./scripts/check.sh` at the repository root.

The package deliberately leaves model inference, persistence, and retrieval I/O
behind injected protocols. Its cross-runtime guarantee covers deterministic,
Expand Down
2 changes: 2 additions & 0 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ dependencies = []
Homepage = "https://github.com/kevindechang/affect-kernel"
Repository = "https://github.com/kevindechang/affect-kernel"
Issues = "https://github.com/kevindechang/affect-kernel/issues"
Changelog = "https://github.com/kevindechang/affect-kernel/blob/main/CHANGELOG.md"
Documentation = "https://github.com/kevindechang/affect-kernel/tree/main/docs"

[project.optional-dependencies]
dev = [
Expand Down
13 changes: 13 additions & 0 deletions scripts/tests/test_public_boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,19 @@ def test_boundary_rejects_binary_payload_in_an_allowed_directory(
assert any("binary file is not allowed" in error for error in errors)


def test_boundary_allows_reviewed_support_policy(
tmp_path: Path,
fixture: dict[str, Any],
continuity_fixture: dict[str, Any],
) -> None:
_write_minimal_candidate(tmp_path, fixture, continuity_fixture)
(tmp_path / "SUPPORT.md").write_text("# Support\n", encoding="utf-8")

errors = verify(tmp_path)

assert not any("unexpected top-level entries" in error for error in errors)


def test_boundary_scans_force_tracked_ignored_paths(
tmp_path: Path,
fixture: dict[str, Any],
Expand Down
1 change: 1 addition & 0 deletions scripts/verify_public_boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"README.md",
"ROADMAP.md",
"SECURITY.md",
"SUPPORT.md",
"bench",
"docs",
"examples",
Expand Down
8 changes: 8 additions & 0 deletions typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ characters. It provides deterministic affect, appraisal, memory scoring, presenc
surfacing, and an engine with injected model, appraisal, storage, and retrieval
adapters. Application instructions and prompt wording remain caller-owned.

```sh
npm install affect-kernel
```

The [repository README](https://github.com/kevindechang/affect-kernel#readme)
contains runnable headless examples, benchmark results, limitations, and the
cross-runtime contract.

The engine runtime-validates unknown gate output, normalizes built-in or explicitly
registered custom intents, and propagates gate errors unless `gateFallback` is supplied.
`AppraisalPolicy` is a synchronous injection seam; `DEFAULT_APPRAISAL_POLICY` preserves
Expand Down
1 change: 1 addition & 0 deletions typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "affect-kernel",
"version": "0.1.0",
"description": "Deterministic affect-state kernel for long-lived AI characters, model-agnostic",
"author": "Chang Chia Wei",
"keywords": [
"affect",
"appraisal",
Expand Down
Loading