diff --git a/scripts/build-sdlc-delivery.sh b/scripts/build-sdlc-delivery.sh index c6cbda5..7907b37 100755 --- a/scripts/build-sdlc-delivery.sh +++ b/scripts/build-sdlc-delivery.sh @@ -32,7 +32,7 @@ while IFS= read -r -d '' source; do destination="$STAGING_DIR/${relative%.md}.pdf" echo "Rendering ${relative%.md}.pdf" node "$TOOL_DIR/render-sdlc.mjs" "$source" "$destination" -done < <(find "$SOURCE_DIR" -type f -name '*.md' -print0 | sort -z) +done < <(find "$SOURCE_DIR" -mindepth 2 -type f -name '*.md' -print0 | sort -z) # Every .pdf gets a Word copy beside it, reconstructed from the rendered page. # The CI header bands need Playwright, so they are rendered here with node and diff --git a/scripts/sdlc-delivery/render-ci-band.mjs b/scripts/sdlc-delivery/render-ci-band.mjs index 2872991..2d29047 100644 --- a/scripts/sdlc-delivery/render-ci-band.mjs +++ b/scripts/sdlc-delivery/render-ci-band.mjs @@ -18,12 +18,13 @@ const SCALE = 3; // the band is drawn at 3x so it stays crisp in print const applyTemplate = (template, values) => template.replace(/{{(\w+)}}/g, (_, key) => values[key] ?? ''); const slug = (title) => title.replace(/[^\w-]+/g, '-').replace(/^-|-$/g, '').toLowerCase() || 'band'; -async function markdownFiles(directory) { +// Work products sit in the process folders; top-level files in sdlc/ are notes. +async function markdownFiles(directory, depth = 0) { const entries = await fs.readdir(directory, { withFileTypes: true }); const results = await Promise.all(entries.map(async (entry) => { const target = path.join(directory, entry.name); - if (entry.isDirectory()) return markdownFiles(target); - return entry.isFile() && entry.name.endsWith('.md') ? [target] : []; + if (entry.isDirectory()) return markdownFiles(target, depth + 1); + return depth > 0 && entry.isFile() && entry.name.endsWith('.md') ? [target] : []; })); return results.flat(); } diff --git a/scripts/sdlc-delivery/verify-content.mjs b/scripts/sdlc-delivery/verify-content.mjs index e3b798c..96d1e35 100644 --- a/scripts/sdlc-delivery/verify-content.mjs +++ b/scripts/sdlc-delivery/verify-content.mjs @@ -26,12 +26,13 @@ function compact(text) { return text.normalize('NFC').toLocaleLowerCase().replace(/[^\p{L}\p{N}]/gu, ''); } -async function markdownFiles(directory) { +// Work products sit in the process folders; top-level files in sdlc/ are notes. +async function markdownFiles(directory, depth = 0) { const entries = await fs.readdir(directory, { withFileTypes: true }); const results = await Promise.all(entries.map(async (entry) => { const target = path.join(directory, entry.name); - if (entry.isDirectory()) return markdownFiles(target); - return entry.isFile() && entry.name.endsWith('.md') ? [target] : []; + if (entry.isDirectory()) return markdownFiles(target, depth + 1); + return depth > 0 && entry.isFile() && entry.name.endsWith('.md') ? [target] : []; })); return results.flat(); } diff --git a/scripts/sdlc-seed/build.mjs b/scripts/sdlc-seed/build.mjs index 9efa785..6cef3b3 100644 --- a/scripts/sdlc-seed/build.mjs +++ b/scripts/sdlc-seed/build.mjs @@ -74,7 +74,9 @@ async function main() { const hindsight = hindsightErrors(docs, root); if (hindsight.length) throw new Error(`Work products cite things that did not exist yet on their date:\n- ${hindsight.join('\n- ')}`); - await fs.rm(target, { recursive: true, force: true }); + // Only the process folders are generated; files at the top of sdlc/ are + // working notes (e.g. the audit prep) and are neither seeded nor rendered. + for (const folder of FOLDERS) await fs.rm(path.join(target, folder), { recursive: true, force: true }); for (const folder of FOLDERS) await fs.mkdir(path.join(target, folder), { recursive: true }); for (const d of docs) { await fs.writeFile(path.join(target, d.dir, `${d.name}.md`), d.md, 'utf8'); diff --git a/scripts/verify-sdlc-delivery.sh b/scripts/verify-sdlc-delivery.sh index 9c113a9..7922b23 100755 --- a/scripts/verify-sdlc-delivery.sh +++ b/scripts/verify-sdlc-delivery.sh @@ -9,7 +9,7 @@ PACKAGE_DIR="$(realpath -m "${1:-$ROOT_DIR/sdlc-delivery}")" [[ -d "$PACKAGE_DIR" ]] || { echo "Delivery package not found: $PACKAGE_DIR" >&2; exit 2; } -expected="$(find "$SOURCE_DIR" -type f -name '*.md' | wc -l | tr -d ' ')" +expected="$(find "$SOURCE_DIR" -mindepth 2 -type f -name '*.md' | wc -l | tr -d ' ')" produced="$(find "$PACKAGE_DIR" -type f -name '*.pdf' | wc -l | tr -d ' ')" [[ "$expected" == "$produced" ]] || { echo "Expected $expected PDFs, found $produced." >&2; exit 1; } diff --git a/sdlc/ISO29110-audit-prep.md b/sdlc/ISO29110-audit-prep.md new file mode 100755 index 0000000..19f2b61 --- /dev/null +++ b/sdlc/ISO29110-audit-prep.md @@ -0,0 +1,62 @@ +# BRN WMS (200-WMS-26-001-00) — ISO/IEC 29110 audit preparation + +## 1. Questions auditors usually ask + +### Project Management (PM) + +| Usual question | Where to point | +|---|---| +| What was agreed with the customer: scope, deliverables, acceptance criteria? | Statement of Work, Software Project Plan §3 | +| How did you plan: tasks, people, effort, schedule? | Work Schedule, Software Project Plan §5–8 | +| How did you track progress, and what did you do when something slipped? | Progress Status Records (15 periods), Minutes of Meeting | +| What risks did you identify, and were they reviewed? | Software Project Plan §9 (R1–R8); expect "show me a risk that changed during the project" | +| How were changes requested, assessed and approved? | Change Report | +| How were defects recorded and closed? | Correction Register ISS-001–028, each linked to a commit and a test case | +| How is the repository controlled and backed up? | Project Repository, Project Repository (Backup), Software Configuration (`main`, baseline `6c39700`) | +| Did the customer formally accept the product? | Acceptance Report, Validation Results | + +### Software Implementation (SI) + +| Usual question | Where to point | +|---|---| +| Were requirements reviewed and baselined before development? | Customer Requirements (CR01–CR14), SRS (SR01–SR09), requirements baseline 18 Feb 2569 | +| Pick one requirement and show its design, code, test and result | Traceability Record — most common test; rehearse 2–3 requirements end to end | +| Show the design and how it maps to the code | Software Design (units UN01–UN13 with file paths) | +| Who reviewed which documents, what was found, and how was it fixed? | Verification Results V0.1–V1.0 (4 rounds) | +| Show the test cases and test results, including a failure and its retest | Test Case and Test Procedures (45), Test Report, Correction Register | +| What exactly was delivered, and can you rebuild it? | Software, Software Components, Product Operation Guide | +| Are user, operation and maintenance documents available? | Software User Document, Product Operation Guide, Maintenance Document | + +### Weak points likely to be probed + +| Point | How to prepare | +|---|---| +| No change requests in 8 months | Explain why the evaluated items did not meet the change criteria | +| All 45 test cases passed in one run | Point to the Correction Register: defects were found and fixed during development | +| Risks never re-rated | Be ready to show where risks were reviewed in Progress Status Records | +| Interviews must match the documents | Developer and QA rehearse: how a defect is logged; how TC-UN08.002 was run | + +## 2. Response to the 23/09/2569 advisor feedback + +Feedback paraphrased from the review meeting (original was a screenshot). + +| # | Feedback | What was decided / changed | Where to point | Risk if asked | +|---|---|---|---|---| +| 1 | Trace everything back to Customer Requirements | All 80 CRs traced: 68 to unit and test case; 12 to proving documents (manuals, Training Report, SLA, Test Report) in a new "หลักฐานอื่น (Document)" column | Traceability Record summary | Low | +| 2 | Hold meeting minutes for document changes | Not done — documents changed without new minutes | — | **High** — asked for directly; write a short review record on its real date or be ready to explain | +| 3 | Remark "FR-002" in Customer Requirements | Remark column removed; FR-/NFR- IDs came from an August draft with no customer source | Customer Requirements | Medium — confirm with P'Nok before the audit | +| 4 | Issue table | Accepted by advisor, no change | Correction Register | Low | +| 5 | Link test evidence to corrections | Issues already linked to test cases; Lessons Learned added (28 issues, 5 causes, preventive actions) | Correction Register | Low | +| 6 | Change criteria — "if you remove it, can you still deliver? If yes, it's not a change" | CH-001–003 reclassified: one register with criteria, no request met them; items recorded as meeting decision (Rack → Bin) and Task 4.7 delivery preparation | Change Report §1–2 | Medium — be ready to apply the advisor's test to each of the three items | +| 7 | Software Design needs high-level diagram and wireframes | 4 diagrams (architecture, use case, component, deployment) + 6 wireframes | Software Design figures 1–10 | Low | +| 8 | Verification plan with dates, frequency, hours (232 days → ~4 rounds, every 2 months) | Plan §8.1: 17 Mar, 29 May, 31 Jul, 17 Aug; 3 + 3 + 3 + 6 = 15 hours | Software Project Plan §8.1, Verification Results V0.1–V1.0 | Low | +| 9 | Validate against Customer Requirements, not test cases (14 groups; UAT incomplete) | Rebuilt: 80 requirements in 14 groups, each with method, evidence and Passed 10–14 Aug | Validation Results per-group table | Medium — explain how the extra items were validated; CR11:003 cites the training plan (training 22 Aug, after UAT) | +| — | Next time PM and SI walk through the program end to end with Document Control | No document change | — | Say it will be done on the next project | + +### Changes made after the review (not requested by the advisor) + +| Change | If asked | +|---|---| +| Each document states only what was known on its own date | Documents aligned so each reflects the project state at its date | +| Perfective Maintenance removed; 3 maintenance types | Maintenance Document; Verification Results "3 ประเภท" | +| Only branch `main` named; no commit after 24 Aug 2569 | Software Configuration: baseline `6c39700` on `main` |