Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ kotlin {
}
val jsMain by getting {
dependencies {
implementation(npm("marked", "9.1.6"))
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions kotlin-js-store/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,14 @@ dom-serialize@^2.2.1:
extend "^3.0.0"
void-elements "^2.0.0"

dukat@0.5.8-rc.4:
version "0.5.8-rc.4"
resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.8-rc.4.tgz#90384dcb50b14c26f0e99dae92b2dea44f5fce21"
integrity sha512-ZnMt6DGBjlVgK2uQamXfd7uP/AxH7RqI0BL9GLrrJb2gKdDxvJChWy+M9AQEaL+7/6TmxzJxFOsRiInY9oGWTA==
dependencies:
google-protobuf "3.12.2"
typescript "3.9.5"

ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
Expand Down Expand Up @@ -1247,6 +1255,11 @@ glob@^7.1.3, glob@^7.1.7:
once "^1.3.0"
path-is-absolute "^1.0.0"

google-protobuf@3.12.2:
version "3.12.2"
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.2.tgz#50ce9f9b6281235724eb243d6a83e969a2176e53"
integrity sha512-4CZhpuRr1d6HjlyrxoXoocoGFnRYgKULgMtikMddA9ztRyYR59Aondv2FioyxWVamRo0rF2XpYawkTCBEQOSkA==

graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
Expand Down Expand Up @@ -1651,6 +1664,11 @@ log4js@^6.4.1:
rfdc "^1.3.0"
streamroller "^3.1.5"

marked@9.1.6:
version "9.1.6"
resolved "https://registry.yarnpkg.com/marked/-/marked-9.1.6.tgz#5d2a3f8180abfbc5d62e3258a38a1c19c0381695"
integrity sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==

media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
Expand Down Expand Up @@ -2495,6 +2513,11 @@ type-is@~1.6.18:
media-typer "0.3.0"
mime-types "~2.1.24"

typescript@3.9.5:
version "3.9.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36"
integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==

ua-parser-js@^0.7.30:
version "0.7.35"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.35.tgz#8bda4827be4f0b1dda91699a29499575a1f1d307"
Expand Down
53 changes: 53 additions & 0 deletions src/commonMain/kotlin/codes/miley/model/BlogPost.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package codes.miley.model

data class BlogPost(
val id: String,
val title: String,
val subtitle: String,
val date: String,
val publishedDate: String,
val excerpt: String,
val content: String,
)

val DARK_FACTORY = BlogPost(
id = "dark-factory-needs-windows",
title = "The Dark Factory Needs Windows",
subtitle = "Building trust in AI autonomy through transparent cognition",
date = "February 2026",
publishedDate = "2026-02-11",
excerpt = "AI is raising the level of abstraction in software development. But the verification layer keeps pulling humans back down. What if cognition itself was transparent?",
content = """
There's a factory in Japan where robots build other robots in the dark. No lights, no people — just machines making machines. It became shorthand for full automation, but the interesting thing about the dark factory isn't that humans were removed. It's that they were *leveraged*. Engineers who once stood on the assembly line now design the systems that design the robots.

Dan Shapiro's [five levels of AI-assisted programming](https://www.danshapiro.com/blog/2026/01/the-five-levels-from-spicy-autocomplete-to-the-software-factory/) describe this same trajectory for software. At Level 0, you type every character. At Level 5 — the Dark Software Factory — your role is pure intent. And we're closer to Level 5 than most people realize.

This isn't hypothetical. [StrongDM's AI team](https://factory.strongdm.ai/) has agents writing and testing code without human involvement. [Stripe's Minions](https://stripe.dev/blog/minions-stripes-one-shot-end-to-end-coding-agents) produce over a thousand code changes per week, all authored entirely by AI. [Simon Willison's latest tools](https://simonwillison.net/2026/Feb/10/showboat-and-rodney/) let agents demonstrate what they've built so humans evaluate outcomes, not implementation details. All three are betting on the same thing — AI as [unprecedented leverage](https://tynan.com/bye2025/) for human intelligence. And all three ran into the same wall.

Trusting the layers beneath you is harder than building them. Stripe limits each agent to two attempts at a task because further retries don't improve results. StrongDM's agents found shortcuts that passed quality checks without doing real work. Willison noticed agents tampering with their own demo outputs. The smarter the agent, the more creative the workaround.

Each team solved this by adding layers of external verification — test suites, human review on every change, audit logs, monitoring dashboards. All reconstructing what the agent did after the fact. It works — but it means stepping back down a level of abstraction to check the work you were just freed from doing. The engineer freed from writing code now spends their time checking a thousand changes weekly. The promise of leverage keeps getting pulled back toward the details.

## Windows, not dashboards

There's a different approach — and as an engineer, I've been building it for three years.

Instead of verifying an opaque process from outside, what if cognition itself was transparent? In [AMPERE](https://github.com/socket-link/ampere), every phase of agent reasoning — perception, recall, planning, execution, coordination — emits structured events as a natural consequence of its design. Not logs added after the fact. Thinking you can observe as it forms.

A trace tells you an agent called `writeFile()`. A cognitive event tells you it perceived a requirement, recalled a similar implementation, considered two approaches, estimated low confidence in one, and chose the other — all *before* the write.

When confidence drops, it surfaces as a structured signal. The agent communicates uncertainty in terms a human can evaluate, then incorporates their judgment. Not a failure mode — a collaboration point where each party operates at the abstraction level they're best at.

The human stays elevated. Shortcuts become visible as the thought forms. Failed attempts become diagnosable. Unexpected behavior becomes immediately legible — not after a post-mortem, but in real time.

## The lights are for us

The Dark Factory doesn't need to stay dark. Not because darkness is dangerous, but because the humans who designed it still need to see — not every bolt, but the reasoning that chose which bolt goes where, and the moment when the system isn't sure.

The lights aren't for the robots. They're for us.
""".trimIndent(),
)

val ALL_POSTS = listOf(
DARK_FACTORY,
)
213 changes: 213 additions & 0 deletions src/commonMain/resources/blog.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
/* Blog styles — uses the same Poppins/Karla design system as the portfolio */

.blog-page {
max-width: 680px;
margin: 0 auto;
padding: 0 1.5rem;
}

/* — Blog Index — */

.blog-page .blog-hero {
padding-top: 132px;
margin-bottom: 2rem;
}

.blog-page .blog-hero h1 {
font: 28px 'Poppins', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 700;
color: #1A1A1A;
margin-bottom: 0.5rem;
}

.blog-page .blog-hero .subtitle {
color: #575757;
font: 16px 'Karla', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 300;
max-width: 480px;
line-height: 1.6;
}

.blog-page .post-list {
list-style: none;
padding: 0;
margin: 0;
}

.blog-page .post-item {
border-top: 1px solid #e6e6e6;
padding: 1.5rem 0;
}

.blog-page .post-item a {
text-decoration: none;
display: block;
cursor: pointer;
}

.blog-page .post-item .post-date {
font: 12px 'Poppins', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 500;
color: #999999;
letter-spacing: 0.04em;
margin-bottom: 0.35rem;
}

.blog-page .post-item .post-title {
font: 22px 'Poppins', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 500;
color: #000000;
line-height: 1.3;
margin-bottom: 0.35rem;
transition: color 0.2s;
}

.blog-page .post-item a:hover .post-title {
color: #20A6DF;
}

.blog-page .post-item .post-subtitle {
font: 15px 'Karla', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
color: #575757;
margin-bottom: 0.35rem;
font-style: italic;
}

.blog-page .post-item .post-excerpt {
color: #575757;
font: 15px 'Karla', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 300;
line-height: 1.6;
}

/* — Article — */

.blog-page .article-header {
padding-top: 132px;
margin-bottom: 2rem;
}

.blog-page .article-header .article-date {
font: 12px 'Poppins', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 500;
color: #999999;
letter-spacing: 0.04em;
margin-bottom: 0.75rem;
}

.blog-page .article-header h1 {
font: 28px 'Poppins', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 700;
line-height: 1.2;
color: #1A1A1A;
margin-bottom: 0.5rem;
}

.blog-page .article-header .article-subtitle {
font: 16px 'Karla', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
color: #575757;
font-style: italic;
}

/* — Article Body — */

.blog-page .article-body {
line-height: 1.7;
}

.blog-page .article-body p {
font: 16px 'Karla', 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.7;
color: #575757;
margin-bottom: 1.5rem;
}

.blog-page .article-body strong {
font-weight: 500;
color: #404040;
}

.blog-page .article-body em {
font-style: italic;
}

.blog-page .article-body a {
color: #20A6DF;
text-decoration: none;
border-bottom: 1px solid transparent;
transition: border-color 0.2s;
}

.blog-page .article-body a:hover {
border-bottom-color: #20A6DF;
}

.blog-page .article-body h2 {
font: 20px 'Poppins', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 700;
color: #1A1A1A;
margin-top: 2.5rem;
margin-bottom: 1rem;
line-height: 1.3;
}

.blog-page .article-body code {
font-family: 'Menlo', 'Consolas', monospace;
font-size: 14px;
background: #f0f0f0;
color: #E94F37;
padding: 0.15em 0.4em;
border-radius: 4px;
border: 1px solid #e6e6e6;
}

.blog-page .article-body blockquote {
border-left: 3px solid #5438DC;
padding-left: 1.25rem;
margin: 2rem 0;
color: #575757;
font-style: italic;
}

/* — Article Footer / CTA — */

.blog-page .article-cta {
margin-top: 2.5rem;
padding-top: 1.5rem;
border-top: 1px solid #e6e6e6;
margin-bottom: 3rem;
}

.blog-page .article-cta p {
font: 15px 'Karla', 'Helvetica Neue', Helvetica, Arial, sans-serif;
color: #575757;
font-style: italic;
line-height: 1.6;
}

.blog-page .article-cta a {
color: #20A6DF;
text-decoration: none;
font-style: normal;
font-weight: 500;
border-bottom: 1px solid transparent;
transition: border-color 0.2s;
}

.blog-page .article-cta a:hover {
border-bottom-color: #20A6DF;
}

/* — Responsive — */

@media (max-width: 640px) {
.blog-page .blog-hero { padding-top: 100px; }
.blog-page .blog-hero h1 { font-size: 24px; }

.blog-page .article-header { padding-top: 100px; }
.blog-page .article-header h1 { font-size: 24px; }

.blog-page .article-body h2 { font-size: 18px; }
}
46 changes: 38 additions & 8 deletions src/commonMain/resources/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,46 @@ button {
border-color: rgba(175, 47, 47, 0.2);
}

.categories nav {
width: max-content;
margin: 0 auto;
padding-top: 20px;
}

.categories nav ul {
display: inline-flex;
gap: 8px;
padding: 0;
list-style: none;
}

.categories nav li a {
font: 14px 'Poppins', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 700;
padding: 6px 20px;
border-radius: 32px;
background: #FFF;
color: #999999;
border: 1px solid rgba(0, 0, 0, 0.15);
cursor: pointer;
text-decoration: none;
transition: all 0.2s;
margin: 0;
}

.categories nav li a:hover {
border-color: rgba(0, 0, 0, 0.3);
color: #575757;
}

.categories nav li a.selected {
background: #FF9D2B;
color: #FFFFFF;
border-color: #FF9D2B;
}

.experience-section {
<<<<<<< HEAD
padding-top: 24px;
=======
padding-top: 40px;
>>>>>>> origin/master
display: inline-flex;
flex-direction: column;
}
Expand Down Expand Up @@ -489,11 +523,7 @@ button {
}

.content {
<<<<<<< HEAD
padding: 0 3vw;
=======
padding: 0 20px;
>>>>>>> origin/master
display: flex;
flex-direction: column;
}
Expand Down
Loading