docs(sdlc): add ISO 29110 audit prep note; keep top-level sdlc notes out of seed and render
This commit is contained in:
@@ -32,7 +32,7 @@ while IFS= read -r -d '' source; do
|
|||||||
destination="$STAGING_DIR/${relative%.md}.pdf"
|
destination="$STAGING_DIR/${relative%.md}.pdf"
|
||||||
echo "Rendering ${relative%.md}.pdf"
|
echo "Rendering ${relative%.md}.pdf"
|
||||||
node "$TOOL_DIR/render-sdlc.mjs" "$source" "$destination"
|
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.
|
# 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
|
# The CI header bands need Playwright, so they are rendered here with node and
|
||||||
|
|||||||
@@ -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 applyTemplate = (template, values) => template.replace(/{{(\w+)}}/g, (_, key) => values[key] ?? '');
|
||||||
const slug = (title) => title.replace(/[^\w-]+/g, '-').replace(/^-|-$/g, '').toLowerCase() || 'band';
|
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 entries = await fs.readdir(directory, { withFileTypes: true });
|
||||||
const results = await Promise.all(entries.map(async (entry) => {
|
const results = await Promise.all(entries.map(async (entry) => {
|
||||||
const target = path.join(directory, entry.name);
|
const target = path.join(directory, entry.name);
|
||||||
if (entry.isDirectory()) return markdownFiles(target);
|
if (entry.isDirectory()) return markdownFiles(target, depth + 1);
|
||||||
return entry.isFile() && entry.name.endsWith('.md') ? [target] : [];
|
return depth > 0 && entry.isFile() && entry.name.endsWith('.md') ? [target] : [];
|
||||||
}));
|
}));
|
||||||
return results.flat();
|
return results.flat();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ function compact(text) {
|
|||||||
return text.normalize('NFC').toLocaleLowerCase().replace(/[^\p{L}\p{N}]/gu, '');
|
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 entries = await fs.readdir(directory, { withFileTypes: true });
|
||||||
const results = await Promise.all(entries.map(async (entry) => {
|
const results = await Promise.all(entries.map(async (entry) => {
|
||||||
const target = path.join(directory, entry.name);
|
const target = path.join(directory, entry.name);
|
||||||
if (entry.isDirectory()) return markdownFiles(target);
|
if (entry.isDirectory()) return markdownFiles(target, depth + 1);
|
||||||
return entry.isFile() && entry.name.endsWith('.md') ? [target] : [];
|
return depth > 0 && entry.isFile() && entry.name.endsWith('.md') ? [target] : [];
|
||||||
}));
|
}));
|
||||||
return results.flat();
|
return results.flat();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,9 @@ async function main() {
|
|||||||
const hindsight = hindsightErrors(docs, root);
|
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- ')}`);
|
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 folder of FOLDERS) await fs.mkdir(path.join(target, folder), { recursive: true });
|
||||||
for (const d of docs) {
|
for (const d of docs) {
|
||||||
await fs.writeFile(path.join(target, d.dir, `${d.name}.md`), d.md, 'utf8');
|
await fs.writeFile(path.join(target, d.dir, `${d.name}.md`), d.md, 'utf8');
|
||||||
|
|||||||
@@ -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; }
|
[[ -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 ' ')"
|
produced="$(find "$PACKAGE_DIR" -type f -name '*.pdf' | wc -l | tr -d ' ')"
|
||||||
[[ "$expected" == "$produced" ]] || { echo "Expected $expected PDFs, found $produced." >&2; exit 1; }
|
[[ "$expected" == "$produced" ]] || { echo "Expected $expected PDFs, found $produced." >&2; exit 1; }
|
||||||
|
|
||||||
|
|||||||
Executable
+62
@@ -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` |
|
||||||
Reference in New Issue
Block a user