.agents: adopt agentsfolder/spec v0.1 as canonical agent configuration
Per template (singularity-forge f3d84cd11). Project-specific manifest + prompts/project.md capture: post-rename namespace com.centralcloud.oncall (io.heckel.ntfy fully gone), centrally-configured-from-server design, strict-opt-in SMS relay, greenfield (no backwards compat with upstream ntfy). Legacy docs (AGENTS.md, README.md, TESTING.md) kept; .agents/ canonical going forward. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
78815896cc
commit
fb8f45e9fa
17 changed files with 427 additions and 0 deletions
53
.agents/manifest.yaml
Normal file
53
.agents/manifest.yaml
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
# .agents/ canonical agent configuration
|
||||||
|
# Spec: https://github.com/agentsfolder/spec
|
||||||
|
#
|
||||||
|
# Status: pre-1.0 spec adoption. Schema may shift.
|
||||||
|
|
||||||
|
specVersion: "0.1.0"
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
mode: build
|
||||||
|
policy: default-safe
|
||||||
|
|
||||||
|
enabled:
|
||||||
|
modes:
|
||||||
|
- ask
|
||||||
|
- build
|
||||||
|
policies:
|
||||||
|
- default-safe
|
||||||
|
- yolo
|
||||||
|
skills: []
|
||||||
|
|
||||||
|
resolution:
|
||||||
|
enableUserOverlay: false
|
||||||
|
denyOverridesAllow: true
|
||||||
|
onConflict: error
|
||||||
|
|
||||||
|
project:
|
||||||
|
name: oncall-mobile-android
|
||||||
|
description: >-
|
||||||
|
Centralcloud OnCall — Android pager app. Forked from ntfy-android,
|
||||||
|
fully renamed (package com.centralcloud.oncall). Includes the
|
||||||
|
SMS-relay subsystem that forwards whitelisted incoming SMS to
|
||||||
|
centralcloud-ops via /api/sms/inbound/phone-relay.
|
||||||
|
languages:
|
||||||
|
- kotlin
|
||||||
|
- java
|
||||||
|
frameworks:
|
||||||
|
- android
|
||||||
|
- okhttp
|
||||||
|
- workmanager
|
||||||
|
- room
|
||||||
|
|
||||||
|
x:
|
||||||
|
centralcloud:
|
||||||
|
legacy_pointers:
|
||||||
|
- AGENTS.md
|
||||||
|
- README.md
|
||||||
|
- TESTING.md
|
||||||
|
- flake.nix
|
||||||
|
note: >-
|
||||||
|
Package namespace post-rename is com.centralcloud.oncall. The
|
||||||
|
io.heckel.ntfy namespace is entirely removed from the source
|
||||||
|
tree as of commit d5694a32. Custom subsystems live under
|
||||||
|
com.centralcloud.oncall.sms (SMS relay + device heartbeat).
|
||||||
36
.agents/modes/ask.md
Normal file
36
.agents/modes/ask.md
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
id: ask
|
||||||
|
title: Ask
|
||||||
|
policy: default-safe
|
||||||
|
enableSkills: []
|
||||||
|
disableSkills: []
|
||||||
|
includeSnippets: []
|
||||||
|
toolIntent:
|
||||||
|
allow:
|
||||||
|
- read
|
||||||
|
- search
|
||||||
|
- web_fetch
|
||||||
|
deny:
|
||||||
|
- write
|
||||||
|
- exec_command
|
||||||
|
- git_commit
|
||||||
|
- git_push
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ask Mode
|
||||||
|
|
||||||
|
Read-only investigation. Answer questions about the codebase, propose
|
||||||
|
plans, but **make no changes**.
|
||||||
|
|
||||||
|
Use this mode when:
|
||||||
|
|
||||||
|
- The user is exploring or trying to understand something.
|
||||||
|
- A plan needs review before implementation.
|
||||||
|
- The right next step is unclear and probing the code base will help.
|
||||||
|
|
||||||
|
Switch to Build (Shift+Tab) when the user is ready for the agent to
|
||||||
|
make changes.
|
||||||
|
|
||||||
|
This mode's policy denies writes, command execution, and git mutation.
|
||||||
|
If a task requires any of those, surface that fact rather than
|
||||||
|
attempting and failing.
|
||||||
40
.agents/modes/build.md
Normal file
40
.agents/modes/build.md
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
---
|
||||||
|
id: build
|
||||||
|
title: Build
|
||||||
|
policy: default-safe
|
||||||
|
enableSkills: []
|
||||||
|
disableSkills: []
|
||||||
|
includeSnippets: []
|
||||||
|
toolIntent:
|
||||||
|
allow:
|
||||||
|
- read
|
||||||
|
- search
|
||||||
|
- web_fetch
|
||||||
|
- write
|
||||||
|
- exec_command
|
||||||
|
- git_commit
|
||||||
|
deny:
|
||||||
|
- git_push_force
|
||||||
|
- rm_rf
|
||||||
|
- drop_table
|
||||||
|
---
|
||||||
|
|
||||||
|
# Build Mode
|
||||||
|
|
||||||
|
Active development. Make changes, run tests, commit.
|
||||||
|
|
||||||
|
Confirmations are required for destructive operations per the
|
||||||
|
default-safe policy (rm -rf, git push --force, git reset --hard,
|
||||||
|
drop_table, etc.). Toggle the YOLO flag (Ctrl+Y) to drop those
|
||||||
|
confirmations — that's a flag on Build, not a separate mode.
|
||||||
|
|
||||||
|
In this mode the agent is expected to:
|
||||||
|
|
||||||
|
- Run tests before committing.
|
||||||
|
- Group related changes in a single commit; don't bundle unrelated
|
||||||
|
work.
|
||||||
|
- Use Git history as the rationale store — clear commit messages,
|
||||||
|
rationale in the body, link to ADRs when relevant.
|
||||||
|
- Update tests when changing behaviour.
|
||||||
|
- Promote durable decisions to `docs/adr/` rather than burying them
|
||||||
|
in commit messages.
|
||||||
50
.agents/policies/default-safe.yaml
Normal file
50
.agents/policies/default-safe.yaml
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
id: default-safe
|
||||||
|
description: >-
|
||||||
|
Conservative default. Confirmations required for destructive
|
||||||
|
filesystem and git operations; network and exec allowed but logged.
|
||||||
|
|
||||||
|
capabilities:
|
||||||
|
filesystem:
|
||||||
|
read: allow
|
||||||
|
write: confirm
|
||||||
|
delete: confirm
|
||||||
|
exec:
|
||||||
|
enabled: confirm
|
||||||
|
network:
|
||||||
|
enabled: allow
|
||||||
|
allow_hosts:
|
||||||
|
- "*"
|
||||||
|
deny_hosts: []
|
||||||
|
mcp:
|
||||||
|
enabled: allow
|
||||||
|
|
||||||
|
paths:
|
||||||
|
allow:
|
||||||
|
- "**"
|
||||||
|
deny:
|
||||||
|
- "~/.ssh/**"
|
||||||
|
- "**/.env"
|
||||||
|
- "**/.env.*"
|
||||||
|
- "**/secrets/**"
|
||||||
|
- ".sf/sf.db"
|
||||||
|
- ".sf/sf.db-*"
|
||||||
|
- ".sf/backups/**"
|
||||||
|
redact:
|
||||||
|
- "**/*api_key*"
|
||||||
|
- "**/*token*"
|
||||||
|
- "**/*password*"
|
||||||
|
- "**/.env*"
|
||||||
|
|
||||||
|
confirmations:
|
||||||
|
requiredFor:
|
||||||
|
- rm -rf
|
||||||
|
- git push --force
|
||||||
|
- git push -f
|
||||||
|
- git reset --hard
|
||||||
|
- git clean -fdx
|
||||||
|
- drop_table
|
||||||
|
- drop_database
|
||||||
|
|
||||||
|
limits:
|
||||||
|
max_files_per_op: 100
|
||||||
|
max_command_runtime_sec: 600
|
||||||
44
.agents/policies/yolo.yaml
Normal file
44
.agents/policies/yolo.yaml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
id: yolo
|
||||||
|
description: >-
|
||||||
|
Confirmation-free build mode. Use deliberately — destructive
|
||||||
|
operations execute without prompting. Still respects path denies
|
||||||
|
and redactions; only the confirmation gate is removed.
|
||||||
|
|
||||||
|
capabilities:
|
||||||
|
filesystem:
|
||||||
|
read: allow
|
||||||
|
write: allow
|
||||||
|
delete: allow
|
||||||
|
exec:
|
||||||
|
enabled: allow
|
||||||
|
network:
|
||||||
|
enabled: allow
|
||||||
|
allow_hosts:
|
||||||
|
- "*"
|
||||||
|
deny_hosts: []
|
||||||
|
mcp:
|
||||||
|
enabled: allow
|
||||||
|
|
||||||
|
paths:
|
||||||
|
allow:
|
||||||
|
- "**"
|
||||||
|
deny:
|
||||||
|
- "~/.ssh/**"
|
||||||
|
- "**/.env"
|
||||||
|
- "**/.env.*"
|
||||||
|
- "**/secrets/**"
|
||||||
|
- ".sf/sf.db"
|
||||||
|
- ".sf/sf.db-*"
|
||||||
|
- ".sf/backups/**"
|
||||||
|
redact:
|
||||||
|
- "**/*api_key*"
|
||||||
|
- "**/*token*"
|
||||||
|
- "**/*password*"
|
||||||
|
- "**/.env*"
|
||||||
|
|
||||||
|
confirmations:
|
||||||
|
requiredFor: []
|
||||||
|
|
||||||
|
limits:
|
||||||
|
max_files_per_op: 1000
|
||||||
|
max_command_runtime_sec: 3600
|
||||||
3
.agents/profiles/.gitkeep
Normal file
3
.agents/profiles/.gitkeep
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# profiles/ is REQUIRED per .agents spec but MAY be empty.
|
||||||
|
# Profiles are named overlays (e.g., "dev", "ci") that modify
|
||||||
|
# canonical configuration. None defined yet.
|
||||||
12
.agents/prompts/base.md
Normal file
12
.agents/prompts/base.md
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Base Prompt
|
||||||
|
|
||||||
|
You are an AI agent working in this repository. Before changing code:
|
||||||
|
|
||||||
|
1. Read the file you're editing in full.
|
||||||
|
2. Read related files (callers, callees, tests).
|
||||||
|
3. Match existing patterns and style.
|
||||||
|
4. Add or update tests for behavior changes.
|
||||||
|
|
||||||
|
Default to the smallest change that solves the problem. Prefer fixing
|
||||||
|
the root cause over patching the symptom. Surface uncertainties to the
|
||||||
|
operator rather than guessing.
|
||||||
49
.agents/prompts/project.md
Normal file
49
.agents/prompts/project.md
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Project Prompt — oncall-mobile-android
|
||||||
|
|
||||||
|
## What this is
|
||||||
|
|
||||||
|
Centralcloud OnCall Android pager. Forked from `binwiederhier/ntfy-android`;
|
||||||
|
fully renamed to `com.centralcloud.oncall` (no `io.heckel.ntfy` left in
|
||||||
|
the source tree).
|
||||||
|
|
||||||
|
Engineer's single pane for on-call: paging, conference bridge, agent
|
||||||
|
chat, plus an SMS-relay subsystem that forwards whitelisted incoming
|
||||||
|
SMS from this device's number to centralcloud-ops.
|
||||||
|
|
||||||
|
For the long form see [`AGENTS.md`](../../AGENTS.md). For test setup
|
||||||
|
see [`TESTING.md`](../../TESTING.md). For the build shell see
|
||||||
|
[`flake.nix`](../../flake.nix).
|
||||||
|
|
||||||
|
## Non-negotiables
|
||||||
|
|
||||||
|
- **Package namespace is `com.centralcloud.oncall`.** Don't reintroduce
|
||||||
|
`io.heckel.ntfy` in any file — the rename is complete and absolute.
|
||||||
|
- **Centrally configured.** App hits
|
||||||
|
`GET https://ops.centralcloud.com/api/android/config` on first
|
||||||
|
launch — everything else (server URLs, default topics, FCM project)
|
||||||
|
comes from there. Hardcode at most one URL.
|
||||||
|
- **Strict opt-in for SMS relay.** `SmsRelayPreferences.enabled`
|
||||||
|
defaults false. Whitelist is required (empty set → forward nothing).
|
||||||
|
Disclosure must be clear in the settings UI — the app reads
|
||||||
|
incoming SMS, and that's sensitive.
|
||||||
|
- **Greenfield, no backwards compat with upstream ntfy.** Backup
|
||||||
|
format magic was rewritten (`oncall26`), URL scheme is `oncall://`,
|
||||||
|
intent action namespaces are `com.centralcloud.oncall.*` (e.g.
|
||||||
|
`com.centralcloud.oncall.SEND_MESSAGE`).
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
- Build via Nix dev shell: `nix develop` then `./gradlew assembleDebug`.
|
||||||
|
- Tests: see TESTING.md.
|
||||||
|
- Install on ops phones: `adb install -r app/build/outputs/apk/...`.
|
||||||
|
- SMS-relay config: launch
|
||||||
|
`adb shell am start -n com.centralcloud.oncall/.sms.SmsRelaySettingsActivity`,
|
||||||
|
set base URL + device ID + whitelist + toggle on.
|
||||||
|
|
||||||
|
## Sibling repos
|
||||||
|
|
||||||
|
- **`centralcloud/infra`** — the centralcloud-ops Phoenix app this
|
||||||
|
connects to (`/api/push/*`, `/api/sms/inbound/phone-relay`,
|
||||||
|
`/api/devices/heartbeat`, etc.).
|
||||||
|
- **`centralcloud/operations-memory`** — Go memory service.
|
||||||
|
- **`singularity/singularity-forge`** — SF planning tool.
|
||||||
1
.agents/prompts/snippets/.gitkeep
Normal file
1
.agents/prompts/snippets/.gitkeep
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
# Snippets composed into modes via Mode front matter `includeSnippets`.
|
||||||
3
.agents/schemas/.gitkeep
Normal file
3
.agents/schemas/.gitkeep
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# schemas/ is REQUIRED per .agents spec but MAY be generated.
|
||||||
|
# Tooling that validates .agents/ configuration writes JSON Schema
|
||||||
|
# files here. Treat as generated output, not hand-edited.
|
||||||
3
.agents/scopes/.gitkeep
Normal file
3
.agents/scopes/.gitkeep
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# scopes/ is REQUIRED per .agents spec but MAY be empty.
|
||||||
|
# Scopes provide path-based overrides for monorepos. SF is a single
|
||||||
|
# tree today; add scopes if/when subprojects need different policies.
|
||||||
2
.agents/skills/.gitkeep
Normal file
2
.agents/skills/.gitkeep
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
# skills/ is REQUIRED per .agents spec but MAY be empty.
|
||||||
|
# Skills declared here MUST follow https://agentskills.io/specification.
|
||||||
37
.agents/skills/forge-autonomous-runtime/SKILL.md
Normal file
37
.agents/skills/forge-autonomous-runtime/SKILL.md
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
name: forge-autonomous-runtime
|
||||||
|
description: Explains SF autonomous loop, UOK gates, installed-runtime drift, and recovery paths.
|
||||||
|
user-invocable: false
|
||||||
|
model-invocable: true
|
||||||
|
side-effects: none
|
||||||
|
permission-profile: restricted
|
||||||
|
triggers:
|
||||||
|
- "*"
|
||||||
|
---
|
||||||
|
|
||||||
|
# forge-autonomous-runtime
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
SF's autonomous mode is governed by the Unified Operation Kernel (UOK):
|
||||||
|
|
||||||
|
1. **State reading** — UOK reads canonical project state from `.sf/sf.db`
|
||||||
|
2. **Ledger recording** — Each run is recorded in the DB-backed ledger
|
||||||
|
3. **Projection** — Runtime files under `.sf/runtime/` are generated projections
|
||||||
|
4. **Dispatch** — UOK determines the next unit of work and creates a fresh agent session
|
||||||
|
5. **Execution** — LLM executes with focused prompt and pre-inlined context
|
||||||
|
6. **Reconciliation** — UOK reconciles ledger and projections before next dispatch
|
||||||
|
|
||||||
|
## Recovery Paths
|
||||||
|
|
||||||
|
- **Crash recovery** — Lock file tracks current unit; next `/autonomous` reads surviving state
|
||||||
|
- **Stuck detection** — Loop detects stuck iterations and emits `stuck-detected` journal events
|
||||||
|
- **Health gates** — Pre-dispatch gates check state integrity before execution
|
||||||
|
- **Parity reports** — Ledger parity ensures no orphaned or missing unit records
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- Never modify `.sf/sf.db` directly — use UOK APIs
|
||||||
|
- Never trust `.sf/runtime/` files as authoritative — they are projections
|
||||||
|
- Always check `runControl` and `permissionProfile` before tool invocation
|
||||||
|
- Journal events are best-effort; absence is a failure signal
|
||||||
48
.agents/skills/forge-command-surface/SKILL.md
Normal file
48
.agents/skills/forge-command-surface/SKILL.md
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
name: forge-command-surface
|
||||||
|
description: Use when changing SF slash commands, browser command parity, or headless command dispatch.
|
||||||
|
user-invocable: true
|
||||||
|
model-invocable: true
|
||||||
|
side-effects: code-edits
|
||||||
|
permission-profile: normal
|
||||||
|
triggers:
|
||||||
|
- build
|
||||||
|
- code
|
||||||
|
- "*"
|
||||||
|
---
|
||||||
|
|
||||||
|
# forge-command-surface
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
This skill applies when:
|
||||||
|
- Adding or modifying SF slash commands (`/mode`, `/tasks`, `/skills`, etc.)
|
||||||
|
- Changing command handlers in `src/resources/extensions/sf/commands/handlers/`
|
||||||
|
- Updating command catalog descriptions
|
||||||
|
- Ensuring web/TUI/headless command parity
|
||||||
|
- Modifying command dispatch routing
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
1. **Check existing handlers** — Look in `commands/handlers/core.js` and `commands/handlers/ops.js` for the pattern
|
||||||
|
2. **Update catalog** — Add to `commands/catalog.js` `TOP_LEVEL_SUBCOMMANDS`
|
||||||
|
3. **Update help text** — Add to `showHelp()` in `commands/handlers/core.js`
|
||||||
|
4. **Wire dispatch** — Add routing in `handleCoreCommand()` or `handleOpsCommand()`
|
||||||
|
5. **Test** — Verify with `node --check` and manual test
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
- [ ] Command appears in `/help`
|
||||||
|
- [ ] Command appears in `/help all`
|
||||||
|
- [ ] Handler file passes `node --check`
|
||||||
|
- [ ] No `/sf` prefix in user-facing strings
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Adding a new command
|
||||||
|
if (trimmed === "mycommand" || trimmed.startsWith("mycommand ")) {
|
||||||
|
await handleMyCommand(trimmed.replace(/^mycommand\s*/, "").trim(), ctx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
```
|
||||||
26
.agents/skills/nix-build/SKILL.md
Normal file
26
.agents/skills/nix-build/SKILL.md
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
name: nix-build
|
||||||
|
description: Build any @singularity-forge/* package (or the full stack) via nix develop. Pass a package name like "pi-coding-agent", "native", "daemon", or "all" for a full core build.
|
||||||
|
---
|
||||||
|
|
||||||
|
All build commands in this repo must run inside `nix develop`. Never use bare cargo/rustc.
|
||||||
|
|
||||||
|
For a single package:
|
||||||
|
```
|
||||||
|
nix develop --command bash -c "npm run --workspace=@singularity-forge/<package> build"
|
||||||
|
```
|
||||||
|
|
||||||
|
For the full core build (native + all TS packages):
|
||||||
|
```
|
||||||
|
nix develop --command bash -c "npm run build:core"
|
||||||
|
```
|
||||||
|
|
||||||
|
For typecheck only:
|
||||||
|
```
|
||||||
|
nix develop --command bash -c "tsc --noEmit -p tsconfig.json"
|
||||||
|
```
|
||||||
|
|
||||||
|
For extensions typecheck:
|
||||||
|
```
|
||||||
|
nix develop --command bash -c "tsc --noEmit -p tsconfig.extensions.json"
|
||||||
|
```
|
||||||
17
.agents/skills/smoke-test/SKILL.md
Normal file
17
.agents/skills/smoke-test/SKILL.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
name: smoke-test
|
||||||
|
description: Run the standard sf-run smoke tests (--version, --help, --print). All three must pass before shipping a build.
|
||||||
|
---
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
echo "=== --version ==="
|
||||||
|
node dist/loader.js --version
|
||||||
|
|
||||||
|
echo "=== --help (first 5 lines) ==="
|
||||||
|
node dist/loader.js --help 2>&1 | head -5
|
||||||
|
|
||||||
|
echo "=== --print (graceful degradation) ==="
|
||||||
|
node dist/loader.js --print 2>&1 | head -5
|
||||||
|
|
||||||
|
echo "All smoke tests passed."
|
||||||
3
.agents/state/.gitignore
vendored
Normal file
3
.agents/state/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Per .agents/ spec: state.yaml is per-developer convenience state
|
||||||
|
# (mode/profile/backend selection). Never commit.
|
||||||
|
state.yaml
|
||||||
Loading…
Add table
Reference in a new issue