From b045567815f5eb808fa86c4009174937c42172d0 Mon Sep 17 00:00:00 2001 From: Tyler Windes <66438824+Tyler-Windes@users.noreply.github.com> Date: Thu, 3 Sep 2026 15:45:23 -0600 Subject: [PATCH 1/8] Align readiness project metadata with the platform-neutral and Atlassian layers --- ...entation-readiness-support-transition.json | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/content/projects/implementation-readiness-support-transition.json b/content/projects/implementation-readiness-support-transition.json index 8fd2b8c..dddb563 100644 --- a/content/projects/implementation-readiness-support-transition.json +++ b/content/projects/implementation-readiness-support-transition.json @@ -3,32 +3,32 @@ "schema_version": "2.0.0", "project_id": "PORT-0002", "title": "Implementation Readiness & Support Transition", - "subtitle": "A synthetic, platform-neutral work sample showing how requirements, readiness, UAT findings, transition controls, and support handoff fit together.", + "subtitle": "A two-layer case study connecting a platform-neutral readiness model with a working Jira and Confluence implementation.", "data_class": "Synthetic", "publication_state": "PortfolioApproved", - "differentiator": "This project extends the portfolio beyond technical workflow proof by focusing on implementation readiness, retest judgment, rollback, role enablement, early-life support, and ownership handoff.", - "problem": "A fictional internal service-request process relies on email and a shared tracker. Minimum submission rules blur into later clarification, priority and routing vary, accountable ownership is unclear, and closure can lose context needed by support.", - "judgment": "The design separates the minimum submission gate from post-submission completeness, makes category and priority decisions explicit, requires one accountable owner, and blocks closure until requester validation and handoff context are retained.", + "differentiator": "This project connects platform-neutral lifecycle analysis with a working Atlassian implementation while keeping the two validation models and the v1.1 roadmap distinct.", + "problem": "A fictional service-request process begins with incomplete intake, unclear ownership, hidden dependencies, weak acceptance criteria, and support context that can be lost before handoff.", + "judgment": "The design separates minimum intake from later clarification, makes priority and ownership visible, records real blocking conditions, keeps validation separate from completion, and preserves failed tests through correction and retest.", "evidence": [ - "Eight final synthetic UAT outcomes after two corrected findings and passing retests", - "Six explicit transition smoke checks with a concrete rollback boundary", - "Three simulated hypercare days linked to support runbooks and ownership handoff" + "Eight final synthetic foundation outcomes after two corrected findings and passing retests", + "A Jira and Confluence implementation with ten completed requirements, ten final passing UAT cases, and two closed Bugs", + "Core v1.0 separated from planned Jira reporting and Forge work in the v1.1 roadmap" ], "capabilities": [ - "Discovery and requirements", - "Configuration-readiness judgment", - "Synthetic UAT and retest decisions", - "Cutover, rollback, and communications", - "Role enablement and support handoff" + "Requirements and acceptance criteria", + "Jira workflow and dependency design", + "UAT, Bug correction, and retesting", + "Readiness, rollback, and support handoff", + "Atlassian Forge solution design" ], "links": { - "case_study_path": "projects/implementation-readiness-support-transition.html", + "case_study_path": "irw/index.html", "repository_name": "implementation-readiness-support-transition", "repository_url": "https://github.com/Tyler-Windes/implementation-readiness-support-transition", "repository_state": "ExistingPublicRepositoryWithVerifiedV1Release" }, "scope": [ - "This is a synthetic, fictional, platform-neutral work sample. It is not evidence of a real implementation, stakeholder engagement, configured platform, UAT, deployment, training, hypercare, or support ownership.", - "All readiness, transition, and support outcomes are modeled locally for review; no live platform, external account, or operational outcome is represented." + "This project uses fictional information. The platform-neutral foundation and IRW workspace do not represent a customer deployment or measured business outcome.", + "The Jira dashboard and Forge application remain planned v1.1 work and are not described as complete." ] } From 27b1f394a69ba7994b2068aa814e307faa747662 Mon Sep 17 00:00:00 2001 From: Tyler Windes <66438824+Tyler-Windes@users.noreply.github.com> Date: Thu, 3 Sep 2026 15:48:26 -0600 Subject: [PATCH 2/8] Add the canonical IRW case study route --- src/irw/index.html | 257 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 src/irw/index.html diff --git a/src/irw/index.html b/src/irw/index.html new file mode 100644 index 0000000..9dfc67b --- /dev/null +++ b/src/irw/index.html @@ -0,0 +1,257 @@ + + + + + + Implementation Readiness Workspace | Tyler Windes + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ Back to selected work +

Requirements - Jira - Confluence - UAT - Support

+

Implementation Readiness Workspace

+

A two-layer case study showing how I move an unclear service request through requirements, implementation, validation, readiness, and operational handoff.

+
+
Foundation
Platform-neutral lifecycle model
+
Implementation
Jira and Confluence workspace
+
Validation
10 final passing UAT cases
+
Next
Jira reporting and Forge
+
+ +
+
+ + + +
+
+
+

Project relationship

+

One problem area, developed in two layers

+
+
+

I first developed a platform-neutral implementation-readiness model. It defines intake, routing, readiness, transition, rollback, early-life support, and ownership handoff without tying the work to one product.

+

I then applied the same capability area in a working Jira and Confluence workspace. IRW uses a separate ten-requirement and ten-test model to validate the Atlassian implementation.

+

The original eight validation cases test the platform-neutral model. The ten IRW cases test the Jira and Confluence implementation. I keep the two sets separate because they answer different questions.

+
+
+
+ +
+
+
+

The problem

+

Implementation risk often starts before implementation

+
+
+

A request can look actionable while still missing the information needed for a sound decision. Ownership may be unclear, priority may have no documented reason, dependencies may live only in conversation, and acceptance criteria may be too vague to test.

+

IRW provides a practical way to make those conditions visible and keep the work connected from intake through closeout.

+
+
+
+ +
+
+
+

My role

+

I owned the analysis, decisions, validation, and closeout

+

The project was completed as an individual fictional implementation. I used automation for repetitive setup and consistency checking, while retaining responsibility for the decisions and results.

+
+
+

Define

Set the scope, assumptions, requirements, priorities, ownership, and acceptance criteria.

+

Structure

Organize Epics, Stories, Tasks, Subtasks, workflow states, and dependencies in Jira.

+

Validate

Run the UAT cases, evaluate the actual results, create Bugs after failures, and repeat the tests after correction.

+

Reconcile

Resolve conflicts between Jira and Confluence, make the readiness decision, and separate completed work from the next roadmap.

+
+
+
+ +
+
+
+

Solution

+

A traceable path from intake to handoff

+

Ten requirements define what the workspace must support, and one fictional request shows how the pieces work together.

+
+
+
IRW lifecycleImplementation and acceptance remain distinct
+
    +
  1. 01IntakeRequired information and missing-input checks
  2. +
  3. 02TriageOwner, priority, impact, and urgency
  4. +
  5. 03ImplementJira work, workflow states, and dependencies
  6. +
  7. 04ValidateAcceptance criteria and UAT
  8. +
  9. 05CorrectBug, correction, and retest when needed
  10. +
  11. 06Hand offReadiness, rollback, support, and traceability
  12. +
+
+
+

Requirements

Ten stable requirements cover intake, ownership, workflow, dependencies, validation, defects, readiness, rollback, support, and traceability.

+

Workflow

To Do, Ready, In Progress, Blocked, Validation, and Done keep planned, active, prevented, validating, and completed work distinct.

+

Dependency

IRW-76, the intake prerequisite, blocks IRW-75, the triage and ownership work. The link remains visible after completion.

+

Handoff

The final records include readiness rules, rollback and smoke checks, risks, troubleshooting guidance, and ownership.

+
+
+
+ +
+
+
+

Testing and correction

+

The useful part was not that every test passed the first time

+

Two tests exposed issues. I kept the failed results, corrected the records, and repeated the tests instead of rewriting the history.

+
+
+
+

UAT-004

+

Dependency interpretation

+

A later test record used a stale interpretation of the intake-to-triage dependency. IRW-82 preserved the failure, correction, and passing retest from both linked issues.

+
+
+

UAT-006

+

Defect traceability

+

NEG-001 intentionally omitted its source test ID. IRW-87 was created after the failure, the missing traceability was added, and the same inspection passed on retest.

+
+
+
+
+ +
+
+
+

Results

+

Core v1.0 is complete against the defined requirements

+

The figures describe this fictional project only. They are not business-impact or production metrics.

+
+
+
10Completed requirements
+
10/10Final UAT cases passed
+
2Bugs corrected and retested
+
6Jira workflow states
+
35Completed core Jira items
+
3Planned v1.1 items
+
+
+

The core records include the requirements baseline, SR-001 implementation, UAT and Bug register, readiness and rollback plan, risk and decision log, support runbook, and completion summary.

+

No customer result, production deployment, financial impact, performance metric, Jira dashboard, or Forge runtime is claimed.

+
+
+
+ +
+
+
+

Decisions and tradeoffs

+

A few decisions mattered more than the amount of documentation

+
+
+

Use Blocked only when something actually prevents progress

Ordinary incomplete work stayed in To Do, Ready, or In Progress. Blocked represented a concrete prerequisite.

+

Keep Validation separate from Done

Implementation could be complete without yet being accepted. The workflow kept that distinction visible.

+

Preserve failed tests

The failed results, corrections, and retests remain part of the project instead of being replaced by a cleaner-looking story.

+

Move unfinished features into v1.1

The Jira dashboard and Forge designs are useful, but specifications are not working features. They remain planned until implemented and tested.

+
+
+
+ +
+
+
+

v1.1 roadmap

+

Build a small reporting layer and Forge component next

+
+
+

The first Jira reporting release will create five saved filters and one dashboard covering requirements, open core work, open Bugs, Validation, and the v1.1 roadmap.

+

The first Forge release will provide a read-only project page that checks a small set of high-value Jira readiness conditions, links failed checks to Jira issues, and reports roadmap work separately.

+

I am completing the Atlassian Forge certification path and related hands-on preparation before implementation begins. No source, app identity, build, deployment, installation, or runtime result is claimed yet.

+
+
+
+ +
+
+
+

Scope

+

A fictional implementation, not a customer deployment

+
+
+

IRW demonstrates requirements analysis, Jira and Confluence organization, implementation planning, UAT, Bug handling, readiness decisions, rollback planning, and support handoff.

+

It does not represent customer work, production administration, measured outcomes, a completed Jira dashboard, or a deployed Forge application.

+
+
+
+ + +
+ + + + From 1312dec9ca7ab1d002247f2301f080ebfecffa5e Mon Sep 17 00:00:00 2001 From: Tyler Windes <66438824+Tyler-Windes@users.noreply.github.com> Date: Thu, 3 Sep 2026 15:48:45 -0600 Subject: [PATCH 3/8] Redirect the former readiness route to the canonical IRW page --- ...entation-readiness-support-transition.html | 103 ++++-------------- 1 file changed, 22 insertions(+), 81 deletions(-) diff --git a/src/projects/implementation-readiness-support-transition.html b/src/projects/implementation-readiness-support-transition.html index a76249a..0d5ee0d 100644 --- a/src/projects/implementation-readiness-support-transition.html +++ b/src/projects/implementation-readiness-support-transition.html @@ -3,21 +3,22 @@ - Implementation Readiness & Support Transition | Tyler Windes - + Implementation Readiness Workspace | Tyler Windes + - + + - - - + + + - + @@ -26,87 +27,27 @@ -
- ← Back to selected work -

Synthetic implementation lifecycle work sample

-

Implementation Readiness & Support Transition

-

A platform-neutral model for moving a fictional internal service-request workflow from ambiguous intake through readiness, synthetic UAT, transition controls, early-life support, and ownership handoff.

-
-
Problem
Ambiguous intake and ownership
-
Judgment
Readiness before transition
-
Evidence
UAT, retests, and smoke checks
-
Boundary
Synthetic · No live platform
-
- +

Project page moved

+

Implementation Readiness Workspace

+

The implementation-readiness case study now has a shorter, stable address.

+

Open the current case study

- - - -
-
-

The problem

A request process can look simple while hiding implementation risk

-

The fictional current state begins in email and a shared tracker. Minimum submission content blurs into later clarification, priority and routing depend on individual judgment, accountable ownership is inconsistent, and closure can lose the context support would need.

The work sample turns those ambiguities into explicit, reviewable decisions without claiming that a platform was configured or a live process changed.

-
-
- -
-
-

Design decisions

Separate the gates, make ownership visible, and protect closure

Four decisions shape the readiness, test, transition, and support evidence.

-
-

Two-stage intake

Five minimum fields control submission. Conditional routing detail is reviewed only after submission, so a failed minimum gate never masquerades as clarification.

-

Deterministic priority and routing

Four categories map to modeled skill contexts. Priority is evaluated from Critical through Low, and the first satisfied rule controls.

-

One accountable owner

The coordinator retains responsibility until a match exists; assignment and reassignment always leave exactly one accountable Fulfiller.

-

Requester-controlled closure

Closure requires a requester decision plus resolution, ownership, category, support reference, and handoff context.

-
-
-
- -
-
-

Representative request

Follow one request from intake to support context

A fictional reporting request makes the decision rules concrete without introducing PII or a live platform.

-
-
Department exception-view requestModeled lifecycle, not a live transaction
-
    -
  1. 01SubmitFive minimum fields are present.
  2. -
  3. 02ClarifyReporting period and filter definition are added.
  4. -
  5. 03PrioritizeWorkaround plus near-term need produces Medium.
  6. -
  7. 04AssignData/Reporting route, one accountable Fulfiller.
  8. -
  9. 05ResolveA definition blocker is recorded and cleared.
  10. -
  11. 06Validate and closeRequester accepts; support context is retained.
  12. -
-
Text alternative

A fictional Requester submits all five minimum fields for a department-level exception view. The coordinator requests missing reporting-period and filter details, recalculates completeness, applies Medium priority, and routes to the Data/Reporting skill context. One Fulfiller becomes accountable. A documented field-definition blocker is resolved before requester validation and closure with a support reference and handoff note.

-
-
-
- -
-
-

Test findings

Findings matter when they change the readiness judgment

Eight synthetic UAT cases exercise intake, routing, ownership, transition controls, communication, validation, and handoff.

-
6Initial synthetic passes
2Bounded findings corrected
2Passing retests
8/8Final synthetic passes
6Transition smoke checks
0Unresolved Critical or High items
-

One finding exposed stale post-clarification completeness. The other exposed direct closure without a requester decision. The modeled guidance and rules were corrected, both retests passed, and the final readiness state changed accordingly.

These are static, synthetic observations. They do not claim software execution, real users, real UAT, or a configured platform.

-
-
- -
-

Readiness and rollback

A GO decision follows the evidence; it does not create it

Passing retests, no unresolved Critical or High item, a frozen baseline, and ready role/runbook guidance precede the simulated go/no-go review. Its resulting GO decision then governs the modeled transition and six smoke checks.

If a required check fails, the model pauses transition, restores the frozen baseline, preserves evidence, records rollback communication, and requires revalidation before resuming.

All six modeled smoke checks pass, so rollback remains available but is not invoked.

-
- -
-

Enablement and support

Transition is incomplete until roles and support can use the result

Role guidance

Requester, coordinator, fulfiller, and support responsibilities focus on changed decisions and retained context.

Three-day hypercare model

Early-life questions are triaged across three simulated business days without claiming a live support operation.

Runbook mapping

Each simulated case maps to a recovery path for completeness, closure validation, or handoff context.

Ownership handoff

The final review confirms closed cases, usable mappings, retained context, and no unresolved Critical or High item.

-
- -

Scope

Synthetic implementation-analysis proof, not implementation experience

This project demonstrates requirements, readiness, test design, retest judgment, rollback logic, enablement, and support-transition thinking. It does not prove real stakeholder participation, configuration, platform administration, UAT, deployment, go-live, training, hypercare, SLA performance, adoption, savings, or other business outcomes.

It adds lifecycle and transition proof beyond the portfolio’s separate workflow/data foundation and integration-reliability project.

- -
- + From cbc0b6601417bfba26c99e24fb877c384e024b7b Mon Sep 17 00:00:00 2001 From: Tyler Windes <66438824+Tyler-Windes@users.noreply.github.com> Date: Thu, 3 Sep 2026 15:50:03 -0600 Subject: [PATCH 4/8] Align the homepage with the three-project narrative and canonical IRW route --- src/index.html | 129 +++++++++++++++++-------------------------------- 1 file changed, 44 insertions(+), 85 deletions(-) diff --git a/src/index.html b/src/index.html index 490842d..d482ac7 100644 --- a/src/index.html +++ b/src/index.html @@ -3,20 +3,20 @@ - Tyler Windes | Technical Consultant & Systems Analyst + Tyler Windes | Technical Consultant and Systems Analyst - - + + - + @@ -47,9 +47,9 @@
-

Technical Consultant · Systems Analyst · Business Systems Analyst

+

Technical Consultant | Systems Analyst | Business Systems Analyst

I turn ambiguous workflows into clear, testable systems.

-

I connect business context to requirements, data rules, SQL-backed analysis, and practical documentation so the next decision is easier to understand and support.

+

I connect business context to requirements, data rules, implementation details, and practical documentation so the next decision is easier to understand and support.

Explore selected work Explore capabilities @@ -63,9 +63,9 @@

Analysis that holds up after handoff

  • Systems and workflow analysis
  • Requirements and acceptance criteria
  • Data-quality validation
  • -
  • SQL, reconciliation, and traceability
  • +
  • Implementation and support documentation
  • -

    I aim for work that a business partner can follow, a technical reviewer can test, and a support team can maintain.

    +

    I aim for work that a business partner can follow, a technical reviewer can test, and another person can maintain.

    @@ -74,8 +74,8 @@

    Analysis that holds up after handoff

    Capabilities

    -

    From operating problem to reviewable evidence

    -

    I work across the boundaries between business analysis, implementation detail, and technical validation.

    +

    From operating problem to usable solution

    +

    I work across the boundaries between business analysis, implementation detail, technical validation, and operational handoff.

    @@ -90,13 +90,13 @@

    Requirements and acceptance

    03

    -

    Data quality and SQL

    +

    Data quality and reconciliation

    Preserve source meaning, route exceptions honestly, query controlled data, and reconcile reported results.

    04

    -

    Traceable communication

    -

    Connect decisions to source values, rules, tests, and documentation that technical and business readers can use.

    +

    Implementation and handoff

    +

    Connect decisions to work, tests, corrections, and documentation that technical and business readers can use.

    @@ -105,36 +105,36 @@

    Traceable communication

    -

    Selected work

    Three projects. Three different kinds of proof.

    -

    Each case study uses synthetic data and a bounded local scope. Together they show how I move from workflow analysis, to implementation readiness, to integration reliability and support.

    +

    Selected work

    Three projects across one connected workflow.

    +

    Together, the projects show how I move from workflow and data analysis, to implementation readiness, to integration reliability and troubleshooting.

    -
    02 · Implementation lifecycleSynthetic lifecycle
    -

    Implementation Readiness & Support Transition

    -

    Carry a fictional service-request workflow through requirements, readiness, UAT findings, retests, rollback, enablement, and support handoff.

    -

    Strongest proof: implementation-analysis judgment, transition controls, role readiness, hypercare, and handoff.

    -
    • Readiness
    • Synthetic UAT
    • Retests
    • Rollback
    • Handoff
    - +
    02 - Implementation lifecycleTwo related layers
    +

    Implementation Readiness and Support Transition

    +

    Connect a platform-neutral readiness model with a Jira and Confluence implementation covering requirements, dependencies, UAT, Bug correction, rollback, and handoff.

    +

    Focus: implementation judgment, Jira workflow design, validation, readiness decisions, and operational transition.

    +
    • Jira
    • Confluence
    • UAT
    • Rollback
    • Handoff
    +
    -
    03 · Integration reliabilitySynthetic integration
    -

    SaaS Integration Reliability & Support Troubleshooting

    +
    03 - Integration reliabilitySynthetic integration
    +

    SaaS Integration Reliability and Support Troubleshooting

    Exercise source-to-target contracts, mapping, idempotency, ordering, retries, dead letter, replay, reconciliation, and incident response.

    -

    Strongest proof: executable integration reliability, structured evidence, recovery, and troubleshooting.

    +

    Focus: executable integration reliability, structured diagnostics, recovery, and troubleshooting.

    • FastAPI
    • Mapping
    • Retries
    • Replay
    • Reconciliation
    - +
    @@ -145,25 +145,13 @@

    SaaS Integration Reliability & Support Troub

    How I work

    Structured enough to trust. Practical enough to use.

    -

    I treat analysis as a chain: the business question shapes the rule, the rule shapes the implementation, and the evidence shows whether the result holds.

    +

    I treat analysis as a chain: the business question shapes the rule, the rule shapes the implementation, and the result shows whether the approach holds.

      -
    1. - 01 -

      Understand the operating context

      Identify the people, process, systems, source authority, constraints, and decision boundary.

      -
    2. -
    3. - 02 -

      Define the contract

      Translate ambiguity into requirements, data rules, mappings, assumptions, and acceptance criteria.

      -
    4. -
    5. - 03 -

      Test the important edges

      Preserve exceptions, reconcile outputs, and distinguish supported facts from values that still need judgment.

      -
    6. -
    7. - 04 -

      Make the result usable

      Document the reasoning and evidence so another person can review, implement, or support the work.

      -
    8. +
    9. 01

      Understand the operating context

      Identify the people, process, systems, source authority, constraints, and decision boundary.

    10. +
    11. 02

      Define the contract

      Translate ambiguity into requirements, data rules, mappings, assumptions, and acceptance criteria.

    12. +
    13. 03

      Test the important edges

      Preserve exceptions, reconcile outputs, and distinguish supported facts from values that still need judgment.

    14. +
    15. 04

      Make the result usable

      Document the reasoning and decisions so another person can review, implement, or support the work.

    @@ -176,7 +164,7 @@

    Business context, translated into technical work

    My background combines independent technical analysis with regulated business operations and years of client-facing problem solving. I translate that experience into requirements, data rules, technical documentation, and handoffs that business and technical teams can use.

    -

    That experience shapes how I work: clarify what a rule means, account for exceptions, document the decision, and leave the next person with something they can use.

    +

    That experience shapes how I work: clarify what a rule means, account for exceptions, document the decision, and leave the next person with something usable.

    @@ -185,22 +173,11 @@

    Business context, translated into technical work

    Tools and methods

    -

    Tools connected to bounded, reviewable proof

    -

    The projects connect analysis artifacts to local Python, SQLite, SQL, API contracts, structured tests, transition evidence, reconciliation, and support documentation.

    +

    Tools tied to practical project work

    +

    The projects connect analysis to Python, SQLite, SQL, APIs, Jira, Confluence, structured tests, reconciliation, and support documentation.

    -
    @@ -209,31 +186,13 @@

    Tools connected to bounded, reviewable proof

    Background

    -

    Education & Technical Training

    -

    My education combines a business foundation with hands-on technical training that supports my work across systems, workflows, data quality, and technical problem solving.

    +

    Education and Technical Training

    +

    My education combines a business foundation with hands-on technical training that supports work across systems, workflows, data quality, and technical problem solving.

    -
    -
    -

    Business foundation

    -

    Front Range Community College

    -
    -

    Associate of Arts with Business Designation, 2015

    -
    - -
    -
    -

    Coursework

    -

    Additional coursework

    -
    -

    Additional coursework at Colorado State University and the University of Northern Colorado

    -
    +

    Business foundation

    Front Range Community College

    Associate of Arts with Business Designation, 2015

    + +

    Coursework

    Additional coursework

    Additional coursework at Colorado State University and the University of Northern Colorado

    @@ -255,7 +214,7 @@

    Continue the conversation

    From c0780a279fccb393fce1cde1936a813d72ce5ce3 Mon Sep 17 00:00:00 2001 From: Tyler Windes <66438824+Tyler-Windes@users.noreply.github.com> Date: Thu, 3 Sep 2026 15:50:35 -0600 Subject: [PATCH 5/8] Add the canonical IRW route to the deterministic build and sitemap --- scripts/build.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/build.mjs b/scripts/build.mjs index b18e408..34a34be 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -20,6 +20,7 @@ const distRoot = join(projectRoot, "dist"); const validationRoot = join(projectRoot, "validation"); const htmlRoutes = [ "index.html", + "irw/index.html", "projects/workflow-intake-analysis.html", "projects/implementation-readiness-support-transition.html", "projects/saas-integration-reliability-support-troubleshooting.html", @@ -27,8 +28,8 @@ const htmlRoutes = [ ]; const sitemapRoutes = [ "/", + "/irw/", "/projects/workflow-intake-analysis.html", - "/projects/implementation-readiness-support-transition.html", "/projects/saas-integration-reliability-support-troubleshooting.html", ]; From 792856c991564e6fcc0833db6b1287cf4b2d94ae Mon Sep 17 00:00:00 2001 From: Tyler Windes <66438824+Tyler-Windes@users.noreply.github.com> Date: Thu, 3 Sep 2026 15:50:43 -0600 Subject: [PATCH 6/8] Add the canonical IRW route to the source sitemap --- src/sitemap.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sitemap.xml b/src/sitemap.xml index 8f43652..9805198 100644 --- a/src/sitemap.xml +++ b/src/sitemap.xml @@ -4,10 +4,10 @@ {{SITE_BASE_URL}}/ - {{SITE_BASE_URL}}/projects/workflow-intake-analysis.html + {{SITE_BASE_URL}}/irw/ - {{SITE_BASE_URL}}/projects/implementation-readiness-support-transition.html + {{SITE_BASE_URL}}/projects/workflow-intake-analysis.html {{SITE_BASE_URL}}/projects/saas-integration-reliability-support-troubleshooting.html From 2468bce2507695a9cb25f52ad9a6ad7acbbc541a Mon Sep 17 00:00:00 2001 From: Tyler Windes <66438824+Tyler-Windes@users.noreply.github.com> Date: Thu, 3 Sep 2026 15:54:03 -0600 Subject: [PATCH 7/8] Update the site validator for the canonical IRW route and revised project model --- scripts/validation-core.mjs | 308 ++++++++++++++++++++---------------- 1 file changed, 175 insertions(+), 133 deletions(-) diff --git a/scripts/validation-core.mjs b/scripts/validation-core.mjs index ab1e22f..4b75217 100644 --- a/scripts/validation-core.mjs +++ b/scripts/validation-core.mjs @@ -20,25 +20,36 @@ const PORT2_TOKEN = "{{PORT0002_REPOSITORY_URL}}"; const PORT3_TOKEN = "{{PORT0003_REPOSITORY_URL}}"; const PROFILE_URL = "https://github.com/Tyler-Windes"; const LINKEDIN_URL = "https://www.linkedin.com/in/tylerwindes"; +const IRW_ATLASSIAN_URL = + "https://tyler-windes.atlassian.net/wiki/spaces/~7120203b004a0c07184b39860e66e497b78dd0/pages/426169"; const ROUTES = [ - { path: "index.html", url: `${SITE_ORIGIN}/`, type: "website" }, + { path: "index.html", canonical: `${SITE_ORIGIN}/`, type: "website" }, + { path: "irw/index.html", canonical: `${SITE_ORIGIN}/irw/`, type: "article" }, { path: "projects/workflow-intake-analysis.html", - url: `${SITE_ORIGIN}/projects/workflow-intake-analysis.html`, + canonical: `${SITE_ORIGIN}/projects/workflow-intake-analysis.html`, type: "article", }, { path: "projects/implementation-readiness-support-transition.html", - url: `${SITE_ORIGIN}/projects/implementation-readiness-support-transition.html`, + canonical: `${SITE_ORIGIN}/irw/`, type: "article", + redirect: "../irw/", }, { path: "projects/saas-integration-reliability-support-troubleshooting.html", - url: `${SITE_ORIGIN}/projects/saas-integration-reliability-support-troubleshooting.html`, + canonical: `${SITE_ORIGIN}/projects/saas-integration-reliability-support-troubleshooting.html`, type: "article", }, - { path: "404.html", url: `${SITE_ORIGIN}/404.html`, type: "website" }, + { path: "404.html", canonical: `${SITE_ORIGIN}/404.html`, type: "website" }, +]; + +const SITEMAP_URLS = [ + `${SITE_ORIGIN}/`, + `${SITE_ORIGIN}/irw/`, + `${SITE_ORIGIN}/projects/workflow-intake-analysis.html`, + `${SITE_ORIGIN}/projects/saas-integration-reliability-support-troubleshooting.html`, ]; const EXPECTED_STATIC_PATHS = [ @@ -47,6 +58,7 @@ const EXPECTED_STATIC_PATHS = [ "assets/favicon.svg", "assets/social-preview-1200x630.png", "index.html", + "irw/index.html", "projects/implementation-readiness-support-transition.html", "projects/saas-integration-reliability-support-troubleshooting.html", "projects/workflow-intake-analysis.html", @@ -80,6 +92,7 @@ const PUBLIC_INPUT_PATHS = [ "src/.nojekyll", "src/404.html", "src/index.html", + "src/irw/index.html", "src/projects/implementation-readiness-support-transition.html", "src/projects/saas-integration-reliability-support-troubleshooting.html", "src/projects/workflow-intake-analysis.html", @@ -95,7 +108,6 @@ const FORBIDDEN_REVIEW_PHRASES = [ "Read candidate case study", "Repository link withheld", "A local repository candidate exists", - "not yet public", "not authorized for public", "PrivatePublicationCandidateNotYetAuthorized", "LocalCandidateWithheldUntilPublicationAuthorization", @@ -119,13 +131,7 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) for (const path of PUBLIC_INPUT_PATHS) { check(`INPUT_${safeId(path)}`, existsSync(absolute(path)), path); } - check("INPUT_COUNT_EXACT", PUBLIC_INPUT_PATHS.length === 30, "Thirty explicit public inputs."); - check( - "CANDIDATE_AUTHORITIES_REMOVED", - !existsSync(absolute("content/schemas/public-project-candidate-content.schema.json")) && - !existsSync(absolute("scripts/validate-consolidated-candidate.mjs")), - "No parallel candidate schema or candidate validator remains active.", - ); + check("INPUT_COUNT_EXACT", PUBLIC_INPUT_PATHS.length === 31, "Thirty-one explicit public inputs."); const packageJson = json("package.json"); const siteConfig = json("content/site/site-config.json"); @@ -142,7 +148,7 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) packageJson.scripts?.build === "node scripts/build.mjs" && packageJson.scripts?.validate === "npm run validate:public" && packageJson.scripts?.["validate:public"] === "npm run build && node scripts/validate-public.mjs", - "Node 24, deterministic build, preflight default, and fail-closed final validation are configured.", + "Node 24, deterministic build, and fail-closed validation are configured.", ); check("SITE_ORIGIN", siteConfig.site_base_url === SITE_ORIGIN, "Authorized custom-domain origin."); check( @@ -151,7 +157,7 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) schema.oneOf?.length === 2 && schema.$defs?.workflow_analysis_v1 && schema.$defs?.public_case_study_v2, - "One closed published-project schema preserves PORT-0001 and governs PORT-0002/3.", + "One project-content schema governs the three published projects.", ); check( "PORT1_CONTENT_PRESERVED", @@ -159,19 +165,25 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) "6599D5B7FD5ADBEE1A97681BB5ABE4217D34533867C0E7B8A41F4753D9855D00" && port1.title === "Workflow Intake Analysis Demo" && port1.links?.repository_url === PORT1_REPOSITORY, - "The accepted PORT-0001 content record is byte-exact.", + "The accepted Workflow Intake Analysis content record is unchanged.", ); const expectedRepositories = allowRepositoryTokens - ? { "PORT-0002": PORT2_TOKEN, "PORT-0003": PORT3_TOKEN } - : { "PORT-0002": PORT2_REPOSITORY, "PORT-0003": PORT3_REPOSITORY }; + ? { + "PORT-0002": new Set([PORT2_REPOSITORY, PORT2_TOKEN]), + "PORT-0003": new Set([PORT3_REPOSITORY, PORT3_TOKEN]), + } + : { + "PORT-0002": new Set([PORT2_REPOSITORY]), + "PORT-0003": new Set([PORT3_REPOSITORY]), + }; const expectedRecords = [ [ port2, { id: "PORT-0002", title: "Implementation Readiness & Support Transition", - route: "projects/implementation-readiness-support-transition.html", + route: "irw/index.html", repository: "implementation-readiness-support-transition", }, ], @@ -185,8 +197,8 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) }, ], ]; + for (const [record, expected] of expectedRecords) { - const keys = Object.keys(record).sort(); const expectedKeys = [ "$schema", "capabilities", @@ -203,7 +215,11 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) "subtitle", "title", ].sort(); - check(`CONTENT_KEYS_${expected.id}`, equalArrays(keys, expectedKeys), `${expected.id} has only the reviewed published fields.`); + check( + `CONTENT_KEYS_${expected.id}`, + equalArrays(Object.keys(record).sort(), expectedKeys), + `${expected.id} has only the reviewed published fields.`, + ); check( `CONTENT_IDENTITY_${expected.id}`, record.$schema === "../schemas/public-project-content.schema.json" && @@ -212,19 +228,15 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) record.title === expected.title && record.data_class === "Synthetic" && record.publication_state === "PortfolioApproved", - `${expected.id} published content identity.`, + `${expected.id} identity and publication state are correct.`, ); check( `CONTENT_LINKS_${expected.id}`, - equalArrays( - Object.keys(record.links).sort(), - ["case_study_path", "repository_name", "repository_state", "repository_url"].sort(), - ) && - record.links.case_study_path === expected.route && + record.links.case_study_path === expected.route && record.links.repository_name === expected.repository && - record.links.repository_url === expectedRepositories[expected.id] && + expectedRepositories[expected.id].has(record.links.repository_url) && record.links.repository_state === "ExistingPublicRepositoryWithVerifiedV1Release", - `${expected.id} route and repository fields match the ${allowRepositoryTokens ? "bounded URL token" : "verified final URL"} mode.`, + `${expected.id} route and repository identity are correct.`, ); check( `CONTENT_SUBSTANCE_${expected.id}`, @@ -234,29 +246,31 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) record.evidence.length >= 3 && record.capabilities.length >= 4 && record.scope.length >= 2, - `${expected.id} retains reviewed problem, judgment, evidence, capabilities, and scope.`, + `${expected.id} contains substantive problem, judgment, evidence, capability, and scope fields.`, ); check( `CONTENT_BOUNDARY_${expected.id}`, - /synthetic/i.test(JSON.stringify(record.scope)) && - /(not evidence|no real customer|no live platform)/i.test(JSON.stringify(record.scope)), - `${expected.id} retains a clear synthetic and non-production boundary.`, + /synthetic|fictional/i.test(JSON.stringify(record.scope)) && + /not represent|not evidence|no real customer|no live platform/i.test(JSON.stringify(record.scope)), + `${expected.id} keeps a clear fictional and non-production boundary.`, ); } + check( + "PORT2_TWO_LAYER_MODEL", + /platform-neutral/i.test(JSON.stringify(port2)) && + /Jira and Confluence implementation/i.test(JSON.stringify(port2)) && + /Eight final synthetic foundation outcomes/i.test(JSON.stringify(port2)) && + /ten final passing UAT cases/i.test(JSON.stringify(port2)) && + /v1.1 roadmap/i.test(JSON.stringify(port2)), + "The readiness project distinguishes its platform-neutral foundation, Atlassian implementation, and v1.1 roadmap.", + ); const port3All = JSON.stringify(port3); check( "PORT3_N8N_BOUNDARY", /n8n runtime execution was deferred/i.test(port3All) && /rather than evidence of n8n proficiency/i.test(port3All), - "The n8n-deferred/no-proficiency ceiling is exact.", - ); - check( - "PORT2_READINESS_PROOF", - /Eight final synthetic UAT outcomes/.test(JSON.stringify(port2)) && - /Six explicit transition smoke checks/.test(JSON.stringify(port2)) && - /passing retests/.test(JSON.stringify(port2)), - "PORT-0002 retains bounded UAT, retest, smoke-check, rollback, and handoff proof.", + "The integration project keeps the reviewed n8n boundary.", ); check( "PORT3_RELIABILITY_PROOF", @@ -265,7 +279,7 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) /503/.test(port3All) && /dead-letter replay/.test(port3All) && /reconciliation/.test(port3All), - "PORT-0003 retains mapping, retry, dead-letter, replay, and reconciliation proof.", + "The integration project retains mapping, retry, replay, and reconciliation evidence.", ); const activeTextPaths = [ @@ -281,13 +295,29 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) check( "ZERO_REVIEW_STAGE_RESIDUE", residue.length === 0, - residue.length ? residue.join("; ") : "No active reader-facing review-stage residue.", + residue.length ? residue.join("; ") : "No reader-facing review-stage residue.", ); check( "ZERO_LOCAL_PATH_RESIDUE", !/[A-Za-z]:\\\\|file:\/\/|\/Users\/|\/home\//i.test(activeText), - "No absolute local filesystem path in public content or output.", + "No absolute local filesystem path appears in public content.", + ); + check( + "NO_OVERT_AUDIENCE_LANGUAGE", + !/(recruiter-facing|employer-facing|built to prove|proof for employers)/i.test(activeText), + "The public site describes the work directly rather than addressing an application audience.", ); + const refreshedSurfaces = [ + text("src/index.html"), + text("src/irw/index.html"), + text("src/projects/implementation-readiness-support-transition.html"), + ].join("\n"); + check( + "ASCII_DASHES_ON_REFRESHED_SURFACES", + !/[\u2013\u2014]/u.test(refreshedSurfaces), + "The refreshed homepage and IRW routes contain no en dash or em dash.", + ); + const renderedText = [ ...walk(absolute("src")).filter(isTextPath), ...walk(absolute("dist")).filter(isTextPath), @@ -295,29 +325,9 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) check( "NO_CONTROLLED_IDS_IN_RENDERED_SITE", !/PORT-000[123]/.test(renderedText), - "Controlled project IDs remain structured metadata only.", + "Internal project IDs remain structured metadata only.", ); - const tokenCounts = { - port2Content: occurrences(text("content/projects/implementation-readiness-support-transition.json"), PORT2_TOKEN), - port3Content: occurrences(text("content/projects/saas-integration-reliability-support-troubleshooting.json"), PORT3_TOKEN), - port2Source: occurrences(text("src/index.html") + text("src/projects/implementation-readiness-support-transition.html"), PORT2_TOKEN), - port3Source: occurrences(text("src/index.html") + text("src/projects/saas-integration-reliability-support-troubleshooting.html"), PORT3_TOKEN), - port2Dist: occurrences(text("dist/index.html") + text("dist/projects/implementation-readiness-support-transition.html"), PORT2_TOKEN), - port3Dist: occurrences(text("dist/index.html") + text("dist/projects/saas-integration-reliability-support-troubleshooting.html"), PORT3_TOKEN), - }; - const exactPreflightTokens = - tokenCounts.port2Content === 1 && tokenCounts.port3Content === 1 && - tokenCounts.port2Source === 2 && tokenCounts.port3Source === 2 && - tokenCounts.port2Dist === 2 && tokenCounts.port3Dist === 2; - const noRepositoryTokens = Object.values(tokenCounts).every((count) => count === 0); - check( - "REPOSITORY_URL_GATE", - allowRepositoryTokens ? exactPreflightTokens : noRepositoryTokens, - allowRepositoryTokens - ? "Each bounded URL token occurs once in content and twice across source/built home-plus-project surfaces." - : "No repository URL token remains after independently verified URL insertion.", - ); const sourceTokens = uniqueTokens( walk(absolute("src")).filter(isTextPath).map((path) => readFileSync(path, "utf8")).join("\n"), ); @@ -327,13 +337,15 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) const distTokens = uniqueTokens( walk(absolute("dist")).filter(isTextPath).map((path) => readFileSync(path, "utf8")).join("\n"), ); + const tokenSetAllowed = (tokens, allowed) => tokens.every((token) => allowed.has(token)); check( "ONLY_AUTHORIZED_TOKENS", - allowRepositoryTokens - ? equalArrays(sourceTokens, [PORT2_TOKEN, PORT3_TOKEN, "{{SITE_BASE_URL}}"].sort()) && - equalArrays(contentTokens, [PORT2_TOKEN, PORT3_TOKEN].sort()) && - equalArrays(distTokens, [PORT2_TOKEN, PORT3_TOKEN].sort()) - : equalArrays(sourceTokens, ["{{SITE_BASE_URL}}"] ) && contentTokens.length === 0 && distTokens.length === 0, + tokenSetAllowed(sourceTokens, new Set(["{{SITE_BASE_URL}}", PORT2_TOKEN, PORT3_TOKEN])) && + tokenSetAllowed(contentTokens, new Set([PORT2_TOKEN, PORT3_TOKEN])) && + tokenSetAllowed(distTokens, new Set([PORT2_TOKEN, PORT3_TOKEN])) && + (allowRepositoryTokens || (!sourceTokens.includes(PORT2_TOKEN) && !sourceTokens.includes(PORT3_TOKEN) && + !contentTokens.includes(PORT2_TOKEN) && !contentTokens.includes(PORT3_TOKEN) && + !distTokens.includes(PORT2_TOKEN) && !distTokens.includes(PORT3_TOKEN))), `source=${sourceTokens.join(",") || "none"}; content=${contentTokens.join(",") || "none"}; dist=${distTokens.join(",") || "none"}`, ); @@ -344,16 +356,17 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) const builtPaths = walk(absolute("dist")) .map((path) => relative(absolute("dist"), path).replaceAll("\\", "/")) .sort(); - check("STATIC_SOURCE_SET", equalArrays(staticPaths, EXPECTED_STATIC_PATHS), "Eleven exact deployable source files."); - check("BUILD_FILE_SET", equalArrays(builtPaths, EXPECTED_STATIC_PATHS), "Built tree contains the same eleven files."); + check("STATIC_SOURCE_SET", equalArrays(staticPaths, EXPECTED_STATIC_PATHS), "Twelve exact deployable source files."); + check("BUILD_FILE_SET", equalArrays(builtPaths, EXPECTED_STATIC_PATHS), "The built tree contains the same twelve files."); check( "BUILD_MANIFEST_TOPOLOGY", manifest.build_mode === "DeterministicThreeProjectSiteBaseUrlGeneration" && manifest.site_base_url === SITE_ORIGIN && - manifest.file_count === 11 && + manifest.file_count === 12 && equalArrays((manifest.entries || []).map((item) => item.relative_path).sort(), EXPECTED_STATIC_PATHS), - "Build manifest records the exact deterministic topology.", + "The build manifest records the exact deterministic topology.", ); + const manifestByPath = new Map((manifest.entries || []).map((item) => [item.relative_path, item])); const generatedHtml = new Set(ROUTES.map((route) => route.path)); for (const path of EXPECTED_STATIC_PATHS) { @@ -373,7 +386,7 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) check( `BUILD_HASH_${safeId(path)}`, entry?.size_bytes === builtBytes.length && entry?.sha256 === sha256(builtBytes), - `${path} matches its build-manifest identity.`, + `${path} matches the build manifest.`, ); } @@ -385,13 +398,13 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) //.test(html) && //.test(html) && - html.includes(``) && + html.includes(``) && html.includes(``) && - html.includes(``) && + html.includes(``) && html.includes(``) && //.test(html) && / home.includes(value)) && + home.includes("Workflow Intake Analysis Demo") && + home.includes("Implementation Readiness and Support Transition") && + home.includes("SaaS Integration Reliability and Support Troubleshooting") && occurrences(home, "Read case study") === 3 && - occurrences(home, "View repository") === 3, - "Homepage exposes three distinct case studies and repository paths.", + occurrences(home, "View repository") === 2 && + occurrences(home, "View foundation repository") === 1, + "The homepage retains three projects and distinct repository links.", + ); + check( + "HOME_IRW_CANONICAL_LINK", + home.includes('href="irw/index.html"') && !home.includes('href="projects/implementation-readiness-support-transition.html">Read case study'), + "The readiness project card uses the canonical IRW route.", ); check( - "ALL_PROJECT_NAVIGATION", - p1Page.includes("implementation-readiness-support-transition.html") && - p1Page.includes("saas-integration-reliability-support-troubleshooting.html") && - p2Page.includes("workflow-intake-analysis.html") && - p2Page.includes("saas-integration-reliability-support-troubleshooting.html") && - p3Page.includes("workflow-intake-analysis.html") && - p3Page.includes("implementation-readiness-support-transition.html"), - "Each project page links to the other two projects.", + "IRW_TWO_LAYER_NARRATIVE", + /platform-neutral implementation-readiness model/i.test(irw) && + /working Jira and Confluence workspace/i.test(irw) && + /original eight validation cases/i.test(irw) && + /ten IRW cases/i.test(irw) && + /IRW-76.*blocks IRW-75/is.test(irw), + "The IRW page explains both layers, the separate validation sets, and the current dependency.", ); check( - "PORT2_VISIBLE_BOUNDARY", - /Modeled lifecycle, not a live transaction/.test(p2Page) && - /Eight synthetic UAT cases/.test(p2Page) && - /Passing retests/.test(p2Page) && - /six modeled smoke checks/i.test(p2Page) && - /rollback/i.test(p2Page) && - /support-transition thinking/i.test(p2Page), - "PORT-0002 page keeps its lifecycle, readiness, retest, rollback, and handoff boundary.", + "IRW_HUMAN_OWNERSHIP", + /I owned the analysis, decisions, validation, and closeout/i.test(irw) && + /automation for repetitive setup and consistency checking/i.test(irw) && + /responsibility for the decisions and results/i.test(irw), + "The IRW page explains Tyler's ownership without hiding tool assistance.", + ); + check( + "IRW_SCOPE_BOUNDARY", + /fictional implementation/i.test(irw) && + /does not represent customer work/i.test(irw) && + /No source, app identity, build, deployment, installation, or runtime result is claimed yet/i.test(irw), + "The IRW page distinguishes completed core work from customer work and unfinished Forge delivery.", + ); + check( + "PROJECT_NAVIGATION", + p1.includes("implementation-readiness-support-transition.html") && + p1.includes("saas-integration-reliability-support-troubleshooting.html") && + irw.includes("workflow-intake-analysis.html") && + irw.includes("saas-integration-reliability-support-troubleshooting.html") && + p3.includes("workflow-intake-analysis.html") && + p3.includes("implementation-readiness-support-transition.html") && + p2Redirect.includes("../irw/"), + "Each project remains connected, and legacy readiness links resolve through the redirect.", ); check( "PORT3_VISIBLE_BOUNDARY", - /No external service or live endpoint/.test(p3Page) && - /Twelve scenarios/.test(p3Page) && - /Dead letter and replay/i.test(p3Page) && - /n8n execution was deferred/.test(p3Page) && - /does not establish n8n proficiency/.test(p3Page), - "PORT-0003 page keeps executable evidence and the exact n8n ceiling.", + /No external service or live endpoint/.test(p3) && + /Twelve scenarios/.test(p3) && + /Dead letter and replay/i.test(p3) && + /n8n execution was deferred/.test(p3) && + /does not establish n8n proficiency/.test(p3), + "The integration page retains its reviewed execution and n8n boundaries.", ); const robots = text("dist/robots.txt"); const sitemap = text("dist/sitemap.xml"); - const sitemapUrls = ROUTES.filter((route) => route.path !== "404.html").map((route) => route.url); check( "ROBOTS_PUBLIC", robots === `User-agent: *\nAllow: /\n\nSitemap: ${SITE_ORIGIN}/sitemap.xml\n`, - "Public crawl and sitemap declaration.", + "Public crawl and sitemap declaration are correct.", ); check( - "SITEMAP_FOUR_ROUTES", - occurrences(sitemap, "") === 4 && - sitemapUrls.every((url) => sitemap.includes(`${url}`)), - "Sitemap contains exactly the homepage and three project routes.", + "SITEMAP_CANONICAL_ROUTES", + occurrences(sitemap, "") === SITEMAP_URLS.length && + SITEMAP_URLS.every((url) => sitemap.includes(`${url}`)) && + !sitemap.includes("implementation-readiness-support-transition.html"), + "The sitemap contains the homepage, canonical IRW route, and two other project routes.", ); + const css = text("dist/styles.css"); check( "CSS_ACCESSIBILITY", @@ -474,8 +515,8 @@ export function runPublicationValidation({ allowRepositoryTokens = false } = {}) ); check( "NO_ACTIVE_CODE_SURFACE", - !/ existsSync(absolute(path))).map((path) => { @@ -526,6 +564,7 @@ function validateLinks(pagePath, html, allowRepositoryTokens, check) { PORT3_REPOSITORY, PROFILE_URL, LINKEDIN_URL, + IRW_ATLASSIAN_URL, ]); const idsByPath = new Map( ROUTES.map((route) => { @@ -535,6 +574,7 @@ function validateLinks(pagePath, html, allowRepositoryTokens, check) { ); let valid = true; const failures = []; + for (const href of hrefs) { if (href === PORT2_TOKEN || href === PORT3_TOKEN) { if (!allowRepositoryTokens) { @@ -544,7 +584,7 @@ function validateLinks(pagePath, html, allowRepositoryTokens, check) { continue; } if (href.startsWith("https://")) { - const allowedCanonical = ROUTES.some((route) => route.url === href); + const allowedCanonical = ROUTES.some((route) => route.canonical === href); const allowedSocial = href === `${SITE_ORIGIN}/assets/social-preview-1200x630.png`; if (!allowedExternal.has(href) && !allowedCanonical && !allowedSocial) { valid = false; @@ -557,10 +597,12 @@ function validateLinks(pagePath, html, allowRepositoryTokens, check) { failures.push(`prohibited scheme ${href}`); continue; } + const [targetPart, fragment] = href.split("#", 2); - const targetPath = targetPart + let targetPath = targetPart ? posix.normalize(posix.join(posix.dirname(pagePath), targetPart)) : pagePath; + if (targetPath.endsWith("/")) targetPath = `${targetPath}index.html`; if (!existsSync(join(projectRoot, "dist", ...targetPath.split("/")))) { valid = false; failures.push(`missing ${href}`); @@ -571,6 +613,7 @@ function validateLinks(pagePath, html, allowRepositoryTokens, check) { failures.push(`missing fragment ${href}`); } } + check( `LINKS_${safeId(pagePath)}`, valid, @@ -579,11 +622,10 @@ function validateLinks(pagePath, html, allowRepositoryTokens, check) { } function renderSitemap() { - const sitemapRoutes = ROUTES.filter((route) => route.path !== "404.html").map((route) => route.url); return [ '', '', - ...sitemapRoutes.flatMap((url) => [" ", ` ${url}`, " "]), + ...SITEMAP_URLS.flatMap((url) => [" ", ` ${url}`, " "]), "", "", ].join("\n"); From 2987f83f3aa742c57dda8e45b5115f370823ffe5 Mon Sep 17 00:00:00 2001 From: Tyler Windes <66438824+Tyler-Windes@users.noreply.github.com> Date: Thu, 3 Sep 2026 15:54:20 -0600 Subject: [PATCH 8/8] Align the repository documentation with the canonical IRW route and two-layer project model --- README.md | 67 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index c736a81..13915cc 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,30 @@ -# Tyler Windes Portfolio — Three-Project Publication Source +# Tyler Windes Portfolio - Three Project Site -Source for [tyler-windes.com](https://tyler-windes.com/), the public narrative layer for three distinct technical and implementation work samples. The GitHub Pages hosting repository remains `Tyler-Windes/Tyler-Windes.github.io`; that repository identity is distinct from the public website identity. +Source for [tyler-windes.com](https://tyler-windes.com/), a static site that brings three related work samples into one consistent project path. -This static-site source brings three distinct work samples into one recruiter-facing portfolio: +The site presents: -- **Workflow Intake Analysis Demo** — workflow analysis, data validation, Python, SQL, API contracts, testing, and traceability; -- **Implementation Readiness & Support Transition** — requirements, readiness, synthetic UAT, retest judgment, rollback, enablement, and support handoff; and -- **SaaS Integration Reliability & Support Troubleshooting** — local API contracts, mapping, idempotency, retry, dead letter, replay, reconciliation, and operator troubleshooting. +- **Workflow Intake Analysis Demo** - workflow analysis, data validation, Python, SQL, API contracts, testing, and traceability +- **Implementation Readiness and Support Transition** - a platform-neutral foundation connected to the IRW Jira and Confluence implementation, including requirements, UAT, Bug correction, readiness, rollback, and handoff +- **SaaS Integration Reliability and Support Troubleshooting** - local API contracts, mapping, idempotency, retry, dead letter, replay, reconciliation, and troubleshooting -All project data and scenarios are synthetic. The site does not claim client work, employer implementation, production operation, real UAT, real go-live, measured outcomes, or n8n proficiency. +All project data and scenarios are fictional. The site does not claim customer work, production deployment, measured outcomes, or tools that were not actually implemented and tested. -## Verified project repositories +## Canonical project routes -The published project pages link to the verified public repositories: +- `https://tyler-windes.com/projects/workflow-intake-analysis.html` +- `https://tyler-windes.com/irw/` +- `https://tyler-windes.com/projects/saas-integration-reliability-support-troubleshooting.html` +The previous implementation-readiness route remains as a redirect to `/irw/` so existing links continue to work. + +## Project repositories + +- `https://github.com/Tyler-Windes/workflow-intake-analysis-demo` - `https://github.com/Tyler-Windes/implementation-readiness-support-transition` - `https://github.com/Tyler-Windes/saas-integration-reliability-support-troubleshooting` -`npm run validate` performs the complete public-source gate and fails closed if either repository URL is missing or if an unresolved publication token remains. +The implementation-readiness repository contains the platform-neutral foundation. The live IRW Jira and Confluence workspace is the Atlassian implementation layer of the same project area. The foundation uses eight synthetic validation cases; IRW uses a separate ten-requirement and ten-test model. ## Local use @@ -31,35 +38,43 @@ npm run dev The build copies committed static source and assets to `dist`, resolves `{{SITE_BASE_URL}}` from `content/site/site-config.json`, generates `robots.txt` and `sitemap.xml`, and writes a deterministic manifest to `validation/build-manifest.json`. -## Content contracts +## Content and validation -`content/schemas/public-project-content.schema.json` is the shared project-content contract. Version 2 preserves the existing Workflow Intake Analysis content shape and adds the published case-study shape used by the readiness and integration projects. Their project IDs and exact published-state vocabulary remain structured metadata and are not rendered in the employer-facing pages. +`content/schemas/public-project-content.schema.json` is the shared project-content contract. The validation scripts check: -Education remains controlled by `content/site/education.json` and `content/schemas/public-education-content.schema.json`. It distinguishes the completed University of Denver technical-training program from degrees and preserves Colorado State University and the University of Northern Colorado as coursework only. +- The exact public input and build file sets +- Canonical URLs and social metadata +- Internal and approved external links +- The three-project homepage structure +- The two-layer implementation-readiness narrative +- The canonical `/irw/` route and legacy redirect +- Fictional and non-production scope boundaries +- Accessible page structure +- Deterministic build parity and file hashes +- Absence of local paths, unresolved tokens, and review-stage residue -## Site address authority +## Site address -`content/site/site-config.json` is the committed authority for the employer-facing base URL. The build derives canonical URLs, `og:url`, absolute social-preview URLs, robots, and sitemap entries from `site_base_url`. The current value is `https://tyler-windes.com`. +`content/site/site-config.json` controls the public base URL. The current value is `https://tyler-windes.com`. -For any later separately authorized domain move, change only `site_base_url`, then run the full validation, deployment, redirect, and signed-out readback gates. DNS, Cloudflare, and GitHub Pages settings remain separate infrastructure actions. +For a later domain move, change only `site_base_url`, then run the full validation, deployment, redirect, and signed-out review process. DNS, Cloudflare, and GitHub Pages settings remain separate infrastructure actions. ## Deployment -GitHub Pages deploys only from validated pushes to `main`. Pull requests run the same public validation without deploying. The workflow uses least-privilege job permissions, the `github-pages` environment, deployment concurrency, and immutable action commit pins. +GitHub Pages deploys only from validated pushes to `main`. Pull requests run the same public validation without deploying. The workflow uses least-privilege permissions, the `github-pages` environment, deployment concurrency, and immutable action commit pins. + +## Current roadmap + +The IRW core v1.0 work is complete. The next phase contains: -Action pins reviewed on 2026-08-13: +- Jira saved filters and a small status dashboard +- A read-only Forge readiness component -| Action | Reviewed release | Commit SHA | -| --- | --- | --- | -| `actions/checkout` | `v7.0.1` | `3d3c42e5aac5ba805825da76410c181273ba90b1` | -| `actions/setup-node` | `v7.0.0` | `820762786026740c76f36085b0efc47a31fe5020` | -| `actions/configure-pages` | `v6.0.0` | `45bfe0192ca1faeb007ade9deae92b16b8254a0d` | -| `actions/upload-pages-artifact` | `v5.0.0` | `fc324d3547104276b827a68afc52ff2a11cc49c9` | -| `actions/deploy-pages` | `v5.0.0` | `cd2ce8fcbc39b97be8ca5fce6e763baed58fa128` | +The Forge design is complete, and the certification path and hands-on preparation are in progress. No Forge source, app identity, build, deployment, installation, or runtime result is claimed yet. ## Scope -This repository controls the static site source. Deployment, DNS, Cloudflare, profiles, Job Search, résumés, email, and messaging remain separately governed surfaces. +This repository controls the static site source. Jira and Confluence configuration, DNS, Cloudflare, LinkedIn, resumes, email, and other career materials remain separately managed. ## License