26 KiB
phase, verified, status, score, covered_files, covered_digest, covered_files_note, behavior_unverified, overrides_applied, decision_coverage, deferred, human_verification
| phase | verified | status | score | covered_files | covered_digest | covered_files_note | behavior_unverified | overrides_applied | decision_coverage | deferred | human_verification | |||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 15-journal-plugin | 2026-10-06T17:29:31Z | human_needed | 22/22 must-haves verified |
|
v2:sha256:dffb5e2bb692df38cfc2be6a36f6e3305b4d7d81304c9c6fa15bf86362f2aa80 | verification.fingerprint covers only paths under the summercms.go root. Sibling implementation read this pass: sm-journal-plugin d09edde (plugin.go, models, seven gormigrate steps, YAML admin, FormatHTML, /_journal/api/v1, commands, tests); sm-grzybyfunkcjonalne-app ff20e6c (summer.yaml, plugins.gen.go, go.work, gitlinks, boot_test.go, config/http.yaml). Host journal gitlink is d09edde. PHP pin /media/nvme/dev/golem15/fonoteka/plugins/golem15/journal HEAD 02110eb1c0c3861370b0b9b47b209a0702ac5d88, clean tree, not edited. | 0 | 0 |
|
|
|
Phase 15: Journal plugin Verification Report
Phase Goal: The Golem15 Journal plugin is ported to Go as sm-journal-plugin and mounts in a host application the same way sm-user-plugin does, so a blog can run on SummerCMS without the PHP plugin.
Verified: 2026-10-06T17:29:31Z
Status: human_needed
Re-verification: No — initial verification
MVP note: ROADMAP marks this phase mode: mvp but the ROADMAP goal is not in user-story form (user-story.validate → valid: false). PLAN.md goals are valid user stories. This report uses the PLAN story for User Flow Coverage and does not refuse verification.
User story (from plans): As an application developer, I want to mount sm-journal-plugin in a host the same way sm-user-plugin mounts, so that a blog can run on SummerCMS without the PHP plugin.
User Flow Coverage
| Step | Expected | Evidence | Status |
|---|---|---|---|
| Mount | Host lists journal beside user and translate as git submodules | sm-grzybyfunkcjonalne-app/.gitmodules, git ls-files -s mode 160000 for plugins/golem15/{user,translate,journal}; journal gitlink d09edde; summer.yaml + plugins.gen.go blank-import sm-journal-plugin |
✓ |
| Boot | Host Activate returns the three plugin IDs and assembles Journal routes | boot_test.go:TestBootUserTranslateJournal required by check-phase15.sh --host (PASS this pass) |
✓ |
| Public content | Anonymous GET lists published posts; categories/tags/rss exist | TestJournalPublicList, TestJournalPublicCategories, TestJournalPublicTags, TestJournalRSS in plugin suite (PASS this pass) |
✓ |
| Outcome | A blog can run on SummerCMS without the PHP plugin | Plugin module git.golem15.com/golem15/sm-journal-plugin, PHP pin clean at 02110eb1, --php PASS; PHP components journalPost documented as Phase 16 successor in plugin README |
✓ |
Goal Achievement
Observable Truths
| # | Truth | Status | Evidence |
|---|---|---|---|
| 1 | SC-1: Journal plugin repo exists with models, migrations and YAML admin screens, permission-gated | ✓ VERIFIED | sm-journal-plugin HEAD d09edde; models Post/Category/Tag/Settings; seven gormigrate IDs; controllers golem15.journal.posts|categories|tags; TestPostsFormCompiles (mlmarkdown/mltext); TestPostsAdminForbidden 403 without access_posts |
| 2 | SC-2: A host can mount the plugin as a submodule and serve public posts/categories/PHP-equivalent routes | ✓ VERIFIED | Host gitlink + TestBootUserTranslateJournal asserts GET/POST /_journal/api/v1/posts; routes.go public group; TestJournalPublicList PASS |
| 3 | SC-3: Plugin README stays application-neutral | ✓ VERIFIED | README uses the application, acme, blog; --forbidden greps README for fonoteka/płytarium/grzybyfunkcjonalne (PASS) |
| 4 | SC-4: Unit tests in the phase's last plan | ✓ VERIFIED | 15-04 added fillable/translatable/FormatHTML/migrations/API/search/integration tests; check-phase15.sh --plugin ran go test ./... and -race (PASS this pass) |
| 5 | D-01/D-02/D-03/D-07: Schema/models from PHP SHA 02110eb1; PHP tree unmodified |
✓ VERIFIED | check-phase15.sh --php: HEAD 02110eb1c0c3861370b0b9b47b209a0702ac5d88, porcelain empty |
| 6 | D-04: gormigrate creates golem15_journal_* tables, pivots, settings singleton, backend_users.golem15_bloghub_author_slug; rollback remigrates |
✓ VERIFIED | updates/202610060001–007; TestJournalTables; TestJournalMigrationsRollbackAndRemigrate in PLUGIN_REQUIRE (PASS) |
| 7 | D-05: RESEARCH §8 PHPUnit rows have named Go tests | ✓ VERIFIED | JOURNAL-001/002 TestFillable; JOURNAL-005 TestJournal005DraftShow; JOURNAL-006 TestJournal006MediaUpload; JOURNAL-003/004 substitute TestFormatHTMLRejectsUnsafeHTML; redactor_id TestFillable + TestJournalAPIMassAssignRedactor |
| 8 | D-06: HasLang catalogs exist for en and pl only | ✓ VERIFIED | lang/en/lang.yaml, lang/pl/lang.yaml only; plugin.go HasLang + //go:embed lang |
| 9 | D-08: Admin nav SVG is embedded | ✓ VERIFIED | assets/images/journal-icon.svg byte-identical to PHP; TestJournalSVGEmbed opens it from AdminFS; NavigationItem has no IconSvg (framework), so nav uses lucide pencil per RESEARCH |
| 10 | D-09/D-10: ID golem15.journal, Requires exactly golem15.translate, Post/Category Translatable/MorphName PHP strings, mltext/mlmarkdown |
✓ VERIFIED | plugin.go Requires() []string{"golem15.translate"}; TestPostTranslatableSmoke; TestTranslatable; models/post/fields.yaml mltext/mlmarkdown |
| 11 | D-11: post content YAML type is mlmarkdown; cabana markdown types not re-added this phase |
✓ VERIFIED | TestPostsFormCompiles; TestCabanaMarkdownFieldTypes; git diff -- modules/cabana/field_markdown.go empty; --forbidden refuses a dirty field_markdown.go |
| 12 | D-12: search_use_typesense defaults false; unpublished/gate-off not searchable; fresh save makes zero Typesense HTTP |
✓ VERIFIED | DDL DEFAULT FALSE; TestSearchGateOff must not skip (gate detector refuses skip); zero httptest hits this pass |
| 13 | D-13: journal:export-posts / journal:import-posts registered; Posts toolbar requires golem15.journal.access_import_export |
✓ VERIFIED | TestJournalCommands PASS; commands write JSON-per-slug files matching PHP ExportPosts/ImportPosts (not a Winter CSV framework — RESEARCH) |
| 14 | FormatHTML regenerates content_html on admin/API save with goldmark footnote/table/attribute + rejectUnsafe; cabana.RenderMarkdown not edited |
✓ VERIFIED | controllers/posts.go preparePostWrite; API posts_helpers.go; import path; TestFormatHTMLRejectsUnsafeHTML; TestPostsAdminCreateSmoke stores HTML |
| 15 | Without access_other_posts, list/form queries restrict to user_id; publish without access_publish is ForbiddenError |
✓ VERIFIED | restrictToOwnPosts in controllers/posts.go; TestPostsAdminCreateSmoke/publish_without_access_publish 403; JOURNAL-005 owner vs stranger vs access_other_posts |
| 16 | D-14: anonymous GET /_journal/api/v1/posts, posts/{slug}, categories, tags, rss; show is slug; per_page default 9 max 30 |
✓ VERIFIED | routes.go; TestJournalPublicList (per_page 9, drafts omitted); TestJournalPerPageClamp; TestClampPerPage; categories/tags/RSS named tests PASS |
| 17 | D-15: writes require cabana backend JWT (aud=backend); missing Bearer is JSON {error:Authentication required}; frontend audience rejected |
✓ VERIFIED | requireBackendPrincipal; TestJournalWriteUnauthenticated; TestJournalWriteFrontendAudience; TestJournalFeaturedImageUnauthenticated |
| 18 | D-16: Journal is not added to the Płytarium tide 154-route harness | ✓ VERIFIED | TestNoTideJournalFixtures; --forbidden greps fonoteka.go parity/tide and modules/tide for /_journal/api/v1 (no hits) |
| 19 | D-17: buckets journal-public-api and journal-api Max 120; host CORS _journal/api/*; supports_credentials false |
✓ VERIFIED | TestJournalBuckets; TestCORS; config/http.yaml; 429 body remains surf "Too Many Attempts." (no Journal 429 writer) |
| 20 | D-18–D-23: proof host is sm-grzybyfunkcjonalne-app at the sibling path; three submodules; plugin module/ID/path |
✓ VERIFIED | --layout PASS; host not fonoteka.go / sm-summercmsio-app / in-module testhost; go.mod module git.golem15.com/golem15/sm-journal-plugin; origin URLs match D-18/D-22 |
| 21 | JOURNAL-005: unpublished or future published_at show is 404 with no data unless owner or access_other_posts |
✓ VERIFIED | Show in controllers/api/posts.go; TestJournal005DraftShow; TestJournalEndToEnd anonymous/stranger 404, owner/priv 200 |
| 22 | scripts/check-phase15.sh --all is fail-closed; 15-SECURITY-REVIEW.md closes every high T-15-* threat |
✓ VERIFIED | --self-test detector (fail/skip/zero/no-tests/race/missing-named); this pass executed every --all stage (self-test, php, layout, plugin, host, forbidden, security) — all PASS; review marks T-15-01..15 and T-15-SC mitigate |
Score: 22/22 truths verified (0 present, behavior-unverified)
Deferred Items
Items not yet met but explicitly addressed in later milestone phases.
| # | Item | Addressed In | Evidence |
|---|---|---|---|
| 1 | API-09 (154 Płytarium routes) stale map onto Phase 15 | Phase 20 | Phase 20 cutover goal; plans forbid claiming API-09; D-16 |
| 2 | QA-05 (cutover harness + Nuxt/MCP unchanged) stale map onto Phase 15 | Phase 20 | Phase 20 definition of done |
| 3 | Winter theme components journalPost / journalPosts / live site HTML |
Phase 16 | CONTEXT deferred; plugin README names them as a later successor |
Required Artifacts
| Artifact | Expected | Status | Details |
|---|---|---|---|
../sm-journal-plugin/plugin.go |
compiled plugin, Requires translate, migrations/models | ✓ VERIFIED | ID golem15.journal; HasMigrations/Models/Lang/Commands/Routes; BucketProvider |
../sm-journal-plugin/updates/202610060001_create_golem15_journal_posts.go |
squashed posts DDL | ✓ VERIFIED | golem15_journal_posts; Rollback DROP |
../sm-journal-plugin/models/post.go |
TableName, MorphName, Translatable | ✓ VERIFIED | PHP class string Golem15\Journal\Models\Post |
../sm-grzybyfunkcjonalne-app/summer.yaml |
three compiled plugins including journal | ✓ VERIFIED | user, translate, journal |
../sm-grzybyfunkcjonalne-app/boot_test.go |
three-plugin boot | ✓ VERIFIED | TestBootUserTranslateJournal |
../sm-grzybyfunkcjonalne-app/config/http.yaml |
CORS _journal/api/* |
✓ VERIFIED | path present; supports_credentials: false |
../sm-journal-plugin/controllers/posts.go |
YAML controller, ListExtendQuery, FormatHTML | ✓ VERIFIED | access_posts; preparePostWrite |
../sm-journal-plugin/models/post/fields.yaml |
mlmarkdown content | ✓ VERIFIED | type: mlmarkdown |
../sm-journal-plugin/assets/images/journal-icon.svg |
embedded nav SVG | ✓ VERIFIED | bytes match PHP; go:embed in AdminFS |
../sm-journal-plugin/classes/format_html.go |
func FormatHTML |
✓ VERIFIED | goldmark + rejectUnsafe |
../sm-journal-plugin/console/export_posts.go |
journal:export-posts |
✓ VERIFIED | command name registered |
../sm-journal-plugin/models/settings/fields.yaml |
settings code journal | ✓ VERIFIED | search_use_typesense |
../sm-journal-plugin/routes.go |
/_journal/api/v1 |
✓ VERIFIED | public GET + write groups |
../sm-journal-plugin/controllers/api/posts.go |
PHP {error} string JSON, slug show, draft 404 |
✓ VERIFIED | Authentication required; no data on draft 404 |
../sm-journal-plugin/controllers/api/media.go |
JOURNAL-006 media upload | ✓ VERIFIED | media/upload; journal/ prefix |
../sm-journal-plugin/search.go |
beachcomber Gate | ✓ VERIFIED | reads ID=1 search_use_typesense; errors count as off |
../sm-journal-plugin/integration_test.go |
end-to-end | ✓ VERIFIED | TestJournalEndToEnd in package journal_test |
../sm-journal-plugin/models/fillable_test.go |
JOURNAL-001/002 | ✓ VERIFIED | TestFillable |
../sm-journal-plugin/controllers/api/posts_test.go |
clampPerPage unit | ✓ VERIFIED | HTTP JOURNAL-005 lives at plugin-root journal_api_writes_test.go (dispatch-authorized) |
scripts/check-phase15.sh |
fail-closed phase gate | ✓ VERIFIED | all stages PASS this pass |
.planning/phases/15-journal-plugin/15-SECURITY-REVIEW.md |
ASVS L1 | ✓ VERIFIED | T-15-01 present; --security PASS |
Key Link Verification
| From | To | Via | Status | Details |
|---|---|---|---|---|
plugin.go |
golem15.translate |
Requires |
✓ WIRED | Requires() []string{"golem15.translate"} |
models/post.go |
posts migration | TableName |
✓ WIRED | both golem15_journal_posts |
summer.yaml |
plugins.gen.go |
summer build blank-import |
✓ WIRED | _ "git.golem15.com/golem15/sm-journal-plugin" |
controllers/posts.go |
classes/format_html.go |
FormBeforeCreate/Update | ✓ WIRED | classes.FormatHTML(post.Content) |
admin_permissions.go |
controllers/posts.go |
RequiredPermissions |
✓ WIRED | golem15.journal.access_posts |
console/export_posts.go |
plugin.go |
HasCommands |
✓ WIRED | console.ExportPosts in Commands() |
routes.go |
controllers/api/auth.go |
backend JWT on writes | ✓ WIRED | requireBackendPrincipal / optionalBackendPrincipal |
controllers/api/posts.go |
classes/format_html.go |
store/update | ✓ WIRED | posts_helpers.go calls FormatHTML |
search.go |
models/settings.go |
Gate ID=1 | ✓ WIRED | SetGate + settingsSearchEnabled |
integration_test.go |
routes.go |
assembled handlers | ✓ WIRED | TestJournalEndToEnd hits public GET and Bearer POST |
check-phase15.sh |
plugin suite | go -C full, not -short |
✓ WIRED | --plugin PASS this pass |
15-SECURITY-REVIEW.md |
named tests | T-15-* | ✓ WIRED | --security requires mitigate on high IDs |
Data-Flow Trace (Level 4)
| Artifact | Data Variable | Source | Produces Real Data | Status |
|---|---|---|---|---|
GET /_journal/api/v1/posts |
data / meta |
GORM Model(&models.Post{}) + lagoon.Paginate |
Yes — TestJournalPublicList seeds rows and asserts listed slug |
✓ FLOWING |
| Admin POST posts | stored Post + translate attributes |
cabana form → GORM + golem15_translate_attributes |
Yes — TestPostsAdminCreateSmoke / TestJournalEndToEnd |
✓ FLOWING |
FormatHTML content_html |
post.ContentHTML |
goldmark convert of content |
Yes — create smoke asserts markup, rejects script | ✓ FLOWING |
| Settings gate | search_use_typesense |
golem15_journal_settings id=1 |
Yes — default false in DDL; TestSearchGateOff |
✓ FLOWING |
| Nav SVG | AdminFS file | //go:embed assets/images/journal-icon.svg |
Bytes present; SPA nav uses lucide pencil (no IconSvg field) |
✓ FLOWING (embed); SPA icon is lucide |
Behavioral Spot-Checks
| Behavior | Command | Result | Status |
|---|---|---|---|
| PHP pin frozen and clean | bash scripts/check-phase15.sh --php |
phase15 php passed (02110eb1…) |
✓ PASS |
| Host layout + gitlinks + CORS | bash scripts/check-phase15.sh --layout |
phase15 layout passed |
✓ PASS |
| Plugin vet + full suite + race | bash scripts/check-phase15.sh --plugin |
phase15 plugin passed (~85s) |
✓ PASS |
Host vet + TestBootUserTranslateJournal/TestCORS + build |
bash scripts/check-phase15.sh --host |
phase15 host passed |
✓ PASS |
| Forbidden surfaces | bash scripts/check-phase15.sh --forbidden |
phase15 forbidden passed |
✓ PASS |
| Security review + VALIDATION sign-off | bash scripts/check-phase15.sh --security |
phase15 security passed |
✓ PASS |
| Detector fail-closed | bash scripts/check-phase15.sh --self-test |
phase15 self-test passed |
✓ PASS |
Probe Execution
No scripts/*/tests/probe-*.sh. Phase-declared gate is scripts/check-phase15.sh.
| Probe | Command | Result | Status |
|---|---|---|---|
scripts/check-phase15.sh --self-test |
bash scripts/check-phase15.sh --self-test |
exit 0 | PASS |
scripts/check-phase15.sh --php |
bash scripts/check-phase15.sh --php |
exit 0 | PASS |
scripts/check-phase15.sh --layout |
bash scripts/check-phase15.sh --layout |
exit 0 | PASS |
scripts/check-phase15.sh --plugin |
bash scripts/check-phase15.sh --plugin |
exit 0 | PASS |
scripts/check-phase15.sh --host |
bash scripts/check-phase15.sh --host |
exit 0 | PASS |
scripts/check-phase15.sh --forbidden |
bash scripts/check-phase15.sh --forbidden |
exit 0 | PASS |
scripts/check-phase15.sh --security |
bash scripts/check-phase15.sh --security |
exit 0 | PASS |
--all is those seven stages in order. Each stage was executed in this verification process.
Requirements Coverage
ROADMAP lists Requirements: TBD. REQUIREMENTS.md has no Journal IDs. Plan frontmatter IDs are CONTEXT decisions D-01–D-23. Every ID from plans is accounted for below.
| Requirement | Source Plan | Description | Status | Evidence |
|---|---|---|---|---|
| D-01 | 01, 04 | Port contract PHP SHA 02110eb |
✓ SATISFIED | --php HEAD match |
| D-02 | 01, 04 | Freeze at that SHA | ✓ SATISFIED | gate pins full SHA |
| D-03 | 01, 04 | Read frozen tree at fonoteka journal path | ✓ SATISFIED | PHASE15_PHP default path; tree present |
| D-04 | 01, 02, 04 | Models/tables/YAML/perms/commands/API | ✓ SATISFIED | migrations + YAML + routes + commands |
| D-05 | 04 | PHPUnit map | ✓ SATISFIED | named Go tests for §8 rows |
| D-06 | 01, 02, 04 | en+pl only | ✓ SATISFIED | two lang dirs; 02 prohibition |
| D-07 | 01, 04 | Do not edit PHP journal | ✓ SATISFIED | porcelain empty; test-tier prohibition wired in --php |
| D-08 | 02, 04 | Embed journal-icon.svg | ✓ SATISFIED | AdminFS + byte cmp |
| D-09 | 01, 04 | Do not port Translate inside Journal; Require translate not apparatus | ✓ SATISFIED | Requires exactly translate; no apparatus ID |
| D-10 | 01–04 | Translatable attributes | ✓ SATISFIED | Post/Category Translatable + MorphName |
| D-11 | 02, 04 | Use existing cabana markdown; no second field type | ✓ SATISFIED | mlmarkdown; field_markdown.go untouched |
| D-12 | 03, 04 | Typesense off by default | ✓ SATISFIED | TestSearchGateOff |
| D-13 | 02, 04 | Import/export CLI + toolbar (PHP JSON files, not Winter CSV) | ✓ SATISFIED | TestJournalCommands |
| D-14 | 03, 04 | Full /_journal/api/v1 |
✓ SATISFIED | routes + public tests |
| D-15 | 03, 04 | Backend Bearer writes only | ✓ SATISFIED | 401 PHP shape; frontend aud rejected |
| D-16 | 03, 04 | Not tide | ✓ SATISFIED | --forbidden + TestNoTideJournalFixtures |
| D-17 | 01, 03, 04 | Limiters + CORS | ✓ SATISFIED | buckets + http.yaml |
| D-18 | 01, 04 | Proof host sm-grzybyfunkcjonalne-app | ✓ SATISFIED | sibling checkout + origin |
| D-19 | 01, 04 | Mount, migrate, admin, API (SPA chrome → human) | ✓ SATISFIED | boot + plugin HTTP; SPA listed under Human Verification |
| D-20 | 01, 04 | Local host path | ✓ SATISFIED | /media/nvme/dev/golem15/summercms.io/summercms/sm-grzybyfunkcjonalne-app |
| D-21 | 01, 04 | Submodules journal+translate+user | ✓ SATISFIED | gitlinks 160000 |
| D-22 | 01, 04 | Plugin remote/module/package/ID | ✓ SATISFIED | go.mod + plugin.go + origin |
| D-23 | 01, 04 | Local plugin checkout + host submodule replace | ✓ SATISFIED | sibling sm-journal-plugin; host replace => ./plugins/golem15/journal |
| API-09 | REQUIREMENTS.md map only | 154 Płytarium routes | deferred | Phase 20; not in any Phase 15 plan requirements: |
| QA-05 | REQUIREMENTS.md map only | Cutover harness | deferred | Phase 20; not in any Phase 15 plan requirements: |
Orphaned REQUIREMENTS.md IDs mapped to Phase 15: API-09, QA-05 — recorded under Deferred, not gaps. Plans treat them as Phase 20.
Prohibitions (test-tier): D-07, D-09, D-18, D-11, D-13 (no Pages/dashboard), D-06, D-15, D-14 (PHP error envelope), D-12, D-16 — each has wired --php/--layout/--forbidden or a named test. Not unverified.
Decision Coverage
All trackable CONTEXT.md decisions are honored by shipped artifacts. 23/23 honored.
Test Quality Audit
| Test File | Linked Req | Active | Skipped | Circular | Assertion Level | Verdict |
|---|---|---|---|---|---|---|
models/fillable_test.go |
D-05 JOURNAL-001/002 | yes | no | no | Value | OK |
journal_api_writes_test.go |
D-14/D-15/JOURNAL-005 | yes | no | no | Behavioral | OK |
journal_api_task3_test.go |
JOURNAL-006, RSS | yes | no | no | Behavioral | OK |
search_test.go |
D-12 | yes | no | no | Behavioral | OK |
classes/format_html_test.go |
JOURNAL-003/004 subst. | yes | no | no | Value | OK |
updates/migrations_test.go |
D-04 | yes | only -short |
no | Behavioral | OK |
integration_test.go |
D-05/D-14/D-15 | yes | only -short |
no | Behavioral | OK |
empty TestJournalEndToEnd shims in other packages |
gate -run hygiene |
yes (no-op) | no | no | Existence | ⚠️ WARNING — real proof is journal_test.TestJournalEndToEnd |
Disabled tests on requirements: 0 blockers. t.Skip("requires testcontainers postgres") only when -test.short; full --plugin run is not -short and TestMain exits 1 if Docker fails.
Circular patterns detected: 0
Insufficient assertions: empty EndToEnd shims only (other tests cover the requirement)
Anti-Patterns Found
| File | Line | Pattern | Severity | Impact |
|---|---|---|---|---|
plugin_test.go (and sibling packages) |
TestJournalEndToEnd empty |
no-op test shim | ℹ️ Info | Keeps go test ./... -run TestJournalEndToEnd from printing no tests to run; real test is integration_test.go package journal_test |
updates/postgres_test.go |
rainlab table name in test | historical name check | ℹ️ Info | Test-only; --forbidden excludes _test.go |
go.mod |
require sm-user-plugin |
test harness module | ℹ️ Info | Production .go files do not import it (--forbidden + TestJournalEndToEndFixtureAbsentFromProduction) |
15-SECURITY-REVIEW.md |
reviewer | executor self-review | ℹ️ Info | No dedicated auditor in this Cursor session; cited tests were re-run by --plugin this pass |
| production plugin sources | — | TBD/FIXME/XXX | none | No unreferenced debt markers |
Human Verification Required
1. Journal admin SPA on the proof host
Test: Boot sm-grzybyfunkcjonalne-app. Sign in as an administrator holding golem15.journal.*. Open Journal nav. List and create a post whose content is mlmarkdown. Repeat without golem15.journal.access_posts.
Expected: Posts/Categories/Tags screens work; mlmarkdown editor is present; missing permission cannot open Posts.
Why human: Needs a running host, admin login, and visual confirmation. Automated tests cover HTTP 403/schema/create, not SPA chrome.
2. Gitea remotes still exist
Test: git ls-remote git@git.golem15.com:golem15/sm-journal-plugin.git and the proof-host remote.
Expected: Each remote returns a HEAD SHA.
Why human: Local origin URLs match D-18/D-22; this verifier could not complete git ls-remote within 8s.
Gaps Summary
No blocking gaps. All 22 must-have truths are present, wired, and exercised by named tests or the fail-closed gate. Status is human_needed because harvested end-of-phase UAT (admin SPA and remote reachability) remains. ROADMAP/STATE were not marked complete.
PHPUnit XSS template tests (\|raw_safe on .htm) stay Phase 16 by RESEARCH; FormatHTML unsafe-tag tests substitute this phase and passed.
Verified: 2026-10-06T17:29:31Z Verifier: the agent (gsd-verifier)