test: add ARNES self-tests and docs index

This commit is contained in:
rikrdo
2026-05-18 00:30:39 +02:00
parent b396b6d3c9
commit aaf33880c4
11 changed files with 157 additions and 3 deletions

View File

@@ -207,6 +207,7 @@ El núcleo no cambia; solo el adaptador.
- Guía breve: `HOWTO.md` - Guía breve: `HOWTO.md`
- Starter pack: `starter-pack/README.md` - Starter pack: `starter-pack/README.md`
- Adaptación del template: `TEMPLATE.md` - Adaptación del template: `TEMPLATE.md`
- Índice de docs: `docs/README.md`
- Layout del repo: `docs/repository-layout.md` - Layout del repo: `docs/repository-layout.md`
- Referencia de scripts: `docs/scripts-reference.md` - Referencia de scripts: `docs/scripts-reference.md`
- Manual Skeleton (uso + mejoras): `docs/skeleton-manual.md` - Manual Skeleton (uso + mejoras): `docs/skeleton-manual.md`

17
docs/README.md Normal file
View File

@@ -0,0 +1,17 @@
# Docs index
## Core docs
- `../README.md` — framework overview
- `../HOWTO.md` — quick start
- `../HOWTO-FEATURE.md` — feature workflow
- `../TEMPLATE.md` — how to adapt ARNES
## Reference docs
- `repository-layout.md` — repo structure and separation rules
- `scripts-reference.md` — start/verify/ticket/publish/install scripts
- `skeleton-manual.md` — default Skeleton UI notes
## Harness source of truth
- `../harness/agents.matrix.yml` — roles and edit boundaries
- `../harness/workflow.stages.yml` — ordered workflow stages
- `../harness/policies/` — governance, security, quality, language, model routing

View File

@@ -13,15 +13,17 @@
- `harness/` — workflow, roles, policies, contracts - `harness/` — workflow, roles, policies, contracts
- `spec/` — product, tech, acceptance, SDD, BDD source docs - `spec/` — product, tech, acceptance, SDD, BDD source docs
- `features/` — optional executable BDD runner assets - `features/` — optional executable BDD runner assets
- `scripts/` — start, verify, ticket creation, runtime status - `scripts/` — start, verify, ticket creation, publish, install, runtime status
- `platforms/` — platform adapters (pi, opencode) - `platforms/` — platform adapters (pi, opencode)
- `defaults/` — optional starter assets - `defaults/` — optional starter assets
- `tests/` — self-tests for the ARNES source repo only
## Recommended separation ## Recommended separation
- Core ARNES should stay generic. - Core ARNES should stay generic.
- Domain checks go in `scripts/verify.local.sh`. - Domain checks go in `scripts/verify.local.sh`.
- Domain rules go in `AGENTS.local.md`. - Domain rules go in `AGENTS.local.md`.
- Real code should not be mixed into `harness/`, `work/`, `backlog/`, or `spec/`. - Real code should not be mixed into `harness/`, `work/`, `backlog/`, or `spec/`.
- Source-repo self-tests under `tests/` are not part of installed project repos.
## Default project shape ## Default project shape
```text ```text

View File

@@ -14,6 +14,8 @@ Interactive bootstrap wizard.
What it does: What it does:
- asks project metadata - asks project metadata
- chooses default app directory (`project/` by default) - chooses default app directory (`project/` by default)
- defaults Python/Flask projects to `python3 -m unittest discover -s project/tests -v`
- seeds a minimal bootstrap smoke test under `project/tests/` for Python/Flask
- writes `harness/project.config.json` - writes `harness/project.config.json`
- creates `scripts/verify.local.sh` - creates `scripts/verify.local.sh`
- can seed one bootstrap ticket - can seed one bootstrap ticket
@@ -30,6 +32,7 @@ What it checks:
- only one feature is `in_progress` - only one feature is `in_progress`
- done features have all required artifacts, including publish evidence - done features have all required artifacts, including publish evidence
- runtime status JSON is valid - runtime status JSON is valid
- source-repo self-tests run automatically if `tests/` exists
- optional local overlay runs if present - optional local overlay runs if present
## `python3 scripts/new_ticket.py` ## `python3 scripts/new_ticket.py`

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -38,7 +38,12 @@ else
CSSFW="skeleton" CSSFW="skeleton"
fi fi
TEST_CMD="$(ask 'Test command' 'make test')" DEFAULT_TEST_CMD="echo TODO-set-test-command"
if [ "$BACKEND" = "python/flask" ]; then
DEFAULT_TEST_CMD="python3 -m unittest discover -s $APP_DIR/tests -v"
fi
TEST_CMD="$(ask 'Test command' "$DEFAULT_TEST_CMD")"
LINT_CMD="$(ask 'Lint command (optional)' '')" LINT_CMD="$(ask 'Lint command (optional)' '')"
MODEL_MODE="$(ask 'Model mode (lean/balanced/power)' 'lean')" MODEL_MODE="$(ask 'Model mode (lean/balanced/power)' 'lean')"
ADD_BOOTSTRAP="$(ask 'Create bootstrap ticket F-001 now? (y/n)' 'y')" ADD_BOOTSTRAP="$(ask 'Create bootstrap ticket F-001 now? (y/n)' 'y')"
@@ -52,7 +57,19 @@ Configured by ARNES start wizard.
EOF EOF
if [ "$BACKEND" = "python/flask" ]; then if [ "$BACKEND" = "python/flask" ]; then
mkdir -p "$APP_DIR/templates" "$APP_DIR/static/js" "$APP_DIR/static/css" "$APP_DIR/static/images" mkdir -p "$APP_DIR/templates" "$APP_DIR/static/js" "$APP_DIR/static/css" "$APP_DIR/static/images" "$APP_DIR/tests"
[ -f "$APP_DIR/tests/test_bootstrap.py" ] || cat > "$APP_DIR/tests/test_bootstrap.py" <<'PY'
import unittest
class BootstrapSmokeTest(unittest.TestCase):
def test_bootstrap(self):
self.assertTrue(True)
if __name__ == '__main__':
unittest.main()
PY
fi fi
if [ "$CSSFW" = "skeleton" ]; then if [ "$CSSFW" = "skeleton" ]; then
@@ -195,3 +212,4 @@ echo "- Ticket tool: python3 scripts/new_ticket.py"
echo "- Publish tool: python3 scripts/publish_ticket.py --feature-id F-001" echo "- Publish tool: python3 scripts/publish_ticket.py --feature-id F-001"
echo "- Verify: ./scripts/verify.sh" echo "- Verify: ./scripts/verify.sh"
echo "- Runtime: python3 scripts/agent_status.py show" echo "- Runtime: python3 scripts/agent_status.py show"
echo "- Reminder: configure git remote before final publish if missing"

View File

@@ -21,6 +21,7 @@ required=(
"README.md" "README.md"
"HOWTO.md" "HOWTO.md"
"TEMPLATE.md" "TEMPLATE.md"
"docs/README.md"
"docs/repository-layout.md" "docs/repository-layout.md"
"docs/scripts-reference.md" "docs/scripts-reference.md"
"harness/agents.matrix.yml" "harness/agents.matrix.yml"

Binary file not shown.

112
tests/test_arnes_core.py Normal file
View File

@@ -0,0 +1,112 @@
import json
import subprocess
import tempfile
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
INSTALL = ROOT / 'scripts' / 'install_into_repo.sh'
class ArnesCoreTests(unittest.TestCase):
def run_cmd(self, args, cwd=None, input_text=None, check=True):
result = subprocess.run(
args,
cwd=cwd or ROOT,
input=input_text,
text=True,
capture_output=True,
)
if check and result.returncode != 0:
raise AssertionError(
f"Command failed: {args}\nSTDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}"
)
return result
def test_install_refuses_source_repo(self):
result = self.run_cmd([str(INSTALL), str(ROOT)], check=False)
self.assertNotEqual(result.returncode, 0)
self.assertIn('Refusing to install ARNES into its own source repository', result.stdout)
def test_install_start_verify_and_publish_in_external_repo(self):
with tempfile.TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
target = tmp_path / 'project-repo'
remote = tmp_path / 'remote.git'
self.run_cmd([str(INSTALL), str(target)])
self.assertTrue((target / 'scripts' / 'start.sh').is_file())
self.assertFalse((target / 'tests').exists(), 'source self-tests must not be installed into project repo')
self.run_cmd(['git', 'config', 'user.name', 'ARNES Bot'], cwd=target)
self.run_cmd(['git', 'config', 'user.email', 'arnes@example.com'], cwd=target)
self.run_cmd(['git', 'init', '--bare', str(remote)])
self.run_cmd(['git', 'remote', 'add', 'origin', str(remote)], cwd=target)
wizard_input = '\n'.join([
'demo-project',
'Demo project',
'project',
'1',
'',
'',
'',
'',
]) + '\n'
self.run_cmd(['./scripts/start.sh'], cwd=target, input_text=wizard_input)
self.assertTrue((target / 'project' / 'tests').is_dir())
cfg = json.loads((target / 'harness' / 'project.config.json').read_text(encoding='utf-8'))
self.assertEqual(cfg['app_dir'], 'project')
self.assertEqual(cfg['commands']['test'], 'python3 -m unittest discover -s project/tests -v')
verify_result = self.run_cmd(['./scripts/verify.sh'], cwd=target)
self.assertIn('Harness verificado', verify_result.stdout)
self.run_cmd(['python3', 'scripts/new_ticket.py'], cwd=target, input_text='\n'.join([
'fix',
'Repair docs',
'Need docs repair',
'Make docs clear',
'Docs flow',
'No redesign',
'low',
'med',
'Docs clear',
'Verify green',
'',
]) + '\n')
with (target / 'project' / 'README.md').open('a', encoding='utf-8') as fh:
fh.write('\nchange\n')
publish_result = self.run_cmd(
['python3', 'scripts/publish_ticket.py', '--feature-id', 'F-001'],
cwd=target,
)
self.assertIn('done ->', publish_result.stdout)
publish_path = target / 'work' / 'artifacts' / 'F-001' / 'publish.json'
payload = json.loads(publish_path.read_text(encoding='utf-8'))
self.assertEqual(payload['verdict'], 'PUBLISHED')
self.assertTrue(payload['pushed'])
self.assertEqual(payload['remote'], 'origin')
status_result = self.run_cmd(['git', 'status', '--short'], cwd=target)
self.assertEqual(status_result.stdout.strip(), '')
remote_refs = self.run_cmd(['git', 'ls-remote', 'origin'], cwd=target)
self.assertIn('refs/heads/master', remote_refs.stdout)
def test_agent_status_rejects_invalid_agent(self):
result = self.run_cmd(
['python3', 'scripts/agent_status.py', 'set', '--agent', 'nope'],
check=False,
)
self.assertNotEqual(result.returncode, 0)
combined = (result.stdout + result.stderr)
self.assertIn('Invalid agent: nope', combined)
if __name__ == '__main__':
unittest.main()