test: add ARNES self-tests and docs index
This commit is contained in:
@@ -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
17
docs/README.md
Normal 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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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`
|
||||||
|
|||||||
BIN
scripts/__pycache__/agent_status.cpython-313.pyc
Normal file
BIN
scripts/__pycache__/agent_status.cpython-313.pyc
Normal file
Binary file not shown.
BIN
scripts/__pycache__/new_ticket.cpython-313.pyc
Normal file
BIN
scripts/__pycache__/new_ticket.cpython-313.pyc
Normal file
Binary file not shown.
BIN
scripts/__pycache__/publish_ticket.cpython-313.pyc
Normal file
BIN
scripts/__pycache__/publish_ticket.cpython-313.pyc
Normal file
Binary file not shown.
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
BIN
tests/__pycache__/test_arnes_core.cpython-313.pyc
Normal file
BIN
tests/__pycache__/test_arnes_core.cpython-313.pyc
Normal file
Binary file not shown.
112
tests/test_arnes_core.py
Normal file
112
tests/test_arnes_core.py
Normal 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()
|
||||||
Reference in New Issue
Block a user