Add Flask web UI, Docker Compose, core engine + tests

- physcom core: CLI, 5-pass pipeline, SQLite repo, 37 tests
- physcom_web: Flask app with HTMX for entity/domain/pipeline/results CRUD
- Docker Compose: web + cli services sharing a named volume for the DB
- Clean up local settings to use wildcard permissions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Simonson, Andrew
2026-02-18 13:59:53 -06:00
parent 6e0f82835a
commit 8118a62242
54 changed files with 3505 additions and 1 deletions

View File

@@ -0,0 +1,82 @@
{% extends "base.html" %}
{% block title %}Combination #{{ combo.id }} — PhysCom{% endblock %}
{% block content %}
<div class="page-header">
<h1>Combination #{{ combo.id }}</h1>
<a href="{{ url_for('results.results_domain', domain_name=domain.name) }}" class="btn">Back to list</a>
</div>
<div class="card">
<dl>
<dt>Domain</dt><dd>{{ domain.name }}</dd>
<dt>Status</dt><dd><span class="badge badge-{{ combo.status }}">{{ combo.status }}</span></dd>
{% if combo.block_reason %}
<dt>Block Reason</dt><dd>{{ combo.block_reason }}</dd>
{% endif %}
{% if result %}
<dt>Composite Score</dt><dd class="score-cell">{{ "%.4f"|format(result.composite_score) }}</dd>
<dt>Pass Reached</dt><dd>{{ result.pass_reached }}</dd>
{% if result.novelty_flag %}
<dt>Novelty</dt><dd>{{ result.novelty_flag }}</dd>
{% endif %}
{% if result.llm_review %}
<dt>LLM Review</dt><dd>{{ result.llm_review }}</dd>
{% endif %}
{% if result.human_notes %}
<dt>Human Notes</dt><dd>{{ result.human_notes }}</dd>
{% endif %}
{% endif %}
</dl>
</div>
<h2>Entities</h2>
<div class="card-grid">
{% for e in combo.entities %}
<div class="card">
<h3><a href="{{ url_for('entities.entity_detail', entity_id=e.id) }}">{{ e.name }}</a></h3>
<p class="subtitle">{{ e.dimension }}</p>
<p>{{ e.description }}</p>
<table class="compact">
<thead><tr><th>Key</th><th>Value</th><th>Type</th></tr></thead>
<tbody>
{% for dep in e.dependencies %}
<tr>
<td>{{ dep.key }}</td>
<td>{{ dep.value }}{{ ' ' + dep.unit if dep.unit else '' }}</td>
<td><span class="badge badge-{{ dep.constraint_type }}">{{ dep.constraint_type }}</span></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endfor %}
</div>
{% if scores %}
<h2>Per-Metric Scores</h2>
<div class="card">
<table>
<thead>
<tr><th>Metric</th><th>Raw Value</th><th>Normalized</th><th>Method</th><th>Confidence</th></tr>
</thead>
<tbody>
{% for s in scores %}
<tr>
<td>{{ s.metric_name }}</td>
<td>{{ "%.2f"|format(s.raw_value) if s.raw_value is not none else '—' }}</td>
<td class="score-cell">{{ "%.4f"|format(s.normalized_score) if s.normalized_score is not none else '—' }}</td>
<td>{{ s.estimation_method or '—' }}</td>
<td>{{ "%.2f"|format(s.confidence) if s.confidence is not none else '—' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<h2>Human Review</h2>
<div id="review-section">
{% include "results/_review_form.html" %}
</div>
{% endblock %}