chore: save current workspace progress
This commit is contained in:
@@ -0,0 +1,432 @@
|
||||
# Daily Summary Job Personal Skill Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Install a personal `daily-summary-job` skill that records compact development checkpoints and generates or updates evidence-grounded Markdown reports with self-contained interactive HTML visualizations.
|
||||
|
||||
**Architecture:** A concise `SKILL.md` orchestrates context/Git evidence collection and semantic classification. A standard-library Python helper validates the normalized JSON fact source, selects safe module/date/topic paths, and renders both deliverables from one source; an HTML asset provides all offline interaction.
|
||||
|
||||
**Tech Stack:** Markdown, YAML, Python 3.12 standard library, HTML5, CSS, inline SVG, native JavaScript, `unittest`, PowerShell verification.
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- Install to `C:\Users\admin\.codex\skills\daily-summary-job`.
|
||||
- Use the normalized skill name `daily-summary-job`; do not use `dailySummary_job` as a folder or YAML name.
|
||||
- Trigger on demand from explicit `$daily-summary-job` invocations or clear natural-language daily progress/report intents; never run in the background.
|
||||
- Never copy full conversations or full logs into checkpoints.
|
||||
- Limit one checkpoint to 5 achievements, 5 issues, and 3 next steps; descriptions should be at most 120 Chinese characters where practical.
|
||||
- Prefer existing `<module>_rep` naming; otherwise use a normalized module, `cross-module_rep`, or `general_rep`.
|
||||
- Store final files under `dailywork_report/<module>_rep/YYYY-MM-DD/`.
|
||||
- Generate Markdown and HTML from the same normalized JSON source.
|
||||
- HTML must be a single offline file with no CDN, network request, third-party library, or external image.
|
||||
- Do not modify ParkingRobot business code, stage files, or create Git commits.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Initialize the personal skill scaffold
|
||||
|
||||
**Files:**
|
||||
- Create: `C:\Users\admin\.codex\skills\daily-summary-job\SKILL.md`
|
||||
- Create: `C:\Users\admin\.codex\skills\daily-summary-job\agents\openai.yaml`
|
||||
- Create directories: `scripts`, `references`, `assets`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `skill-creator/scripts/init_skill.py` and the approved design.
|
||||
- Produces: A discoverable personal skill skeleton with UI metadata.
|
||||
|
||||
- [ ] **Step 1: Confirm the target does not already exist**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
$target = 'C:\Users\admin\.codex\skills\daily-summary-job'
|
||||
if (Test-Path -LiteralPath $target) { throw "Skill already exists: $target" }
|
||||
```
|
||||
|
||||
Expected: no output.
|
||||
|
||||
- [ ] **Step 2: Initialize the skill with required resource folders**
|
||||
|
||||
Run with approval for writing outside the workspace:
|
||||
|
||||
```powershell
|
||||
python 'C:\Users\admin\.codex\skills\.system\skill-creator\scripts\init_skill.py' daily-summary-job `
|
||||
--path 'C:\Users\admin\.codex\skills' `
|
||||
--resources scripts,references,assets `
|
||||
--interface 'display_name=Daily Summary Job' `
|
||||
--interface 'short_description=按需记录、分类并生成带证据与交互可视化的开发工作日报' `
|
||||
--interface 'default_prompt=使用 $daily-summary-job 记录当前开发进展,并生成今日 Markdown 与交互式 HTML 日报。'
|
||||
```
|
||||
|
||||
Expected: `daily-summary-job` is created and `agents/openai.yaml` contains the three interface values.
|
||||
|
||||
- [ ] **Step 3: Inspect only the new scaffold**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
Get-ChildItem -LiteralPath 'C:\Users\admin\.codex\skills\daily-summary-job' -Recurse
|
||||
```
|
||||
|
||||
Expected: `SKILL.md`, `agents/openai.yaml`, and the three resource directories are present.
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Implement deterministic path planning and checkpoint budgets with tests first
|
||||
|
||||
**Files:**
|
||||
- Create: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py`
|
||||
- Create: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `find_project_root(start: Path) -> Path`, `normalize_slug(value: str, fallback: str) -> str`, `infer_module(changed_paths: list[str], report_root: Path, explicit: str | None) -> str`, `plan_paths(...) -> ReportPaths`, and `validate_checkpoint_budget(data: dict) -> None`.
|
||||
- `ReportPaths` exposes `module_dir`, `date_dir`, `state_file`, `markdown_file`, and `html_file` as `Path` values.
|
||||
|
||||
- [ ] **Step 1: Write failing standard-library tests**
|
||||
|
||||
Create tests covering exact behavior:
|
||||
|
||||
```python
|
||||
def test_prefers_existing_module_folder(self):
|
||||
(self.root / "dailywork_report" / "pathsmoothing_rep").mkdir(parents=True)
|
||||
module = target.infer_module(
|
||||
["src/PathSmoothing/LocalG2/Pipeline.cs"],
|
||||
self.root / "dailywork_report",
|
||||
None,
|
||||
)
|
||||
self.assertEqual("pathsmoothing_rep", module)
|
||||
|
||||
def test_multiple_existing_modules_become_cross_module(self):
|
||||
report_root = self.root / "dailywork_report"
|
||||
(report_root / "Map_rep").mkdir(parents=True)
|
||||
(report_root / "coarsepath_rep").mkdir()
|
||||
module = target.infer_module(
|
||||
["src/Map/Grid.cs", "src/CoarsePath/Search.cs"], report_root, None
|
||||
)
|
||||
self.assertEqual("cross-module_rep", module)
|
||||
|
||||
def test_unknown_scope_becomes_general(self):
|
||||
self.assertEqual(
|
||||
"general_rep",
|
||||
target.infer_module(["README.md"], self.root / "dailywork_report", None),
|
||||
)
|
||||
|
||||
def test_rejects_checkpoint_over_budget(self):
|
||||
data = {"achievements": [{"title": str(i)} for i in range(6)], "issues": [], "next_steps": []}
|
||||
with self.assertRaisesRegex(ValueError, "at most 5 achievements"):
|
||||
target.validate_checkpoint_budget(data)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the tests and confirm the expected import failure**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
python 'C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py'
|
||||
```
|
||||
|
||||
Expected: FAIL because `prepare_report.py` does not yet provide the tested API.
|
||||
|
||||
- [ ] **Step 3: Implement safe normalization, module inference, and path planning**
|
||||
|
||||
Use a frozen dataclass and reject traversal:
|
||||
|
||||
```python
|
||||
@dataclass(frozen=True)
|
||||
class ReportPaths:
|
||||
module_dir: Path
|
||||
date_dir: Path
|
||||
state_file: Path
|
||||
markdown_file: Path
|
||||
html_file: Path
|
||||
|
||||
def normalize_slug(value: str, fallback: str) -> str:
|
||||
normalized = unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii")
|
||||
normalized = re.sub(r"[^a-zA-Z0-9]+", "-", normalized).strip("-").lower()
|
||||
if not normalized or normalized in {".", ".."}:
|
||||
normalized = fallback
|
||||
return normalized[:64].rstrip("-") or fallback
|
||||
```
|
||||
|
||||
Implement existing-folder matching before generic path inference. Preserve an existing folder's exact spelling, use `cross-module_rep` for more than one matched module, and `general_rep` when only generic files such as `README.md` are available.
|
||||
|
||||
`plan_paths` must reuse an existing state file with the same date/module/topic in update mode and otherwise choose the next two-digit sequence.
|
||||
|
||||
- [ ] **Step 4: Implement and enforce checkpoint budgets**
|
||||
|
||||
```python
|
||||
def validate_checkpoint_budget(data: dict[str, Any]) -> None:
|
||||
limits = {"achievements": 5, "issues": 5, "next_steps": 3}
|
||||
for key, limit in limits.items():
|
||||
values = data.get(key, [])
|
||||
if not isinstance(values, list):
|
||||
raise ValueError(f"{key} must be a list")
|
||||
if len(values) > limit:
|
||||
raise ValueError(f"checkpoint allows at most {limit} {key}")
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Run the focused tests**
|
||||
|
||||
Run the same test command.
|
||||
|
||||
Expected: all path, classification, update, traversal, and budget tests pass.
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Define and validate the normalized fact source
|
||||
|
||||
**Files:**
|
||||
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py`
|
||||
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py`
|
||||
- Create: `C:\Users\admin\.codex\skills\daily-summary-job\references\report-schema.md`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `validate_report_data(data: dict) -> None`, `render_markdown(data: dict) -> str`, and a documented JSON schema shared by checkpoints, generation, and update mode.
|
||||
|
||||
- [ ] **Step 1: Add failing schema and Markdown tests**
|
||||
|
||||
The fixture must include one issue for each evidence level and assert stable issue identifiers appear in Markdown:
|
||||
|
||||
```python
|
||||
self.assertRaisesRegex(ValueError, "unsupported evidence level", target.validate_report_data, bad_data)
|
||||
markdown = target.render_markdown(self.sample_data())
|
||||
self.assertIn("## 3. 今日发现的问题", markdown)
|
||||
self.assertIn("issue-baseline", markdown)
|
||||
self.assertIn("待验证风险", markdown)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests and confirm the new API fails**
|
||||
|
||||
Expected: FAIL because validation and Markdown rendering are not implemented.
|
||||
|
||||
- [ ] **Step 3: Implement strict schema validation**
|
||||
|
||||
Require top-level fields `date`, `title`, `summary`, `modules`, `achievements`, `issues`, `validations`, `next_steps`, and `sources`. Require each issue to contain `id`, `title`, `module`, `evidence_level`, `discovery`, `actual`, `expected`, `cause`, `impact`, `improvements`, `validation`, `next_steps`, and `evidence`. Accept only these labels:
|
||||
|
||||
```python
|
||||
EVIDENCE_LEVELS = {"已验证", "静态分析", "对话发现", "待验证风险", "结论冲突"}
|
||||
```
|
||||
|
||||
Reject duplicate issue identifiers and non-list collection fields.
|
||||
|
||||
- [ ] **Step 4: Implement Markdown rendering from the validated data**
|
||||
|
||||
Render the approved seven main sections. Every issue heading includes its stable identifier and evidence level. Evidence is rendered as a compact table containing label, reference, and result; empty optional collections render as “无已记录项” rather than invented content.
|
||||
|
||||
- [ ] **Step 5: Document the exact schema and evidence rules**
|
||||
|
||||
`report-schema.md` must contain the complete JSON example, field table, five evidence labels, checkpoint budget, merge-by-issue-id rule, conflict behavior, and safe-language examples distinguishing verified facts from risks.
|
||||
|
||||
- [ ] **Step 6: Run the focused tests**
|
||||
|
||||
Expected: schema and Markdown tests pass.
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Build the self-contained interactive HTML renderer
|
||||
|
||||
**Files:**
|
||||
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py`
|
||||
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py`
|
||||
- Create: `C:\Users\admin\.codex\skills\daily-summary-job\assets\interactive-report-template.html`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `render_html(data: dict, template: str) -> str` and UI hooks `issue-button`, `evidence-filter`, `cause-node`, `solution-step`, `before-after-toggle`, `validation-gate`, and `roadmap-item`.
|
||||
|
||||
- [ ] **Step 1: Add failing HTML safety and interaction tests**
|
||||
|
||||
```python
|
||||
html = target.render_html(self.sample_data(), template_text)
|
||||
self.assertIn('id="daily-summary-app"', html)
|
||||
self.assertIn('class="issue-button"', html)
|
||||
self.assertIn('class="before-after-toggle"', html)
|
||||
self.assertIn('@media (prefers-reduced-motion: reduce)', html)
|
||||
self.assertNotRegex(html, r'https?://|<script[^>]+src=')
|
||||
self.assertNotIn("</script><script>alert", html)
|
||||
for issue in self.sample_data()["issues"]:
|
||||
self.assertIn(issue["id"], html)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests and confirm rendering fails**
|
||||
|
||||
Expected: FAIL because the template and renderer do not exist.
|
||||
|
||||
- [ ] **Step 3: Create the offline data-driven template**
|
||||
|
||||
The template must contain:
|
||||
|
||||
```html
|
||||
<main id="daily-summary-app" data-selected-issue="">
|
||||
<header class="hero">...</header>
|
||||
<nav class="filters" aria-label="筛选问题证据等级">...</nav>
|
||||
<section class="overview" aria-label="今日工作总览">...</section>
|
||||
<section class="problem-lab" aria-live="polite">...</section>
|
||||
<section class="validation-funnel">...</section>
|
||||
<section class="roadmap">...</section>
|
||||
</main>
|
||||
<script id="report-data" type="application/json">__REPORT_DATA__</script>
|
||||
<script>/* native rendering and keyboard navigation */</script>
|
||||
```
|
||||
|
||||
Use text and icons together for status; do not rely on color alone. Provide visible focus states, arrow-key issue navigation, responsive single-column fallbacks, and a no-animation media query. Display “概念示意” whenever a problem lacks numeric evidence.
|
||||
|
||||
- [ ] **Step 4: Implement safe JSON embedding and rendering**
|
||||
|
||||
```python
|
||||
def safe_json_for_html(data: dict[str, Any]) -> str:
|
||||
raw = json.dumps(data, ensure_ascii=False, separators=(",", ":"))
|
||||
return raw.replace("<", "\\u003c").replace(">", "\\u003e").replace("&", "\\u0026")
|
||||
|
||||
def render_html(data: dict[str, Any], template: str) -> str:
|
||||
validate_report_data(data)
|
||||
if template.count("__REPORT_DATA__") != 1:
|
||||
raise ValueError("template must contain exactly one report data placeholder")
|
||||
return template.replace("__REPORT_DATA__", safe_json_for_html(data))
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Run the focused tests**
|
||||
|
||||
Expected: HTML safety, interaction-hook, evidence-consistency, and accessibility-source tests pass.
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Add checkpoint, render, update, and validate CLI workflows
|
||||
|
||||
**Files:**
|
||||
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py`
|
||||
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces CLI subcommands `inspect`, `checkpoint`, `render`, and `validate`.
|
||||
- All successful commands emit compact JSON to stdout; failures return nonzero with a specific message on stderr.
|
||||
|
||||
- [ ] **Step 1: Add failing end-to-end CLI tests**
|
||||
|
||||
Use `tempfile.TemporaryDirectory` to verify:
|
||||
|
||||
1. `checkpoint` creates one compact JSON under `.daily-summary-job/YYYY-MM-DD/checkpoints`.
|
||||
2. `render` creates canonical state plus a Markdown/HTML pair under `<module>_rep/YYYY-MM-DD`.
|
||||
3. `render --update` preserves the original sequence and paths.
|
||||
4. A second topic receives the next sequence.
|
||||
5. `validate` rejects mismatched issue identifiers or an external URL in HTML.
|
||||
|
||||
- [ ] **Step 2: Run tests and confirm CLI failures**
|
||||
|
||||
Expected: FAIL because the subcommands are not wired.
|
||||
|
||||
- [ ] **Step 3: Implement the four subcommands**
|
||||
|
||||
- `inspect`: report project root, local date, changed paths, existing report modules, inferred module, and evidence file candidates without writing.
|
||||
- `checkpoint`: validate compact input, create the checkpoint directory, and write UTF-8 JSON atomically.
|
||||
- `render`: validate full input, plan or reuse paths, render both outputs to temporary siblings, validate them, atomically replace the pair, and persist canonical state.
|
||||
- `validate`: compare issue identifiers and evidence levels across canonical JSON, Markdown, and HTML; reject external resources.
|
||||
|
||||
Use `tempfile.NamedTemporaryFile(delete=False, dir=target.parent)` and `Path.replace` only after both staged files pass validation. Clean up staged files in `finally` without deleting existing deliverables.
|
||||
|
||||
- [ ] **Step 4: Run all script tests**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
python 'C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py' -v
|
||||
```
|
||||
|
||||
Expected: all tests pass.
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Write the concise skill workflow and metadata-aligned instructions
|
||||
|
||||
**Files:**
|
||||
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\SKILL.md`
|
||||
- Verify: `C:\Users\admin\.codex\skills\daily-summary-job\agents\openai.yaml`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `scripts/prepare_report.py`, `references/report-schema.md`, and `assets/interactive-report-template.html`.
|
||||
- Produces: A skill another Codex instance can invoke for record, generate, or update intents without loading unrelated history.
|
||||
|
||||
- [ ] **Step 1: Replace scaffold placeholders with final frontmatter**
|
||||
|
||||
Use only the required YAML keys:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: daily-summary-job
|
||||
description: Record compact development checkpoints and generate or update evidence-grounded daily work reports with paired Markdown and self-contained interactive HTML. Use when the user asks to record current development progress, summarize today's coding work, organize problems and improvements, visualize problem/solution reasoning, or update an existing daily development report.
|
||||
---
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Write the imperative workflow**
|
||||
|
||||
The body must tell the invoking agent to:
|
||||
|
||||
1. Determine record/generate/update intent without requiring fixed wording.
|
||||
2. Read only current context and today's relevant evidence.
|
||||
3. Run `inspect` before any write.
|
||||
4. Preserve evidence boundaries and conflicts.
|
||||
5. Create the normalized JSON using `report-schema.md`.
|
||||
6. Use `checkpoint` for compact progress capture.
|
||||
7. Use `render` for new reports and `render --update` for exact-topic updates.
|
||||
8. Run `validate` and report precise paths.
|
||||
9. Never fix business code, run Git commit, fabricate evidence, or read historical days by default.
|
||||
|
||||
- [ ] **Step 3: Verify interface metadata remains aligned**
|
||||
|
||||
`agents/openai.yaml` must show `Daily Summary Job`, the approved Chinese short description, and a default prompt explicitly containing `$daily-summary-job`. Do not add icons, colors, dependencies, or policy fields.
|
||||
|
||||
---
|
||||
|
||||
### Task 7: Validate the installed skill and run a disposable full workflow
|
||||
|
||||
**Files:**
|
||||
- Verify only: `C:\Users\admin\.codex\skills\daily-summary-job\**`
|
||||
- Create and remove only: a dedicated directory under the system temporary directory.
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: Validation evidence for skill structure, unit behavior, report generation, update stability, and offline HTML constraints.
|
||||
|
||||
- [ ] **Step 1: Run skill structure validation**
|
||||
|
||||
```powershell
|
||||
python 'C:\Users\admin\.codex\skills\.system\skill-creator\scripts\quick_validate.py' 'C:\Users\admin\.codex\skills\daily-summary-job'
|
||||
```
|
||||
|
||||
Expected: validation succeeds.
|
||||
|
||||
- [ ] **Step 2: Run the full script test suite**
|
||||
|
||||
```powershell
|
||||
python 'C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py' -v
|
||||
```
|
||||
|
||||
Expected: all tests pass.
|
||||
|
||||
- [ ] **Step 3: Create a disposable simulated project**
|
||||
|
||||
Create one explicit temporary project containing `src/Map`, `src/PathSmoothing`, and an existing `dailywork_report/pathsmoothing_rep`. Feed a checkpoint and a full report fixture containing achievements, two evidence levels, an improvement, validation results, and next steps.
|
||||
|
||||
- [ ] **Step 4: Run record, generate, update, and validation commands**
|
||||
|
||||
Expected:
|
||||
|
||||
- checkpoint path is date-scoped;
|
||||
- multi-module input selects `cross-module_rep` unless explicitly overridden;
|
||||
- generation creates one paired report;
|
||||
- update keeps the same pair;
|
||||
- every issue identifier appears in normalized JSON, Markdown, and HTML;
|
||||
- HTML contains no `http://`, `https://`, external script, or external image reference.
|
||||
|
||||
- [ ] **Step 5: Inspect the final installed file set and repository scope**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
Get-ChildItem -LiteralPath 'C:\Users\admin\.codex\skills\daily-summary-job' -Recurse -File | Select-Object FullName,Length
|
||||
git status --short -- 'docs/superpowers/specs/2026-08-03-daily-summary-job-skill-design.md' 'docs/superpowers/plans/2026-08-03-daily-summary-job-skill.md'
|
||||
```
|
||||
|
||||
Expected: only the new skill files exist in the personal directory; the repository shows the two uncommitted documentation files and no task-caused business-code changes.
|
||||
|
||||
## Execution Choice
|
||||
|
||||
The user requested immediate execution without Git commits. Execute this plan inline with `superpowers:executing-plans`; do not dispatch subagents and do not pause for a separate execution-choice prompt.
|
||||
Reference in New Issue
Block a user