Commit 9d759819 authored by Vacaliuc, Bogdan's avatar Vacaliuc, Bogdan
Browse files

initial load with borrow from the instrument-motion-investigations branch

parent 75ba94ae
Loading
Loading
Loading
Loading

CLAUDE.md

0 → 100644
+57 −0
Original line number Diff line number Diff line
# genesis-proposal-work

This project contains correspondence, screenshots, template documents and documents developed during the course
of preparing documents for research grant proposals.
You may read any and all files that are in this folder and which are provided in the /media/ssd2/Projects/Radiasoft/**.
You may use the internet freely to research profile and documentation.

## Capabilites and Role

You are a scientifc writing specialist who is expert at English, US Government proposal and procurement requirements and have a deep understanding of document creation and editing.
You are able to direct agent teams who are expert statisticians, data miners and administration support. You have a unique interest in the Python programming language and have become adept and using it to solve automation problems.

## General configuration, log and code references

Your prompts will indicate any specific files you should use. Generally, these will come into these paths:

* /media/ssd2/Projects/Radiasoft: files and folders in support of the Genesis Radiasoft-led proposal

## Secure Temporary Files

When a task requires writing a temporary script or data file (e.g. to work around
shell quoting limits when calling an API), **never write it to a world-readable
path**.  `/tmp` on a multi-user Linux system is mode 1777 — files created there
with default umask are readable by every local user.

**Always create temporary files with mode 600 (owner read/write only):**

```python
import os, tempfile

# Preferred: tempfile.NamedTemporaryFile — mode 600 by default
with tempfile.NamedTemporaryFile('w', suffix='.py', delete=False) as fh:
    fh.write(script_content)
    tmp_path = fh.name
try:
    # use tmp_path ...
finally:
    os.unlink(tmp_path)   # always clean up
```

Or with the Write tool followed by an immediate chmod:

```bash
# After writing the file, restrict permissions immediately
chmod 600 /path/to/tempfile
```

**Additional rules:**
- Never embed credentials (tokens, passwords, keys) in files under `plan/`,
  `tests/`, or any other committed path.  Use environment variables or
  `~/.netrc` / `~/.config` files (also mode 600) instead.
- Delete temporary files as soon as they are no longer needed — use a
  `try/finally` block or the `delete=True` default of `NamedTemporaryFile`.
- If a script must be written to `/tmp` via the Write tool (which cannot set
  permissions atomically), run `chmod 600 <path>` in the very next Bash call
  before the file is used.

pdf-tools/.gitignore

0 → 100644
+4 −0
Original line number Diff line number Diff line
.venv/
__pycache__/
*.pyc
*.debug.html
+1 −0
Original line number Diff line number Diff line
3.13

pdf-tools/README.md

0 → 100644
+125 −0
Original line number Diff line number Diff line
# pdf-tools — render investigation reports to print-quality PDF

Markdown → PDF pipeline tuned for BL4A/BL4B motion-control failure-analysis
reports like `tasking/DANGLE-Motion-Failure-Analysis.md`. Built on
WeasyPrint with a print-oriented CSS stylesheet and light HTML
post-processing.

Produces distinct **title page + table of contents + body + appendices +
bottom line** with:

- Title block with a metadata key/value grid parsed from the
  `**Label:** value` lines immediately after the H1
- Table of contents with dotted leaders and live page numbers via CSS
  `leader(dotted)` + `target-counter(attr(href url), page)`
- Running page header (document title on left, "${BL} — Motion Control"
  on right) and `Page X of Y` footer
- Executive Summary callout box (amber)
- Bottom line callout box (green) on its own page
- Appendix H2s styled with a tinted purple band
- Each appendix starts on its own page for clean back-matter separation
- Forced page breaks before Recommended Fixes, Open Questions, and each
  Appendix
- Code blocks that wrap long lines rather than clipping at the right
  margin (7.25 pt monospace)
- DejaVu Sans / DejaVu Sans Mono typography

## Quick start

```bash
cd tasking/pdf-tools
uv sync                             # one-time: install weasyprint, markdown2
uv run python md2pdf.py ../DANGLE-Motion-Failure-Analysis.md ../DANGLE-Motion-Failure-Analysis.pdf
```

The resulting PDF is ~15 pages for a ~30 KB markdown file, ~110 KB on
disk (vs ~400 KB for the same document rendered via Chromium headless
print).

## Options

- `MD2PDF_DEBUG=1` — also write `<output>.debug.html` alongside the PDF
  so you can inspect the intermediate HTML or tweak the CSS
  interactively.

## What the tool expects in the source markdown

The front-matter parser expects the document to start with an H1 title
followed by one or more `**Label:** value` lines, then a `---`
separator, then the body:

```markdown
# Report Title

**Date:** 2026-04-11
**Prepared by:** Somebody
**Instrument:** ${BL}

---

## First Section
...
```

If the metadata block is absent or formatted differently, the title
block will still render but the metadata grid will be empty.

## Section-level styling hooks

The tool adds CSS classes to certain H2s based on their text:

- `Appendix <letter>` — gets `class="appendix-heading"` (purple band,
  `break-before: page`)
- `Executive Summary` — the following content up to the next H2 is
  wrapped in `<section class="callout callout-summary">` (amber)
- `Bottom line` — same treatment with `callout-bottom` (green,
  `break-before: page`)
- `Recommended Fixes`, `Open Questions Still Unresolved`, `Appendix A`,
  `Bottom line` — get `class="new-page"` so they force a page break

## Implementation notes

- **Why markdown2 and not python-markdown?** markdown2 is a
  single-import pure-Python converter with all the extras we need
  (`tables`, `fenced-code-blocks`, `header-ids`, `cuddled-lists`,
  `strike`). python-markdown would also work but needs a plugin
  ecosystem for the same features.
- **Why WeasyPrint?** It supports the `leader()` CSS function and
  `target-counter(attr(href url), page)` which are essential for a
  proper table-of-contents with page numbers. Chromium headless does
  not implement `leader()`, and its `@page` support is limited.
- **Why 7.25 pt code blocks?** At 8 pt, the longest code lines in the
  DANGLE analysis (~130 characters, including the substitutions-file
  dumps and the Appendix A parameter history table) overflow the page
  content width. 7.25 pt + `white-space: pre-wrap` preserves all
  content and wraps only the lines that would otherwise clip.
- **ASCII-art trade-off.** With `white-space: pre-wrap`, an ASCII-art
  table whose lines are narrower than the page prints perfectly, but a
  line wider than the page wraps at a word boundary, which misaligns
  the columns on the wrapped portion. This is a preservation-vs-
  fidelity trade-off; the alternative (`pre` without wrap) would
  silently clip content. If a future report needs perfect ASCII
  preservation for a wide table, convert it to a proper HTML/markdown
  table in the source.

## Files

| File | Purpose |
|---|---|
| `md2pdf.py` | The tool. All logic and CSS embedded in one file. |
| `pyproject.toml` | uv project metadata + dependencies |
| `uv.lock` | Pinned dependency versions |
| `.gitignore` | Excludes `.venv/`, `__pycache__/`, `*.debug.html` |

## Not yet covered

- No syntax highlighting (Pygments is not wired in). All code blocks
  render with a single flat color. Adding highlighting would require
  switching to python-markdown with the `codehilite` extension, or
  invoking Pygments manually before the HTML is built.
- No automatic section numbering (e.g., "1.0", "1.1"). Easy to add via
  CSS counters if requested.
- Wide HTML tables that overflow the page are not specially handled.
  Currently they fit the DANGLE report, but a wider table would clip
  on the right. The fix when needed is landscape-orientation pages via
  a named `@page` rule and a CSS class on the table.

pdf-tools/main.py

0 → 100644
+6 −0
Original line number Diff line number Diff line
def main():
    print("Hello from pdf-tools!")


if __name__ == "__main__":
    main()
Loading